PLSQL ignore compilation error which is not an error - oracle

I came accross interesting error where I am not sure about best way how to fix it. Given following block:
DECLARE
v_column_exists number := 0;
host_column_exists number := 0;
i number;
BEGIN
Select count(*) into v_column_exists from user_tab_cols where column_name = 'CONNECTIONDESCRIPTION' and table_name = 'NODES';
if (v_column_exists = 1) then
Select count(*) into host_column_exists from user_tab_cols where column_name = 'HOST' and table_name = 'NODES';
if (host_column_exists = 0) then
execute immediate 'alter table NODES add (Host varchar2(255))';
for item in (select connectiondescription, code from nodes) loop
... LOOP STUFF ...
end loop;
end if;
end if;
END;
I get following result:
PL/SQL: ORA-00904: "CONNECTIONDESCRIPTION": invalid identifier
ORA-06550: line 40, column 20: PL/SQL: SQL Statement ignored
ORA-06550: line 41, column 20: PLS-00364: loop index variable 'ITEM'
use is invalid
any ideas how to get rid of this error? Problem is occuring when column NODES.CONNECTIONDESCRIPTION is not present in database, however in such case for loop won't execute in runtime. I would need to disable these errors, but haven't found any way to do it. I have tried using ALTER SESSION SET PLSQL_WARNINGS='DISABLE:00904', but it had no effect.
Thanks

Correct approach was to use another dynamic query which bulk collects items to an array and then loop through this array.

Related

ORA-00922: missing or invalid option when trying to create column in table

I'm using the following code for create a column in an existing table, but, I'm getting this error:
ORA-00922: missing or invalid option
I've tried get the desired result (create column in table "only if this column does not exists") without the EXECUTE IMMEDIATE instruction, but, PL/SQL doesn't allow use the ALTER TABLE [...] in an IF [] THEN structure.
Is there something I'm missing?
This is the db<>fiddle sample:
CREATE TABLE "TMP_TABLE_SAMPLE"
( "ID_TABLE" NUMBER(9,0)
) ;
✓
SET SERVEROUTPUT ON;
CLEAR SCREEN;
DECLARE
V_COLUMN_EXISTS NUMBER := 0;
BEGIN
SELECT COUNT(1) CONTEO
INTO V_COLUMN_EXISTS
FROM USER_TAB_COLS
WHERE UPPER(COLUMN_NAME) = 'PNT_NCODE'
AND UPPER(TABLE_NAME) = 'TMP_TABLE_SAMPLE';
IF V_COLUMN_EXISTS = 0 THEN
EXECUTE IMMEDIATE 'ALTER TABLE TMP_TABLE_SAMPLE ADD PNT_NCODE NUMBER (9,0) ' ||
' COMMENT ON COLUMN TMP_TABLE_SAMPLE.PNT_NCODE IS ''Stores ID from TMP_TABLE_SAMPLE_2.''';
ELSE
DBMS_OUTPUT.PUT_LINE('Column already exists');
END IF;
END;
ORA-00922: missing or invalid option
The error you're getting is because you have set serveroutput on and clear screen in your script. db<>fiddle knows how to interpret SQL and PL/SQL. It doesn't support SQL*Plus commands.
If you remove those, the next error you'll get is that you have a single execute immediate statement that is trying to execute two separate statements. Creating the column and adding a comment on the column are separate operations so you need separate statements.
If I change your fiddle to this, it works the way you want
DECLARE
V_COLUMN_EXISTS NUMBER := 0;
BEGIN
SELECT COUNT(1) CONTEO
INTO V_COLUMN_EXISTS
FROM USER_TAB_COLS
WHERE UPPER(COLUMN_NAME) = 'PNT_NCODE'
AND UPPER(TABLE_NAME) = 'TMP_TABLE_SAMPLE';
IF V_COLUMN_EXISTS = 0 THEN
EXECUTE IMMEDIATE 'ALTER TABLE TMP_TABLE_SAMPLE ADD PNT_NCODE NUMBER (9,0) ';
EXECUTE IMMEDIATE 'COMMENT ON COLUMN TMP_TABLE_SAMPLE.PNT_NCODE IS ''Stores ID from TMP_TABLE_SAMPLE_2.''';
ELSE
DBMS_OUTPUT.PUT_LINE('Column already exists');
END IF;
END;
/

I want to update these tables by adding 1000000 'FİLE_NO' and 'PROT_NO' columns

I want to find tables in the user schema that contain the columns 'FİLE_NO' and 'PROT_NO'.
Then I want to update these tables by adding 1000000 to 'FİLE_NO' and 'PROT_NO' columns.
I tried to write the code below, but it failed when updating.
How do I fix this error?
declare
v_match_count integer;
begin
v_match_count:=0;
for tablolar in
(select user_tables.table_name from user_tables,user_tab_columns where
user_tables.table_name=user_tab_columns.table_name
and user_tab_columns.column_name='file_no'
intersect
select user_tables.table_name from user_tables,user_tab_columns where
user_tables.table_name=user_tab_columns.table_name
and user_tab_columns.column_name='PROT_NO'
) loop
-- v_match_count:=v_match_count+1;
-- dbms_output.put_line(tablolar.table_name||' = '||v_match_count);
UPDATE tablolar.table_name SET file_no =file_no+1000000,--oracle gives me the error on this line ???
PROT_NO =PROT_NO+1000000;
end loop;
end;
ORA-06550: line 16, column 25:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 16, column 9:
PL/SQL: SQL Statement ignored
You can not just get a table name from a cursor and update it. Use dynamic SQL for that:
EXECUTE IMMEDIATE 'UPDATE '||tablolar.table_name||' SET file_no = file_no+1000000,
PROT_NO = PROT_NO+1000000';
Unhappily PL/SQL is not an oriented object language. So tablolar.table_name is not a pointer to a table :). You are trying to update the table table_name of the schema tablolar
You have to use some dynamic sql :
EXECUTE IMMEDIATE 'UPDATE ' || tablolar.table_name || ' SET file_no =file_no+1000000, PROT_NO =PROT_NO+1000000';
instead of
UPDATE tablolar.table_name SET file_no =file_no+1000000, PROT_NO =PROT_NO+1000000';

Oracle PL/SQL - parameterizing SAMPLE clause in SELECT statement

I have a Oracle related question. I would like to select a random sample out of a view or table in such a way that the SAMPLE clause is parameterized.
Given the following table.
CREATE TABLE FOO AS
(SELECT LEVEL AS ID
FROM DUAL
CONNECT BY LEVEL < 101
);
The following construct works, using a literal parameter in the SAMPLE clause.
SELECT ID FROM FOO SAMPLE (15); -- this will get a 15% sample
However,
DECLARE
N NUMBER := 50;
BEGIN
FOR r IN
( SELECT ID FROM FOO SAMPLE (N) -- <<< this won't work
)
LOOP
DBMS_OUTPUT.PUT_LINE( r.ID );
END LOOP;
END;
This block blows up when we put a parameter in the SAMPLE clause. It compiles and works if we put it a literal.
But if it is a variable, I get the following:
ORA-06550: line 5, column 33:
PL/SQL: ORA-00933: SQL command not properly ended
Any ideas? I'm racking by brains where the syntax gets broken.
The syntax does not allow a variable there.
One workaround would be to construct the SELECT statement dynamically. For example:
declare
l_rc sys_refcursor;
n number := 5;
begin
-- replace "mtl_system_items" with your table...
open l_rc FOR 'select count(*) from mtl_system_items sample (' || n || ')';
-- replace call to RETURN_RESULT with whatever processing you want
DBMS_SQL.RETURN_RESULT(l_rc);
end;

DBMS_OUTPUT.PUT_LINE returning error

I am attempting to write a basic PL/SQL For Loop and keep getting an error. My statement is:
begin
for tab_x in
(select unique table_name from all_tables
where owner like 'MSGCENTER_DBO%'
and table_name like 'MSG_DETAIL%')
loop
DBMS_OUTPUT.PUT_LINE(tab_x);
end loop;
end;
/
The error message is
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 6, column 7:
PL/SQL: Statement ignored
I am probably missing something VERY obvious but have not been able to get this to work. I appreciate any help!
You want to access tab_x.table_name instead.
begin
for tab_x in
(select unique table_name from all_tables
where owner like 'MSGCENTER_DBO%'
and table_name like 'MSG_DETAIL%')
loop
DBMS_OUTPUT.PUT_LINE(tab_x.table_name );
end loop;
end;
/

Dynamic column name using cursor in Oracle PLSQL

I need to generate the column name dynamically in loop and access the column in oracle table using PLSQL. How do I do that?
DECLARE
varValue VARCHAR(20);
CURSOR c IS
SELECT * FROM TEST1;
BEGIN
FOR i IN c LOOP
FOR j IN 1..5
LOOP
EXECUTE IMMEDIATE 'SELECT ''NAME1'||to_Char(j)||''' from dual' INTO varValue;
dbms_output.put_line(j);
dbms_output.put_line(i.varValue);
END LOOP;
END LOOP;
END;
Actual issue is, I need to acccess the cell values of each row (i) given by cursor (c) like i.name11, i.name12....i.name1100. The logic to be deployed in each cell is same. So i need the column name used here i.e. name11 to be generated dynamically. That is alread done and stored to a variable varValue. Now how can i access the cells i.varValue such that var value is generated in the loop.
The error is as follows:
ORA-06550: line 14, column 34:
PLS-00302: component 'VARVALUE' must be declared
ORA-06550: line 14, column 11:
PL/SQL: Statement ignored
DECLARE
varValue VARCHAR(20);
CURSOR c IS
SELECT * FROM TEST1;
BEGIN
FOR i IN c LOOP
FOR j IN 1..5
LOOP
EXECUTE IMMEDIATE 'SELECT ''NAME1'||to_Char(j)||''' from dual' INTO varValue;
dbms_output.put_line(j);
dbms_output.put_line('NAME1'||to_Char(j)||' : '||varValue);
END LOOP;
END LOOP;
END;

Resources