my procedure is supposed to change 2 values but when i call it it shows the same values entered
code
CREATE OR REPLACE PROCEDURE commande_remise(pourcentage_rem IN Decimal,
c_client IN commande.code_client%type,
c_reg IN commande.reglement%type,
c_montantht IN OUT commande.montant_ht%type,
c_montantttc IN OUT commande.montant_ttc%type)
IS
c_ref commande.ref_commande%type;
BEGIN
SELECT COUNT(ref_commande) INTO c_ref FROM commande;
c_ref := c_ref + 1;
c_montantht := c_montantht-c_montantht*pourcentage_rem;
c_montantttc := c_montantttc-c_montantttc*pourcentage_rem;
INSERT INTO commande(ref_commande, code_client, reglement, montant_ht, montant_ttc)
VALUES(c_ref, c_client, c_reg, c_montantht, c_montantttc);
COMMIT;
END commande_remise;
/
procedure call
DECLARE
c_remise DECIMAL :=0.2;
c_code commande.code_client%type :=2;
c_reglement commande.reglement%type :='oui';
c_montantht commande.montant_ht%type :=3080.12;
c_montantttc commande.montant_ttc%type :=3530.56;
c_com commande%rowtype;
CURSOR c_cur IS SELECT ref_commande, code_client, reglement, montant_ht, montant_ttc FROM commande;
BEGIN
commande_remise(c_remise, c_code, c_reglement, c_montantht, c_montantttc);
OPEN c_cur;
LOOP
FETCH c_cur INTO c_com;
exit when c_cur%notfound;
dbms_output.put_line(c_com.ref_commande || ' ' || c_com.code_client || ' ' || c_com.reglement || ' ' || c_com.montant_ht || ' ' || c_com.montant_ttc);
END LOOP;
CLOSE c_cur;
END;
/
the values are c_montantht and c_montantttc
the result is the third:, please help.
Works for me (I'll tell you a secret later).
Table first:
SQL> create table commande
2 (ref_commande number,
3 code_client number,
4 reglement varchar2(10),
5 montant_ht number,
6 montant_ttc number);
Table created.
SQL>
Procedure:
SQL> CREATE OR REPLACE PROCEDURE commande_remise
2 (pourcentage_rem IN NUMBER,
3 c_client IN commande.code_client%type,
4 c_reg IN commande.reglement%type,
5 c_montantht IN OUT commande.montant_ht%type,
6 c_montantttc IN OUT commande.montant_ttc%type)
7 IS
8 c_ref commande.ref_commande%type;
9 BEGIN
10 SELECT COUNT(ref_commande) INTO c_ref FROM commande;
11 c_ref := c_ref + 1;
12 dbms_output.put_line('pourcentage_rem = ' || pourcentage_rem);
13 c_montantht := c_montantht - c_montantht * pourcentage_rem;
14 c_montantttc := c_montantttc - c_montantttc * pourcentage_rem;
15
16 INSERT INTO commande
17 (ref_commande, code_client, reglement, montant_ht, montant_ttc)
18 VALUES
19 (c_ref, c_client, c_reg, c_montantht, c_montantttc);
20 END commande_remise;
21 /
Procedure created.
SQL>
Anonymous PL/SQL block:
SQL> set serveroutput on;
SQL> DECLARE
2 c_remise NUMBER :=0.2;
3 c_code commande.code_client%type :=2;
4 c_reglement commande.reglement%type :='oui';
5 c_montantht commande.montant_ht%type :=3080.12;
6 c_montantttc commande.montant_ttc%type :=3530.56;
7 c_com commande%rowtype;
8 CURSOR c_cur IS SELECT ref_commande, code_client, reglement, montant_ht, montant_ttc FROM commande;
9 BEGIN
10 commande_remise(c_remise, c_code, c_reglement, c_montantht, c_montantttc);
11 OPEN c_cur;
12 LOOP
13 FETCH c_cur INTO c_com;
14 exit when c_cur%notfound;
15 dbms_output.put_line(c_com.ref_commande || ' ' || c_com.code_client
16 || ' ' || c_com.reglement || ' ' || c_com.montant_ht
17 || ' ' || c_com.montant_ttc);
18 END LOOP;
19 CLOSE c_cur;
20 END;
21 /
pourcentage_rem = ,2
1 2 oui 2464,096 2824,448
PL/SQL procedure successfully completed.
SQL>
Table contents:
SQL> select * From commande;
REF_COMMANDE CODE_CLIENT REGLEMENT MONTANT_HT MONTANT_TTC
------------ ----------- ---------- ---------- -----------
1 2 oui 2464,096 2824,448
SQL>
Looks OK, right?
The secret: don't use DECIMAL in
procedure's parameter declaration: pourcentage_rem IN Decimal
anonymous PL/SQL block's variable declaration: c_remise DECIMAL :=0.2;
Use NUMBER instead. Because, if you use DECIMAL, then procedure's line #12 displays
pourcentage_rem = 0
so - when you subtract something that is multiplied by zero, you subtract zero and get the input value itself.
Related
CREATE TABLE test_table
(
col1 NUMBER(10),
col2 NUMBER(10)
);
INSERT INTO test_table
VALUES (1, 2);
I am writing a stored procedure wherein if I give a table name as an input, that should give me the table data and column details.
For example:
SELECT *
FROM <input_table_name>;
But this causes an error that the SQL command has not ended properly even though I have taken care of this.
My attempt:
CREATE OR REPLACE PROCEDURE sp_test(iv_table_name IN VARCHAR2,
p_out_cur OUT SYS_REFCURSOR)
AS
lv_str VARCHAR2(400);
lv_count NUMBER(1);
lv_table_name VARCHAR2(255):=UPPER(iv_table_name);
BEGIN
lv_str := 'SELECT * FROM '||lv_table_name;
SELECT COUNT(1) INTO lv_count FROM all_tables WHERE table_name = lv_table_name;
IF lv_count = 0 THEN
dbms_output.put_line('Table does not exist');
ELSE
OPEN p_out_cur FOR lv_str;
END IF;
END sp_test;
Tool used: SQL developer(18c)
In dynamic SQL, you do NOT terminate statement with a semicolon.
EXECUTE IMMEDIATE 'SELECT * FROM '||lv_table_name||';';
-----
remove this
Anyway, you won't get any result when you run that piece of code. If you really want to see table's contents, you'll have to switch to something else, e.g. create a function that returns ref cursor.
Sample data:
SQL> SELECT * FROM test_table;
COL1 COL2
---------- ----------
1 2
3 4
Procedure you wrote is now correct:
SQL> CREATE OR REPLACE PROCEDURE sp_test (iv_table_name IN VARCHAR2,
2 p_out_cur OUT SYS_REFCURSOR)
3 AS
4 lv_str VARCHAR2 (400);
5 lv_count NUMBER (1);
6 lv_table_name VARCHAR2 (255) := UPPER (iv_table_name);
7 BEGIN
8 lv_str := 'SELECT * FROM ' || lv_table_name;
9
10 SELECT COUNT (1)
11 INTO lv_count
12 FROM all_tables
13 WHERE table_name = lv_table_name;
14
15 IF lv_count = 0
16 THEN
17 DBMS_OUTPUT.put_line ('Table does not exist');
18 ELSE
19 OPEN p_out_cur FOR lv_str;
20 END IF;
21 END sp_test;
22 /
Procedure created.
Testing:
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 l_rc SYS_REFCURSOR;
3 l_col1 NUMBER (10);
4 l_col2 NUMBER (10);
5 BEGIN
6 sp_test ('TEST_TABLE', l_rc);
7
8 LOOP
9 FETCH l_rc INTO l_col1, l_col2;
10
11 EXIT WHEN l_rc%NOTFOUND;
12
13 DBMS_OUTPUT.put_line (l_col1 || ', ' || l_col2);
14 END LOOP;
15 END;
16 /
1, 2 --> contents of the
3, 4 --> TEST_TABLE
PL/SQL procedure successfully completed.
SQL>
A function (instead of a procedure with the OUT parameter):
SQL> CREATE OR REPLACE FUNCTION sf_test (iv_table_name IN VARCHAR2)
2 RETURN SYS_REFCURSOR
3 AS
4 lv_str VARCHAR2 (400);
5 lv_count NUMBER (1);
6 lv_table_name VARCHAR2 (255) := UPPER (iv_table_name);
7 l_rc SYS_REFCURSOR;
8 BEGIN
9 lv_str := 'SELECT * FROM ' || lv_table_name;
10
11 SELECT COUNT (1)
12 INTO lv_count
13 FROM all_tables
14 WHERE table_name = lv_table_name;
15
16 IF lv_count = 0
17 THEN
18 raise_application_error (-20000, 'Table does not exist');
19 ELSE
20 OPEN l_rc FOR lv_str;
21 END IF;
22
23 RETURN l_rc;
24 END sf_test;
25 /
Function created.
Testing:
SQL> SELECT sf_test ('liksajfla') FROM DUAL;
SELECT sf_test ('liksajfla') FROM DUAL
*
ERROR at line 1:
ORA-20000: Table does not exist
ORA-06512: at "SCOTT.SF_TEST", line 18
SQL> SELECT sf_test ('TEST_TABLE') FROM DUAL;
SF_TEST('TEST_TABLE'
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
COL1 COL2
---------- ----------
1 2
3 4
SQL>
create or replace type pb_calculate_bill_ot as object ( bill id number(9),
version number(2),
rate number(5),
descp varchar2(25)
);
create or replace type pb_calculate_bill_ct is table of pb_calculate_bill_ot;
----- inside a package -----
procedure select_price ( pi_bill id in number,
pi_version in number,
po_data_ct out pb_calculate_bill_ct) IS
lt_calculate_bill_ct pb_calculate_bill_ct := pb_calculate_bill_ct();
-- procedure functionality--
end select_price;
--------- calling this proc inside same pkg ----------
pkg.select_price ( pi_bill_id => pi_bill,
pi_version => pi_version,
po_data_ct => lt_calculate_bill_ct);
how to take dbms_output of lt_calculate_bill_ct ???
Here's an example.
Sample table:
SQL> CREATE TABLE bill
2 AS
3 SELECT 1 bill_id, 20 version, 1234 rate, 'Little' descp FROM DUAL
4 UNION ALL
5 SELECT 2, 13, 434, 'Foot' FROM DUAL;
Table created.
Types you created:
SQL> CREATE OR REPLACE TYPE pb_calculate_bill_ot AS OBJECT
2 (
3 bill_id NUMBER (9),
4 version NUMBER (2),
5 rate NUMBER (5),
6 descp VARCHAR2 (25)
7 );
8 /
Type created.
SQL> CREATE OR REPLACE TYPE pb_calculate_bill_ct IS TABLE OF pb_calculate_bill_ot;
2 /
Type created.
Sample procedure:
SQL> CREATE OR REPLACE PROCEDURE select_price (
2 pi_bill_id IN NUMBER,
3 pi_version IN NUMBER,
4 po_data_ct OUT pb_calculate_bill_ct)
5 IS
6 lt_calculate_bill_ct pb_calculate_bill_ct := pb_calculate_bill_ct ();
7 BEGIN
8 SELECT pb_calculate_bill_ot (bill_id,
9 version,
10 rate,
11 descp)
12 BULK COLLECT INTO lt_calculate_bill_ct
13 FROM bill
14 WHERE bill_id = pi_bill_id
15 AND pi_version = pi_version;
16
17 po_data_ct := lt_calculate_bill_ct;
18 END select_price;
19 /
Procedure created.
Testing (this is what you asked for): declare a local variable which will hold result returned by the procedure; then, in a loop, do something with the result - I displayed it using dbms_output.put_line:
SQL> DECLARE
2 l_res pb_calculate_bill_ct;
3 BEGIN
4 select_price (1, 20, l_res);
5
6 FOR i IN 1 .. l_res.COUNT
7 LOOP
8 DBMS_OUTPUT.put_line (
9 'Bill ID = '
10 || l_res (i).bill_id
11 || ', version = '
12 || l_res (i).version
13 || ', rate = '
14 || l_res (i).rate
15 || ', description = '
16 || l_res (i).descp);
17 END LOOP;
18 END;
19 /
Bill ID = 1, version = 20, rate = 1234, description = Little
PL/SQL procedure successfully completed.
SQL>
I would update this text
try1
try2
try3
try4
How can i set syntax for do a update in oracle 9?
update table set field = 'try1
try2
try3
try4'
where id = 1
without text wrap?
I have a text really very big from update.
You can try to build the string with anonymous PL/SQL block.
This is just an example that you need to adapt:
SQL> set serveroutput on
SQL>
SQL> desc lob_table;
Name Null? Type
----------------------------------------- -------- ----------------------------
KEY_VALUE NUMBER
C_COL CLOB
SQL>
SQL> declare
2 v varchar2(10000);
3 begin
4 v:='try1' || rpad (' ', 9000, ' ') || 'try2';
5 dbms_output.put_line('length(v) = ' || length(v));
6 update lob_table set c_col = v where key_value=12;
7 end;
8 /
length(v) = 9008
PL/SQL procedure successfully completed.
SQL> show errors
No errors.
If the above code does not work in Oracle 9, you can try to use DBMS_LOB.
Example:
SQL> --
SQL> set serveroutput on
SQL> --
SQL> DECLARE
2 value VARCHAR2(10000);
3 amount binary_integer;
4 lob_loc CLOB;
5 BEGIN
6 value :='try1' || rpad (' ', 9000, ' ') || 'try2';
7 dbms_output.put_line('length(v) = ' || length(value));
8 SELECT c_col INTO lob_loc
9 FROM lob_table
10 WHERE key_value = 12 FOR UPDATE;
11 amount := length(value);
12 dbms_lob.write (lob_loc, amount, 1, value);
13 COMMIT;
14 END;
15 /
length(v) = 9008
PL/SQL procedure successfully completed.
SQL> show errors
No errors.
SQL>
Select all the tables of database where column match than pass table name to next query using loop. If column name and column values matches than return true and exist for loop using a stored procedure:
CREATE OR REPLACE PROCEDURE TEST
(
NAME IN VARCHAR2 ,
ID IN NUMBER,
RE OUT SYS_REFCURSOR
) AS
BEGIN
OPEN RE FOR SELECT A.TABLE_NAME FROM
user_tables A JOIN user_tab_columns C
ON C.TABLE_NAME = A.TABLE_NAME
WHERE C.COLUMN_NAME = NAME;
FOR RE IN LOOP
v_Sql := 'SELECT COUNT(*) FROM '|| LOOP.TABLE_NAME || 'WHERE COLUMN_NAME =
ID';
EXECUTE IMMEDIATE v_Sql
IF v_Sql%ROWCOUNT > 0 THEN
return true;
EXIT
END LOOP;
END TEST;
For more understanding the problem
//Get all the tables of database where campus_id is exist in any table of
database
Campus, Class, Section (3 tables found)
Apply forloop on the records
Select count(campus_id) as total from (table name using loop) where campus_id = 1(value
pass)
if(total > 0){
Exist for loop and return true
}
else{
Again iterate the loop to next value
}
What you described doesn't make much sense. If there are several tables that contain a column you're checking and you exit the loop as soon as you find the first one, what about the rest of them?
Here's what I'd do, see if it helps. I'll create a function (not a procedure) that returns a table. In order to do that, I'll create type(s) first:
SQL> create or replace type t_record as object (tn varchar2(30), cnt number);
2 /
Type created.
SQL> create or replace type t_table as table of t_record;
2 /
Type created.
SQL>
The function:
in a cursor FOR loop I'm selecting tables that contain that column
L_STR is used to compose the SELECT statement
DBMS_OUTPUT.PUT_LINE is used to display it first, so that I could visually check whether it is correctly set or not.
if it is, I'm running it with the EXECUTE IMMEDIATE
the result is stored into a table type and returned to the caller
SQL> create or replace function f_colname
2 (par_column_name in varchar2,
3 par_column_value in varchar2
4 )
5 return t_table
6 is
7 retval t_table := t_table();
8 l_str varchar2(200);
9 l_cnt number;
10 begin
11 for cur_r in (select table_name
12 from user_tab_columns
13 where column_name = par_column_name
14 )
15 loop
16 l_str := 'select count(*) from ' || cur_r.table_name ||
17 ' where ' || par_column_name || ' = ' ||
18 chr(39) || par_column_value || chr(39);
19 -- Display l_str first, to make sure that it is OK:
20 -- dbms_output.put_line(l_str);
21 execute immediate l_str into l_cnt;
22 retval.extend;
23 retval(retval.count) := t_record(cur_r.table_name, l_cnt);
24 end loop;
25 return retval;
26 end;
27 /
Function created.
Testing:
SQL> select * from table (f_colname('DEPTNO', '10'));
TN CNT
------------------------------ ----------
TEST_201812 1
DEPT 1
EMP 3
SQL> select * from table (f_colname('ENAME', 'KING'));
TN CNT
------------------------------ ----------
EMP 1
BONUS 1
SQL>
That won't work properly for some datatypes (such as DATE) and will have to be adjusted, if necessary.
[EDIT: after you edited the question]
OK then, that's even simpler. It should still be a function (that returns a Boolean, as you said that - in case that something's being found - you want to return TRUE). Code is pretty much similar to the previous function.
SQL> create or replace function f_colname
2 (par_column_name in varchar2,
3 par_column_value in varchar2
4 )
5 return boolean
6 is
7 l_str varchar2(200);
8 l_cnt number;
9 retval boolean := false;
10 begin
11 for cur_r in (select table_name
12 from user_tab_columns
13 where column_name = par_column_name
14 )
15 loop
16 l_str := 'select count(*) from ' || cur_r.table_name ||
17 ' where ' || par_column_name || ' = ' ||
18 chr(39) || par_column_value || chr(39);
19 -- Display l_str first, to make sure that it is OK:
20 -- dbms_output.put_line(l_str);
21 execute immediate l_str into l_cnt;
22 if l_cnt > 0 then
23 retval := true;
24 exit;
25 end if;
26 end loop;
27 return retval;
28 end;
29 /
Function created.
Testing: as you can't return Boolean at SQL layer, you have to use an anonymous PL/SQL block, as follows:
SQL> declare
2 l_ret boolean;
3 begin
4 if f_colname('DEPTNO', '15') then
5 dbms_output.put_line('It exists');
6 else
7 dbms_output.put_line('It does not exist');
8 end if;
9 end;
10 /
It does not exist
PL/SQL procedure successfully completed.
SQL>
I want to implement one search logic here. What I want is,
A user enters any text in the search box and presses enter. Then what should happen is, it should search in the table on any column and it the record exist then it should display.
Currently what I tried is, it search from one of the column from the table. Below is the code,
PROCEDURE GET_SEARCH_DATA
(
P_INPUTTEXT IN NVARCHAR2,
P_RETURN OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN P_RETURN FOR
SELECT APP_MST_ID, APPLICATIONNAME, PROJECTNO, VSS_FOLDER_LOC FROM
APPLICATION_MASTER WHERE APPLICATIONNAME LIKE '%'|| P_INPUTTEXT || '%';
END;
So what I want is, it should search from every column of the table and display the result.
This is a rather rudimentary "solution" which checks all tables and their columns (from USER_TAB_COLUMNS) and checks which ones of them contain a search string; it displays a table, a column and number of occurrences.
SQL> declare
2 l_str varchar2 (500);
3 l_cnt number := 0;
4 begin
5 for cur_r in (select u.table_name, u.column_name
6 from user_tab_columns u)
7 loop
8 l_str :=
9 'SELECT COUNT(*) FROM '
10 || cur_r.table_name
11 || ' WHERE '
12 || upper (cur_r.column_name)
13 || ' like (''%&search_string%'')';
14
15 execute immediate (l_str) into l_cnt;
16
17 if l_cnt > 0
18 then
19 dbms_output.put_line (
20 cur_r.table_name || '.' || cur_r.column_name || ': ' || l_cnt);
21 end if;
22 end loop;
23 end;
24 /
Enter value for search_string: MANAGE
EMP.JOB: 3
PL/SQL procedure successfully completed.
SQL> /
Enter value for search_string: ACCOU
DEPT.DNAME: 1
PL/SQL procedure successfully completed.
SQL>