Dynamic Query Error in PLSQL - oracle

I am trying to execute this procedure:
CREATE OR REPLACE PROCEDURE SP_DYNAMIC
AS
tbl_list VARCHAR2(2000);
DBLINK VARCHAR2(100);
V_SQL VARCHAR2(1000);
BEGIN
DBLINK := 'SOME_LINK';
V_SQL := 'SELECT table_name,table_owner FROM dba_tab_modifications#:DB_LINK';
EXECUTE IMMEDIATE V_SQL USING DBLINK;
COMMIT;
Dbms_Output.PUT_LINE (TBL_LIST);
END;
But When I execute the stored procedure I get the error:
ORA-01729: database link name expected
ORA-06512: at "SYSTEM.SP_DYNAMIC"
ORA-06512: at line 2
Can somebody help me with what I am doing wrong here?

The reason it doesn't work is because you can't use a bind variable as the dblink. You get the same error when running the following:
select * from dual#:dblink;
If you absolutely must use dynamic sql, you'd have to concatenate the dblink name into the statement - but you'll have to be aware that you're now open to SQL Injection:
V_SQL := 'SELECT table_name,table_owner FROM dba_tab_modifications#'||DB_LINK;

Related

ORA-00942 table or view does not exist when I run a package using a cursor

I get a weird error when running an Oracle page, which needs to find an existing tablespace to create a new schema. I am using an AWS RDS Oracle instance using 19c. The package compiles without errors.
Package
...
ts_name varchar2(30);
sql_stmt varchar2(255);
procedure create_schema (input in varchar2);
Package Body
procedure create_schema (input in varchar2) as
v_cur SYS_REFCURSOR;
v2_cur SYS_REFCURSOR;
BEGIN
usrname := input;
ts_name := substr(input,0,30));
sql_stmt := 'select ts# from v$tablespace where name = '''||ts_name||'''';
OPEN v_cur FOR sql_stmt;
...
When I run it, I get this error:
ORA-00942: table or view does not exist
ORA-06512: at "mypackage", line 13
Line 13 is the OPEN v_cur FOR line. Manually, I can run select ts# from v$tablespace without any issues. No clue why this happens. Can someone explain the non-existing table/view?

Create Oracle sequence via execute immediate without pipe || operator

create sequence s1 ;
declare
v_value number;
v_sql_stmt varchar2(4000);
v_seq_name varchar2(30);
BEGIN
v_seq_name:='S1'; -- **this is dynamic and the sequence will be passed in the proc as input parameter at runtime**
v_sql_stmt:= 'select :v_seq_name'||'.nextval from dual' ;
EXECUTE IMMEDIATE v_sql_stmt INTO v_value USING v_seq_name ;
--**below is working but I dont want to do in this way because of sql injection issue, let me know how to fix the above**
--EXECUTE IMMEDIATE 'select ' || v_seq_name || '.nextval from dual' INTO v_value;
dbms_output.put_line(v_value);
end;
/
the above code is throwing error, please help to fix.
If you run the commented code then it will run but I dont want to use || in execute immediate. I want to use colon : only.
the sequence name will be passed at run time. The above code will be converted to a proc later.
I understand your concern about SQL injection. To my knowledge, table/column/sequence names cannot be specified with bind variables. However, you could do a simple check before executing the unsafe code:
CREATE SEQUENCE s1;
CREATE SEQUENCE s2;
CREATE OR REPLACE FUNCTION p(seq_name VARCHAR2) RETURN NUMBER AS
v_value number;
v_sql_stmt varchar2(4000);
v_seq_name varchar2(128 BYTE);
BEGIN
v_seq_name:= DBMS_ASSERT.SIMPLE_SQL_NAME(seq_name);
v_sql_stmt:= 'select '||v_seq_name||'.nextval from dual';
EXECUTE IMMEDIATE v_sql_stmt INTO v_value;
RETURN v_value;
END p;
/
If a valid name is used, everything works as expected:
select p('s1') from dual;
1
select p('s2') from dual;
2
However, if seq_name is not a valid Oracle name, DBMS_ASSERT throws an exception:
select p('1; DROP TABLE x') from dual;
ORA-44003: invalid SQL name
ORA-06512: at "SYS.DBMS_ASSERT", line 215
ORA-06512: at "WFL.P", line 6
44003. 0000 - "invalid SQL name"

Getting error ORA-06502 while creating Dynamic SQL query using procedure

I have created a procedure and it requires Dynamic SQL block.
Procedure is as below which complies correctly but when I try to run it , it gives the below error.
I have tried to use cast() for all the variable which are used here. But this does not help.
Also, I am trying to run this procedure on Oracle using SQL - Developer tool.
Once the dynamic SQL is stored in sqlquery variable I would try and run the dynamic query and display its results!
**Output**
*Connecting to the database XXX.
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at "XXX.PROCEDURE2", line 28
ORA-06512: at line 6
Who are you ?
Process exited.
Disconnecting from the database XXX.*
Procedure
*create or replace PROCEDURE PROCEDURE2 (var_owner IN dba_tab_cols.owner%TYPE) AS
CURSOR col_ident IS
select col1_name,col2,col3,col4,nullable,'_NM' as s_type
from table_name
where col2 in var_owner
and col3 like 'exp%%'
and col4 like 'exp2%';
sample_record col_ident%ROWTYPE;
BEGIN
OPEN col_ident;
LOOP
FETCH col_ident INTO sample_record;
DECLARE
col_nm VARCHAR2(30);
tab_nm VARCHAR2(30);
schema_nm VARCHAR2(30);
--a1 VARCHAR2(30);
sqlquery VARCHAR2(400);
BEGIN
col_nm := sample_record.col2;
tab_nm := sample_record.col3;
schema_nm := sample_record.col1_name;
IF sample_record.col4 = 'VARCHAR2' THEN
DBMS_OUTPUT.PUT_LINE('Who are you ? ');
sqlquery:= ('select distinct ' +col_nm+ 'from' + schema_nm+'.'+tab_nm + 'where rownum < 1');
DBMS_OUTPUT.PUT_LINE('Do you know me ');
END IF;
EXIT WHEN col_ident%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(sample_record.col1_name||','||sample_record.col3
||','||sample_record.col2||','||sample_record.col4||','||
sample_record.col5||','||sample_record.nullable||','||
sample_record.s_type);
END;
END LOOP;
--Close CURSOR col_ident
CLOSE col_ident;
END PROCEDURE2;*

Oracle display resultset of dynamic sql

i am pretty new to oracle and i am searching for two days already for a solution for my problem.
i have a view which should have a dynamic column and table name.
something like that:
DECLARE
plsql_block VARCHAR2(500);
BEGIN
plsql_block := 'SELECT CONCAT('some','column') FROM CONCAT('some','table')';
EXECUTE IMMEDIATE plsql_block
END;
This would work but how to i display the result? I already tried it with DBMS.Output and a Loop but thats not exactly what i want. i need that it is displayed as a normal result set in the GUI when i run this command. Does anyone has a hint for me how i am doing this in oracle?
I am Thankful for every answer
Thanks pat
Actually I don't understand your dynamic query. But as per my understanding this query is multirow result result set. So you need to use BULK collect and iterate throuh the output for just the purpose of display.
There are two approaches
1) Just to display the output.
SET serveroutput ON;
DECLARE
plsql_block VARCHAR2(500);
lv_col1 VARCHAR2(10):='1';
lv_col2 VARCHAR2(10):='2';
type tab_var
IS
TABLE OF VARCHAR2(10);
tab tab_var;
BEGIN
plsql_block := 'SELECT CONCAT('||lv_col1||','||lv_col2||') FROM dual';
EXECUTE immediate plsql_block bulk collect INTO tab;
FOR i IN tab.first..tab.last
LOOP
dbms_output.put_line(tab(i));
END LOOP;
END;
2) Approach will be refactor this into a function and then use it as below.
Creating a Table Type
create or replace
type string_table
IS TABLE OF VARCHAR2(100);
CREATE OR REPLACE
FUNCTION func_mu
RETURN string_table
AS
plsql_block VARCHAR2(500);
lv_col1 VARCHAR2(10):='1';
lv_col2 VARCHAR2(10):='2';
tab string_table;
BEGIN
plsql_block := 'SELECT CONCAT('||lv_col1||','||lv_col2||') FROM dual';
EXECUTE immediate plsql_block bulk collect INTO tab;
RETURN tab;
END;
SELECT * FROM TABLE(func_mu);
If you are on Oracle 12c (with the corresponding Oracle client), you can do this:
declare
l_resultset sys_refcursor;
l_sql_text varchar2(500) :=q'{select 'Hello, 12c!' as greeting from dual}';
begin
open l_resultset for l_sql_text;
dbms_sql.return_result(l_resultset);
end;
(Untested, because I'm not near a 12c command line right now.)

ORA-00942: table or view does not exist ... can I get more details?

I am running a pretty complex and long query with hundreds of unions and other complex inner queries ... and I am getting ORA-00942: table or view does not exist .... do I have a way to know which table exactly that doesn't exist ?
N.B. : the query is a part of a PL/SQL procedure and the exception is printed via DBMS_OUTPUT.PUT_LINE(SUBSTR(SQLERRM, 1, 400));
If the PL/SQL procedure compiles, any directly referenced table must exist. I'd assume it is dynamic SQL. If you are using DBMS_SQL, then you can use LAST_ERROR_POSITION. If you are using EXECUTE IMMEDIATE, and you have your SQL in a handy variable, then have your code do something like:
begin
execute immediate v_sql;
exception
when others then
declare
v_cur BINARY_INTEGER;
begin
v_cur := dbms_sql.open_cursor;
dbms_sql.parse (v_cur, v_sql, dbms_sql.native);
exception
when others then
dbms_output.put_line (sqlerrm || ' near pos ' ||
substr(v_sql,dbms_sql.last_error_position -10,40));
dbms_sql.close_cursor (v_cur);
raise;
end;
end;

Resources