I can't understand why do I get this error. I have the table but the code sample is not working properly. What's the problem here?
DECLARE
CURSOR c_cust(p_city VARCHAR2) IS
SELECT * FROM cust WHERE cust.city=p_city;
v_cust c_cust%ROWTYPE;
v_city c_cust%TYPE;
BEGIN
v_city := 'London';
OPEN c_cust (v_city);
LOOP
FETCH c_cust INTO v_cust;
EXIT WHEN (c_cust%NOTFOUND);
DBMS_OUTPUT.PUT_LINE (v_cust.cname || ' has ' || v_cust.rating);
END LOOP;
IF (c_cust%ISOPEN) THEN CLOSE c_cust;
END;
ORA-06550: line 15, column 4: PLS-00103:
Encountered the symbol ";"
when expecting one of the following: if
DECLARE
CURSOR c_cust(p_city VARCHAR2) IS
SELECT * FROM cust WHERE cust.city=p_city;**
c_cust%ISOPEN should be before end loop;
If .... then
....
end if;
you miss the end if;
Related
I am trying to get all the tables where bank_id is 01.
I have written the following block
DECLARE
cursor cBankId is
select owner||'.'||table_name from all_tab_columns where column_name = 'BANK_ID';
v_table all_tab_columns.table_name%TYPE;
vcount varchar2(50);
BEGIN
open cBankId;
loop
fetch cBankId into v_table;
exit when cBankId%notfound;
execute immediate 'select count(*) from ' || v_table into vcount || ' where bank_id = 01';
IF vcount > 0 THEN
DBMS_OUTPUT.PUT_LINE (v_table);
END IF;
end loop;
close cBankId;
END;
I want to know how to put where clause in the execute immediate statement .
I am getting the error
ORA-06550: line 15, column 67:
PLS-00103: Encountered the symbol "|" when expecting one of the following:
. ( , % ; return returning using
You only need to change the order you're writing the parts of your query.
When using dynamic SQL, you need something like this:
SQL> declare
2 v_table varchar2(30);
3 vCount number;
4 begin
5 v_table := 'dual';
6 execute immediate 'select count(*) from ' || v_table || ' where 1=1' into vcount;
7 --
8 dbms_output.put_line('vCount: ' || vCount);
9 end;
10
11 /
vCount: 1
PL/SQL procedure successfully completed.
That is: execute immediate 'select ... from ... where ...' INTO ...;
You can't dynamically use a variable for the table name, instead use:
DECLARE
cursor cBankId is
select owner||'.'||table_name from all_tab_columns where column_name = 'BANK_ID';
v_table all_tab_columns.table_name%TYPE;
vcount varchar2(50);
v_sql varchar2(1000);
BEGIN
open cBankId;
loop
fetch cBankId into v_table;
exit when cBankId%notfound;
v_sql := 'select count(*) from ' || v_table || ' into vcount where bank_id = 01';
execute immediate v_sql;
IF vcount > 0 THEN
DBMS_OUTPUT.PUT_LINE (v_table);
END IF;
end loop;
close cBankId;
END;
there is a logic error in the following procedure that I can't find , can you find what is it ? the below procedure is causing the following error :
ora-01001 invalid cursor 01001
and this is the procedure:
CREATE OR REPLACE PROCEDURE P_C is
v_tab_name varchar2(40);
-- v_col_name varchar2(100);
var1 varchar2(2000);
var2 varchar2(2000);
tab_var varchar2(2000);
/* First cursor */
CURSOR get_tables IS
SELECT tab.table_name
FROM user_tables tab;
/* Second cursor */
CURSOR get_columns IS
SELECT DISTINCT cols.column_name
FROM user_tab_cols cols
WHERE cols.table_name = v_tab_name;
BEGIN
var1 := null;
-- Open first cursor
for gettab in get_tables
LOOP
tab_var :=gettab.table_name;
-- Open second cursor
for getcols in get_columns
LOOP
if var1 is null then
var1 :=getcols.column_name;
else
var1 := var1 ||' , '|| getcols.column_name;
end if;
END LOOP;
CLOSE get_columns;
END LOOP;
CLOSE get_tables;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
end P_C;
check the following code, this will work. The main thing is, to use a cursor variable. So the code will be much clearer and easier.
But consider, that you will get all columns of all tables. That's a lot!
CREATE OR REPLACE PROCEDURE P_C is
var1 varchar2(32000);
/* First cursor */
CURSOR get_tables IS
SELECT tab.table_name FROM user_tables tab;
/* Second cursor */
CURSOR get_columns (ci_tab_name in varchar2) IS
SELECT DISTINCT cols.column_name
FROM user_tab_cols cols
WHERE cols.table_name = ci_tab_name;
BEGIN
var1 := null;
for c1 in get_tables loop
for c2 in get_columns (c1.table_name) loop
if var1 is not null then
var1 := var1 || ', ';
end if;
var1 := var1 || c2.column_name;
end loop;
end loop;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,
'An error was encountered - ' || SQLCODE ||
' -ERROR- ' || SQLERRM);
end P_C;
If I've understood your code right, I think you should change second cursor to something like:
/* Second cursor */
CURSOR get_columns(v_tab_p VARCHAR2) IS
SELECT DISTINCT cols.column_name
FROM user_tab_cols cols
WHERE cols.table_name = v_tab_p;
then change the second loop to something like:
tab_var :=gettab.table_name;
-- Open second cursor
for getcols in get_columns(tab_var) LOOP
and finally, I'm not sure you need to explicitly close the 2 cursors.
I was trying to create a PL/SQL program to search for a value in entire database. Following is the code:
DECLARE
custom_query VARCHAR2(100);
user_input VARCHAR2(100);
i NUMBER (6);
TYPE temp_record
IS
varray(1000) OF VARCHAR2(100);
CURSOR t_rec IS
SELECT a.name AS t_name,
b.name AS c_name
FROM sys.TABLES a,
sys.COLUMNS b
WHERE a.object_id = b.object_id;
table_rec t_name%ROWTYPE;
BEGIN
IF NOT t_rec%isopen THEN
OPEN t_rec;
END IF;
FETCH t_rec
INTO table_rec;
WHILE t_rec%FOUND THEN
LOOP
custom_query := 'select'
|| table_rec.c_name
|| 'into temp_record from'
||table_rec.t_name ;
dbms_output.Put_line(custom_query);
EXECUTE IMMEDIATE custom_query;
FOR i IN 1 .. temp_record.count
LOOP
IF (Temp_record(i) = user_input) THEN
dbms_output.Put_line ('The value you are looking for is in '
|| table_rec.c_name
|| 'column of table'
|| table_rec.t_name);
END IF;
END LOOP;
END LOOP;
END;
Can anyone let me know what's wrong with this code?
Use ALL_TAB_COLUMNS to iterate all tables and columns in your dynamic query.
I have the following trigger
CREATE OR REPLACE TRIGGER L_BIUR_G_LAY
BEFORE INSERT OR UPDATE ON G_LAY
FOR EACH ROW
When (new.g_roo is not null)
DECLARE
x number(1);
stmt varchar(255);
BEGIN
FOR I IN (SELECT DISTINCT G_TAB FROM G_LEG)
LOOP
stmt := 'select distinct g_lind from ' || i.g_tab || ' where g_roo = ' || :new.g_roo;
Execute immediate stmt into x;
IF (x<>0) THEN
RAISE_APPLICATION_ERROR(-2001, 'G_ROO cannot be inserted where G_LIND IS NOT ZERO');
END IF;
END LOOP;
END;
/
and when I do
insert into G_LAY (G_OGCS, G_OGC, G_ROO, G_NM, G_TI, G_AB, G_DATE)
(select G_LAY_SEQ.NEXTVAL, 1, G_ROO, G_LGNDIT, G_UNE, 'Pipe Data Long - ' || G_UR, sysdate
from G_DTABLE where G_LIND = 0);
I get the following error
Error report:
SQL Error: ORA-01403: no data found
ORA-06512: at "L_BIUR_G_LAY", line 10
ORA-04088: error during execution of trigger 'G_LAY'
01403. 00000 - "no data found"
Any help would be greatly appreciated. It tried PRAGMA AUTONOMOUS_TRANSACTION after Declare in my trigger but it didn't help me
The problem is not with your INSERT statement. The problem occurs when the dynamically-built SELECT statement in the trigger is executed - no data is found so an ORA-01403 is raised. It looks to me like the easiest thing to do would be to do a SELECT COUNT(...):
CREATE OR REPLACE TRIGGER L_BIUR_G_LAY
BEFORE INSERT OR UPDATE ON G_LAY
FOR EACH ROW
When (new.g_rowno is not null)
DECLARE
x number;
stmt varchar(255);
BEGIN
FOR I IN (SELECT DISTINCT G_DISPCNTRLTAB FROM G_LEG) LOOP
stmt := 'select COUNT(*) from ' || i.g_dispcntrltab ||
' where g_rowno = ' || :new.g_rowno ||
' and g_lind <> 0';
Execute immediate stmt into x;
IF x <> 0 THEN
RAISE_APPLICATION_ERROR(-20001, 'G_RWNO cannot be inserted where G_LIND IS NOT ZERO');
END IF;
END LOOP;
END L_BIUR_G_LAY;
I also changed the error number which is raised as -2001 is not in the range of errors which can be raised using RAISE_APPLICATION_ERROR (the valid range is -20000 to -20999).
Share and enjoy.
On Executing this query, im having an error:
*Error report:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 34
06502. 00000 - "PL/SQL: numeric or value error%s"*
.
My oracle version is:
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
PL/SQL Release 9.2.0.1.0 - Production
please help me..
Regards,
DECLARE CURSOR c1 is SELECT TABLE_NAME FROM All_Tables WHERE TABLE_NAME NOT LIKE '%$%' AND Owner NOT IN ('WMSYS', 'EXFSYS', 'CTXSYS', 'WKSYS', 'SYSMAN', 'SYSTEM', 'FLOWS_030000', 'MDSYS', 'ORDSYS', 'DBSNMP', 'XDB', 'OLAPSYS');
col_names SYS_REFCURSOR; TYPE dat_res IS RECORD(tab_name VARCHAR2(1000),col_name VARCHAR2(1000));
TYPE dr is table of dat_res;
act_dat dr:= dr();
status NUMBER := 0;
cnt NUMBER := 1;
sql_stmt VARCHAR2(10000);
tab_name1 VARCHAR2(100);
col_name1 VARCHAR2(100);
BEGIN
FOR I IN C1 LOOP sql_stmt:= 'SELECT table_name,column_name FROM all_Tab_cols WHERE table_name = '||CHR(39)||I.table_name||CHR(39);
OPEN col_names FOR sql_stmt; LOOP FETCH col_names INTO tab_name1,col_name1;
EXIT WHEN col_names%NOTFOUND;
BEGIN
EXECUTE IMMEDIATE
'SELECT 1 FROM '||tab_name1|| ' WHERE REGEXP_LIKE('||'TO_CHAR('||col_name1||'), '||CHR(39)||'^[%][a-bA-B]'||CHR(39)||') '
INTO status;
EXCEPTION
WHEN VALUE_ERROR THEN NULL;
WHEN NO_DATA_FOUND THEN NULL;
WHEN OTHERS THEN NULL;
END;
IF (status = 1) THEN act_dat.extend; act_dat(cnt).tab_name:= tab_name1; act_dat(cnt).col_name:= col_name1; status := 0; cnt:= cnt + 1;
END IF; END LOOP;
CLOSE col_names;
END LOOP;
dbms_output.put_line('Table Name : Column Name');
FOR K IN act_dat.FIRST..act_dat.LAST LOOP insert into my_SAuditor_table VALUES (act_dat(K).tab_name, act_dat(K).col_name);
END LOOP;
Execute IMMEDIATE 'SELECT * FROM my_SAuditor_table';
END;
You might be looping over an empty collection.
You need to check that act_dr has some rows before using act_dr.FIRST and act_dr.LAST, otherwise you get null which is not a number.
This can be done with:
if act_dr.count > 0 then
FOR K IN act_dat.FIRST..act_dat.LAST LOOP
insert into my_SAuditor_table VALUES (act_dat(K).tab_name, act_dat(K).col_name);
END LOOP;
end if;
Problem is that column table name definitions are not consistent. In the end you end up inserting a 1000 bytes column in a 512 bytes column and the funny part is, you only read the column with a max length of 100 bytes.
I'd advise to cleanup the code.