Execute immediate and dynamic sql
Dear all;
Just curious....Why do developers still use dynamic sql..and execute immediate, because I always thought dynamic sql were bads and the use of execute immediate as well...
or am I missing something...
There are no 'bad' things and 'good' things.
There are 'correctly used' and 'incorrectly used' features.
It depends what you want to do.
One simple example: Oracle 11.2 - you write a package that fetches data from range interval partitioned table (a new partition is created automatically every day when new key values are inserted). If you use static SQL then whenever Oracle creates a new partition then your package gets invalidated and has to be compiled. If your package is heavily used (by many sessions running in parallel) then you may get this:
ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package body "PACKAGE.XXXXX" has been invalidated
ORA-06508: PL/SQL: could not find program unit being called: "PACKAGE.XXXXX" Nice, isn't it?
You can avoid this kind of problems by simply using dynamic SQL. You break dependency with the table and your package is not invalidated when new partition is created.
Similar Messages
-
Error while insert data using execute immediate in dynamic table in oracle
Error while insert data using execute immediate in dynamic table created in oracle 11g .
first the dynamic nested table (op_sample) was created using the executed immediate...
object is
CREATE OR REPLACE TYPE ASI.sub_mark AS OBJECT (
mark1 number,
mark2 number
t_sub_mark is a class of type sub_mark
CREATE OR REPLACE TYPE ASI.t_sub_mark is table of sub_mark;
create table sam1(id number,name varchar2(30));
nested table is created below:
begin
EXECUTE IMMEDIATE ' create table '||op_sample||'
(id number,name varchar2(30),subject_obj t_sub_mark) nested table subject_obj store as nest_tab return as value';
end;
now data from sam1 table and object (subject_obj) are inserted into the dynamic table
declare
subject_obj t_sub_mark;
begin
subject_obj:= t_sub_mark();
EXECUTE IMMEDIATE 'insert into op_sample (select id,name,subject_obj from sam1) ';
end;
and got the below error:
ORA-00904: "SUBJECT_OBJ": invalid identifier
ORA-06512: at line 7
then when we tried to insert the data into the dynam_table with the subject_marks object as null,we received the following error..
execute immediate 'insert into '||dynam_table ||'
(SELECT887684 wrote:
ORA-00904: "SUBJECT_OBJ": invalid identifier
ORA-06512: at line 7The problem is that your variable subject_obj is not in scope inside the dynamic SQL you are building. The SQL engine does not know your PL/SQL variable, so it tries to find a column named SUBJECT_OBJ in your SAM1 table.
If you need to use dynamic SQL for this, then you must bind the variable. Something like this:
EXECUTE IMMEDIATE 'insert into op_sample (select id,name,:bind_subject_obj from sam1) ' USING subject_obj;Alternatively you might figure out to use static SQL rather than dynamic SQL (if possible for your project.) In static SQL the PL/SQL engine binds the variables for you automatically. -
Difference between Static SQL Query and Dynamic SQL Query.
Hi,
Please explain the basic difference between static and dynamic sql queries. Please explain with example.Static: http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10472/static.htm
Dynamic: http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10472/dynamic.htm -
Hi Team,
I need to write a SQL to cater the requirements. Below is my requirements:
pagename fieldname fieldvalue account_number consumerID
AFAccountUpdate ArrangementsBroken dfsdff 1234 1234
AFAccountUpdate ArrangementsBroken1 dfsdff 1234 1234
AFAccountUpdate ArrangementsBroken2 dfsdff 1234 1234
AFAccountUpdate ArrangementsBroken2 dfsdff 12345 12345
AFAccountUpdate ArrangementsBroken1 addf 12345 12345
Create table test_pivot_dynamic
pagename varchar(200),
fieldname Varchar(200),
fieldvalue varchar(500),
N9_Router_Account_Number bigint,
TC_Debt_Item_Reference bigint
--Input
insert into test_pivot_dynamic Values('AFAccountUpdate','ArrangementsBroken','addf',1234,1234)
insert into test_pivot_dynamic Values('AFAccountUpdate','ArrangementsBroken1','dfsdff',1234,1234)
insert into test_pivot_dynamic Values('AFAccountUpdate','ArrangementsBroken2','fder',1234,1234)
insert into test_pivot_dynamic Values('AFAccountUpdate','ArrangementsBroken2','dfdfs',12345,12345)
insert into test_pivot_dynamic Values('AFAccountUpdate','ArrangementsBroken1','dfdwe',12345,12345)
insert into test_pivot_dynamic Values('AFAccountUpdate1','Arrangements','addf',1234,1234)
insert into test_pivot_dynamic Values('AFAccountUpdate1','Test1','dfsdff',1234,1234)
--Expected output:
Select 1234,1234,'AFAccountUpdate','ArrangementsBroken','addf','ArrangementsBroken1','dfsdff','ArrangementsBroken2','fder','ArrangementsBroken2','fder'
Select 12345,12345,'AFAccountUpdate','ArrangementsBroken','addf','ArrangementsBroken1','dfdwe','ArrangementsBroken2','dfdfs'
Select 1234,1234,'AFAccountUpdate1','Arrangements','addf','Test1','dfsdff'
so basically we have to pivot and dynamic sql and insert the expected output to a common table which will have all the required fields
Thanks,Ram.
Please don't forget to Marked as Answer if my post solved your problem and use Vote As Helpful if a post was useful. It will helpful to other users.This should give you what you're looking for
SELECT N9_Router_Account_Number,TC_Debt_Item_Reference,PageName,
MAX(CASE WHEN SEQ = 1 THEN fieldname END) AS fieldname1,
MAX(CASE WHEN SEQ = 1 THEN fieldvalue END) AS fieldvalue1,
MAX(CASE WHEN SEQ = 2 THEN fieldname END) AS fieldname2,
MAX(CASE WHEN SEQ = 2 THEN fieldvalue END) AS fieldvalue2,
MAX(CASE WHEN SEQ = 3 THEN fieldname END) AS fieldname3,
MAX(CASE WHEN SEQ = 3 THEN fieldvalue END) AS fieldvalue3,
MAX(CASE WHEN SEQ = 4 THEN fieldname END) AS fieldname4,
MAX(CASE WHEN SEQ = 4 THEN fieldvalue END) AS fieldvalue4
FROM
SELECT *,ROW_NUMBER() OVER (PARTITION BY N9_Router_Account_Number,TC_Debt_Item_Reference,PageName ORDER BY PageName) AS SEQ,*
FROM test_pivot_dynamic
)t
GROUP BY N9_Router_Account_Number,TC_Debt_Item_Reference,PageName
To make it dynamic see
http://www.beyondrelational.com/modules/2/blogs/70/posts/10791/dynamic-crosstab-with-multiple-pivot-columns.aspx
Please Mark This As Answer if it helps to solve the issue Visakh ---------------------------- http://visakhm.blogspot.com/ https://www.facebook.com/VmBlogs -
Strange Case on Security Rights and Dynamic SQL (Execute Immediate)
Hi friends, (forgive me if I write with wrong grammar and sentence, I not used English for daily)
I got a weird trouble yesterday.
I created a package (we can called it X, OK!?) which containing Execute Immediate Statement, that function to delete a table (we can called it Y).
Several days ago, it's worked, but yesterday it wasn't. Last things happened before was recreate those table, and regrant to a role which including user account that execute package X.
Error Msg shown is ORA-00942 : Table or view does not exist. After rechecked and rechecked, I found nothing that could trigger that error, I used DBMS_OUTPUT.PUT_LINE to debug and show what statement resulted and executed, I cut and paste, and it's worked. I created anonymous PL/SQL Block, and wrote it and executed it, and worked.
Finally, today, We Grant explicitly those table to user account Y, not via Role, ... and it's work. Interesting thing I think :P
And, I revoke, execute package and run. I think, there's something about Oracle he..he.. :D .
Can somebody help me and explain me the reason of that strange symptomp? and right solution? I must know it, because several days again, it's launched / install.
TIAHere is the procedure that get troubled into :)
PROCEDURE DeleteOld_Job(
p_Job_Code IN VARCHAR2,
p_User_Id IN VARCHAR2,
p_Parameter_Entry IN VARCHAR2,
p_Status OUT NUMBER )
IS
StrSql VARCHAR2(1000);
CURSOR CTable_Used_By_Report IS
SELECT TABLE_NAME
,TABLE_OWNER
FROM TABLE_USED_BY_JOB
WHERE
Job_Code = p_Job_Code
BEGIN
p_Status := 1;
DBMS_OUTPUT.PUT_LINE('p_Job_Code '| |p_Job_Code );
DBMS_OUTPUT.PUT_LINE('p_Parameter_Entry '| |p_Parameter_Entry );
FOR Item IN CTable_Used_By_Report
LOOP
StrSql := 'DELETE '| |Item.TABLE_OWNER| |'.'| |Item.TABLE_NAME| |' T WHERE EXISTS ( SELECT 1 FROM USERBATCH.HISTORY_JOB H WHERE H.USER_ID = ' ;
StrSql := StrSql| |''''| |p_User_Id| |''''| |' AND H.Job_Code = '| |''''| |p_Job_Code| |''''| |' AND H.PARAMETER_ENTRY = '| |'''' | |p_Parameter_Entry| |''''| |' AND T.SESSION_ID = H.TRANSACTION_ID)';
DBMS_OUTPUT.PUT_LINE(StrSql);
DBMS_OUTPUT.PUT_LINE(Item.TABLE_OWNER| |'.'| |Item.TABLE_NAME);
EXECUTE IMMEDIATE StrSql;
END LOOP;
DBMS_OUTPUT.PUT_LINE('DELETE USERBATCH.HISTORY_JOB WHERE USER_ID ='''| | p_User_Id | |'''
AND Job_Code ='''| | p_Job_Code | |''' AND PARAMETER_ENTRY = '''| | p_Parameter_Entry | |'''');
EXECUTE IMMEDIATE 'DELETE USERBATCH.HISTORY_JOB WHERE USER_ID ='''| | p_User_Id | |'''
AND Job_Code ='''| | p_Job_Code | |''' AND PARAMETER_ENTRY = '''| | p_Parameter_Entry | |'''';
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
p_Status := 0;
DBMS_OUTPUT.PUT_LINE( SUBSTR(SQLERRM,1,255) );
END DeleteOld_Job;
TIA
null -
PL/SQL Proc, execute immediate and materialized view 9.2.0.6
Hello,
Environement description: Sun Solaris 8 , Oracle database 9.2.0.6
I've a problem trying to execute this PL/SQL Procedure:
I'm loged in with PMU user
CREATE OR REPLACE PROCEDURE PMU.PROC_TEST_PMU_C035 (part_arrete in integer, part_session in integer) AS
lv_p_arrete number := part_arrete;
lv_p_session number := part_session;
lv_stmt varchar2(31000);
BEGIN
lv_stmt := ' ';
lv_stmt := lv_stmt || 'CREATE MATERIALIZED VIEW 'PMU''.''TEST_PMU_C035'' ';
lv_stmt := lv_stmt || 'TABLESPACE PMU_8M_DATA ';
lv_stmt := lv_stmt || 'BUILD IMMEDIATE ';
lv_stmt := lv_stmt || 'REFRESH COMPLETE AS ';
lv_stmt := lv_stmt || 'SELECT * FROM ACTION ';
lv_stmt := lv_stmt || 'WHERE LIBELLE IN ( ''SOCIETE 1'', ''SOCIETE 2'', ''SOCIETE 3'' ) ;';
dbms_output.put_line ( lv_stmt) ;
execute immediate ( lv_stmt);
END;
When I comment the line : execute immediate ( lv_stmt); It works fine and my statement appear on the screen:
CREATE MATERIALIZED VIEW PMU.TEST_PMU_C035 TABLESPACE PMU_8M_DATA BUILD
IMMEDIATE REFRESH COMPLETE AS SELECT LIBELLE FROM ACTION WHERE LIBELLE IN (
'SOCIETE1', 'SOCIETE2', 'SOCIETE3' ) ;
When I execute manually this query it works.
But when I try to do the execute immediate, it gives me this error:
BEGIN "PMU"."PROC_TEST_PMU_C035" ( 13, 14); END;
ERROR at line 1:
ORA-00911: invalid character
ORA-06512: at "PMU.PROC_TEST_PMU_C035", line 15
ORA-06512: at line 1
Action Table has this description and datas:
SQL> desc action
Name Null? Type
ISIN NOT NULL VARCHAR2(20)
LIBELLE VARCHAR2(100)
SQL>
ISIN LIBELLE
FR1 SOCIETE 1
FR2 SOCIETE 2
FR3 SOCIETE 3
FR4 SOCIETE 4
FR5 SOCIETE 5
FR6 SOCIETE 6
FR7 SOCIETE 7
FR8 SOCIETE 8
FR9 SOCIETE 9
FR10 SOCIETE 10
FR11 SOCIETE 11
This is a sample description of my probleme because the real case is on multiple partition tables with million rows, but the problem is the same with this sample.
My question is why it doesn't work ? Could anybody help me ?
Thanks In advance.
LoicYes but you did not show where you want the parametersOK this is my Original Query :
CREATE OR REPLACE PROCEDURE "PMU"."PROC_TEST_PMU_C035" (part_arrete in integer, part_session in integer)AS
lv_p_arrete integer := part_arrete;
lv_p_session integer := part_session;
lv_stmt varchar2(31000);
BEGIN
lv_stmt := 'CREATE OR REPLACE MATERIALIZED VIEW PMU.TEST_PMU_C035 ';
lv_stmt := lv_stmt || ' TABLESPACE PMU_8M_DATA ';
lv_stmt := lv_stmt || ' BUILD IMMEDIATE ';
lv_stmt := lv_stmt || ' REFRESH COMPLETE AS ';
lv_stmt := lv_stmt || ' select CD_SOCIETE, MONTANT, MOIS, TYPEDET, LIEUCONS, DETPEA, PERSPHYS, SECTDET, PAYSDET, ZONEDET, CSPDET, AGEDET, TRMONT, NATINSFI, MATURITE, MONNAIE, DEVISEISO, SECTEMT, PAYSEMT, ZONEEMT, ENCRSDEB, NBCPTIT, TYPEFLUX, CONTRAT, CODISIN, LIBELTIT, SEUILDET, PAYSCTP, NBTIT, SEUILA1, SEUILA2, SEUILM1, SEUILM2, SEUILB1, SEUILB2, SEUILQ1, SEUILQ2, TXEVOL, NBCPTITPEA, NBCPTITPPP, ';
lv_stmt := lv_stmt || ' NO_PCI || ''-'' || SECTDET || ''-'' || ZONEDET || ''-'' || MONNAIE || ''-'' || SECTEMT || ''-'' || DETPEA || ''-'' || PERSPHYS || ''-'' || (CASE WHEN TYPEDET IN (''DCL'', ''DCG'') THEN ''DCL'' ';
lv_stmt := lv_stmt || ' ELSE NVL(TYPEDET,'''') ';
lv_stmt := lv_stmt || ' END ) || ''-'' || (CASE WHEN NATINSFI in (''OBL'', ''EMT'', ''BTR'', ''CDD'', ''CDE'', ''CPP'', ''BTS'', ''MIB'') THEN ''OBL'' ';
lv_stmt := lv_stmt || ' ELSE NVL(NATINSFI,'''') ';
lv_stmt := lv_stmt || ' END) || ''-'' ||(CASE WHEN MATURITE IN (''A0'', ''A1'') THEN ''AC'' ELSE NVL(MATURITE,'''') END) || ''-'' ||(CASE WHEN PAYSEMT IN (''FR'',''MC'') THEN ''F1'' ';
lv_stmt := lv_stmt || ' WHEN PAYSEMT IN (''DE'',''AT'',''BE'',''ES'',''FI'',''GR'',''IE'',''IT'',''LU'',''NL'',''PT'',''SI'', ''4F'') THEN ''ZE'' ';
lv_stmt := lv_stmt || ' WHEN PAYSEMT IN (''BG'',''CY'',''DK'',''EE'',''HU'',''LV'',''LT'',''MT'',''PL'',''RO'',''GB'',''SK'',''SE'',''CZ'', ''4C'', ''4D'', ''4H'', ''4E'', ''4Z'', ''JE'') THEN ''ZU'' ';
lv_stmt := lv_stmt || ' ELSE ''ZR''';
lv_stmt := lv_stmt || ' END ) AS CLE';
lv_stmt := lv_stmt || ' from PMU_ESLD_ESTD partition(PMU_M13_S14) e ,';
lv_stmt := lv_stmt || ' PMU_ESLD_ESTD_SPPRO partition(PMU_M13_S14) a';
lv_stmt := lv_stmt || ' where e.PART_ARRETE = '||lv_p_arrete ;
lv_stmt := lv_stmt || ' AND e.PART_ENV = ''BCE''' ;
lv_stmt := lv_stmt || ' AND e.PART_SESSION = '||lv_p_session ;
lv_stmt := lv_stmt || ' and e.ID = a.ID_ESTD ';
lv_stmt := lv_stmt || ' and e.CD_STATUT = ''VE'' ' ;
lv_stmt := lv_stmt || ' and e.TYP_MONTANT = ''33'' ; ' ;
execute immediate lv_stmt;
END;
Thanks -
If table testrh2 has the following columns and data
col1 --> NULL
col2 --> 2
and table testrh has the following columsn and data
col1 --> NULL
How could I write a dynamic SQL statement to join on the nulls? I've written the following block as a starting point.
declare
cursor c1 is select col1 from isis.testrh;
lval varchar2(1000);
lval2 varchar2(1000);
begin
for r1 in c1 loop
lval := 'select col2 from isis.testrh2 where col1 = '||r1.col1;
execute immediate lval into lval2;
dbms_output.put_line(lval2);
end loop;
end;You can't compare null values with '=' in Oracle SQL.
Null can only be compared with <column> is null .
You can see it when you try these two queries:
select * from dual where null is null; -- you will see one row
select * from dual where null=null; -- you will see no rowsThat's why you have to write something like
(<column1>=<column1> or (<column1> is null and <column2> is null))This should also work with null:
decode(<column1>,<column2>,1,0)=1By the way, why do you use dynamic sql?
lval := 'select col2 from isis.testrh2 where col1 = '||r1.col1;
I think you could replace your two lines ( lval:= ... AND execute immediate) by this:
begin
select col2
into lval
from isis.testrh2
where decode(col1,r1.col1,1,0)=1;
dbms_output.put_line('lval='||lval);
exception
when no_data_found then
dbms_output.put_line('no data found'); -- or whatever you want
end;Edited by: hartmutm on 02.10.2010 23:54 -
ORA-01008 with ref cursor and dynamic sql
When I run the follwing procedure:
variable x refcursor
set autoprint on
begin
Crosstab.pivot(p_max_cols => 4,
p_query => 'select job, count(*) cnt, deptno, row_number() over (partition by job order by deptno) rn from scott.emp group by job, deptno',
p_anchor => Crosstab.array('JOB'),
p_pivot => Crosstab.array('DEPTNO', 'CNT'),
p_cursor => :x );
end;I get the following error:
^----------------
Statement Ignored
set autoprint on
begin
adsmgr.Crosstab.pivot(p_max_cols => 4,
p_query => 'select job, count(*) cnt, deptno, row_number() over (partition by
p_anchor => adsmgr.Crosstab.array('JOB'),
p_pivot => adsmgr.Crosstab.array('DEPTNO', 'CNT'),
p_cursor => :x );
end;
ORA-01008: not all variables bound
I am running this on a stored procedure as follows:
create or replace package Crosstab
as
type refcursor is ref cursor;
type array is table of varchar2(30);
procedure pivot( p_max_cols in number default null,
p_max_cols_query in varchar2 default null,
p_query in varchar2,
p_anchor in array,
p_pivot in array,
p_cursor in out refcursor );
end;
create or replace package body Crosstab
as
procedure pivot( p_max_cols in number default null,
p_max_cols_query in varchar2 default null,
p_query in varchar2,
p_anchor in array,
p_pivot in array,
p_cursor in out refcursor )
as
l_max_cols number;
l_query long;
l_cnames array;
begin
-- figure out the number of columns we must support
-- we either KNOW this or we have a query that can tell us
if ( p_max_cols is not null )
then
l_max_cols := p_max_cols;
elsif ( p_max_cols_query is not null )
then
execute immediate p_max_cols_query into l_max_cols;
else
RAISE_APPLICATION_ERROR(-20001, 'Cannot figure out max cols');
end if;
-- Now, construct the query that can answer the question for us...
-- start with the C1, C2, ... CX columns:
l_query := 'select ';
for i in 1 .. p_anchor.count
loop
l_query := l_query || p_anchor(i) || ',';
end loop;
-- Now add in the C{x+1}... CN columns to be pivoted:
-- the format is "max(decode(rn,1,C{X+1},null)) cx+1_1"
for i in 1 .. l_max_cols
loop
for j in 1 .. p_pivot.count
loop
l_query := l_query ||
'max(decode(rn,'||i||','||
p_pivot(j)||',null)) ' ||
p_pivot(j) || '_' || i || ',';
end loop;
end loop;
-- Now just add in the original query
l_query := rtrim(l_query,',')||' from ( '||p_query||') group by ';
-- and then the group by columns...
for i in 1 .. p_anchor.count
loop
l_query := l_query || p_anchor(i) || ',';
end loop;
l_query := rtrim(l_query,',');
-- and return it
execute immediate 'alter session set cursor_sharing=force';
open p_cursor for l_query;
execute immediate 'alter session set cursor_sharing=exact';
end;
end;
/I can see from the error message that it is ignoring the x declaration, I assume it is because it does not recognise the type refcursor from the procedure.
How do I get it to recognise this?
Thank you in advanceThank you for your help
This is the version of Oracle I am running, so this may have something to do with that.
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
I found this on Ask Tom (http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:3027089372477)
Hello, Tom.
I have one bind variable in a dynamic SQL expression.
When I open cursor for this sql, it gets me to ora-01008.
Please consider:
Connected to:
Oracle8i Enterprise Edition Release 8.1.7.4.1 - Production
JServer Release 8.1.7.4.1 - Production
SQL> declare
2 type cur is ref cursor;
3 res cur;
4 begin
5 open res for
6 'select * from (select * from dual where :p = 1) connect by 1 = 1'
7 using 1;
8 end;
9 /
declare
ERROR at line 1:
ORA-01008: not all variables bound
ORA-06512: at line 5
SQL> declare
2 type cur is ref cursor;
3 res cur;
4 begin
5 open res for
6 'select * from (select * from dual where :p = 1) connect by 1 = 1'
7 using 1, 2;
8 end;
9 /
PL/SQL procedure successfully completed.
And if I run the same thing on 10g -- all goes conversely. The first part runs ok, and the second
part reports "ORA-01006: bind variable does not exist" (as it should be, I think). Remember, there
is ONE bind variable in sql, not two. Is it a bug in 8i?
What should we do to avoid this error running the same plsql program code on different Oracle
versions?
P.S. Thank you for your invaluable work on this site.
Followup June 9, 2005 - 6pm US/Eastern:
what is the purpose of this query really?
but it would appear to be a bug in 8i (since it should need but one). You will have to work that
via support. I changed the type to tarray to see if the reserved word was causing a problem.
variable v_refcursor refcursor;
set autoprint on;
begin
crosstab.pivot (p_max_cols => 4,
p_query =>
'SELECT job, COUNT (*) cnt, deptno, ' ||
' ROW_NUMBER () OVER ( ' ||
' PARTITION BY job ' ||
' ORDER BY deptno) rn ' ||
'FROM emp ' ||
'GROUP BY job, deptno',
p_anchor => crosstab.tarray ('JOB'),
p_pivot => crosstab.tarray ('DEPTNO', 'CNT'),
p_cursor => :v_refcursor);
end;
/Was going to use this package as a stored procedure in forms but I not sure it's going to work now. -
Performance between SQL Statement and Dynamic SQL
Select emp_id
into id_val
from emp
where emp_id = 100
EXECUTE IMMEDIATE
'Select '|| t_emp_id ||
'from emp '
'where emp_id = 100'
into id_valWill there be more impact in performance while using Dynamic SQL?CP wrote:
Will there be more impact in performance while using Dynamic SQL?All SQLs are parsed and executed as SQL cursors.
The 2 SQLs (dynamic and static) results in the exact same SQL cursor. So both methods will use an identical cursor. There are therefore no performance differences ito of how fast that SQL cursor will be.
If an identical SQL cursor is not found (a soft parse), the SQL engine needs to compile the SQL source code supplied, into a SQL cursor (a hard parse).
Hard parsing burns a lot of CPU cycles. Soft parsing burns less CPU cycles and is therefore better. However, no parsing at all is the best.
To explain: if the code creates a cursor (e.g. INSERT INTO tab VALUES( :1, :2, :3 ) for inserting data), it can do it as follows:
while More Data Found loop
parse INSERT cursor
bind variables to INSERT cursor
execute INSERT cursor
close INSERT cursor
end loopIf that INSERT cursor does not yet exists, it will be hard parsed and a cursor created. Each subsequent loop iteration will result in a soft parse.
However, the code will be far more optimal as follows:
parse INSERT cursor
while More Data Found loop
bind variables to INSERT cursor
execute INSERT cursor
end loop
close INSERT cursorWith this approach the cursor is parsed (hard or soft), once only. The cursor handle is then used again and again. And when the application is done inserting data, the cursor handle is released.
With dynamic SQL in PL/SQL, you cannot really follow the optimal approach - unless you use DBMS_SQL (a complex cursor interface). With static SQL, the PL/SQL's optimiser can kick in and it can optimise its access to the cursors your code create and minimise parsing all together.
This is however not the only consideration when using dynamic SQL. Dynamic SQL makes coding a lot more complex. The SQL code can now only be checked at execution time and not at development time. There is the issue of creating shareable SQL cursors using bind variables. There is the risk of SQL injection. Etc.
So dynamic SQL is seldom a good idea. And IMO, the vast majority of people that post problems here relating to dynamic SQL, are using dynamic SQL unnecessary. For no justified and logical reasons. Creating unstable code, insecure code and non-performing code. -
DDL statements and dynamic sql in stored procedure
I created a stored procedure to create and drop tables, using dynamic sql.
When I try to do the inserts using dynamic sql, i.e
v_string := 'INSERT statement';
EXECUTE IMMEDIATE v_string;
I get the following error message:
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at line 63
Line 63 happens to be the line that the EXECUTE IMMEDIATE v_string; statement is in.
I am able to describe the table that the inserts are being made into, so I know that the table exists.
Any idea why I'm getting this error message would be appreciated.Yes I do and I have been able to create other tables using dynamic sql.
The table that I am having problems with SELECTs data from another table to get its column values; within the SELECT statement, the CAST function is used:
ie. CAST(CASE SUBSTR(CAST(E_MOD AS VARCHAR(7)),2,3)
WHEN 'AAA' THEN 'A55'
ELSE ............
I get the following error message:
ERROR at line 18: (this line starts the CAST statement)
ORA-06550: line 18, column 13:
PLS-00103: Encountered the symbol "AAA" when expecting one of the following:
. ( * @ % & = - + ; < / > at in is mod not rem return
returning <an exponent (**)> <> or != or ~= >= <= <> and or
like between into using || bulk
When I remove the quotes or add another single quote, the same error cascades to 'A55'.
After doing the same for the next error, I get the error message below:
ERROR at line 1: (this line has the EXECUTE IMMEDIATE statement)
ORA-00936: missing expression
ORA-06512: at line 6
Any idea what the problem could be?
Also is there another way to have DDL statements as stored procedures other than using dynamic sql or the DBMS_SQL package? -
Execute immediate and "in" operator
Hello!
I want to pass varchar2 type argument to my procedure in format '1,2,3' where 1,2 and 3 are some IDs.
And then, in procedure I write:
stmt := 'select avg(PRICE) from ORDERS where ORDER_ID in (:Ids)';
execute immediate stmt into APrice using ARGUMENT;
I undersand, that this is incorrect, because where clause in executable query is
"where ORDER_ID in ('1,2,3')" but not "where ORDER_ID in (1,2,3)".
Is there any easy way how to solve such a problem?
Maybe I should use other argument type?user10304317 wrote:
I undersand, that this is incorrect, because where clause in executable query isIf you want to use a string you will have to concatenate it into dynamic sql:
stmt := 'select avg(PRICE) from ORDERS where ORDER_ID in (' || ARGUMENT || ')';
execute immediate stmt into APrice;However, it will produce as many sql in shared pool as you will have different ARGUMENT values and each of them will do a hard parse. Or you could use collection and then you do not need dynamic sql (unless select list and/or rest of where clause is dynamic):
SQL> create or replace
2 type num_tbl_type
3 as
4 table of number;
5 /
Type created.
SQL> create or replace procedure p1(
2 p_num_tbl num_tbl_type
3 )
4 is
5 begin
6 for rec in (select empno,ename from emp where empno in (select * from table(p_num_tbl))) loop
7 dbms_output.put_line(rpad(rec.empno,10) || rec.ename);
8 end loop;
9 end;
10 /
Procedure created.
SQL> set serveroutput on
SQL> exec p1(num_tbl_type(7566,7839,7902))
7566 JONES
7839 KING
7902 FORD
PL/SQL procedure successfully completed.
SQL> SY. -
Difficulties with execute immediate and 'in' clause
Hello all,
I have some SQL that will have to run dynamically, which I can get to work by building a long statement, then getting it hard-parsed
example:
sql_stmt VARCHAR2(256) :=
'select distinct some_id from table1
where lname = ''Smith''
and fname in(''Joe'', ''Joey'', ''Joseph'')
and ssn = 111223333';
execute immediate sql_stmt into new_id_value;
the above state executes fine and returns the desired result.
HOWEVER, when I try to use bind variables (this statement will be called several million times), I get a no rows returned error.
I use bind variables as follows:
sql_stmt VARCHAR2(256);
vlname VARCHAR2(50) := 'Smith';
vssn NUMBER := 111223333;
vfname VARCHAR2(100) := '''Joe'', ''Joey'', ''Joseph''';
sql_stmt :=
'select distinct some_id from table1
where lname = :vlname
and fname in(:vfname)
and ssn = :vssn;
execute immediate sql_stmt into new_id_value
using vlname, vfname, vssn;
I know the issue involves the 'in' clause because I've substituted hardcoded values in and it has worked.
any suggestions?Well maybe its all a little confusing, does an end to end demo make it any clearer Mr Bidness?
SQL> create or replace type tabstr_t as table of varchar2(4000)
2 /
Type created.
SQL> create or replace function tabstr (
2 p_str in varchar2,
3 p_sep in varchar2 default ','
4 )
5 return tabstr_t
6 is
7 l_str long := p_str || p_sep;
8 l_tabstr tabstr_t := tabstr_t();
9 begin
10 while l_str is not null loop
11 l_tabstr.extend(1);
12 l_tabstr(l_tabstr.count) := rtrim(substr(
13 l_str,1,instr(l_str,p_sep)),p_sep);
14 l_str := substr(l_str,instr(l_str,p_sep)+1);
15 end loop;
16 return l_tabstr;
17 end;
18 /
Function created.
SQL> var s varchar2(100)
SQL> exec :s := 'king,turner,ward'
PL/SQL procedure successfully completed.
SQL> select ename, sal from emp
2 where ename in (
3 select upper(column_value) from
4 table(cast(tabstr(:s) as tabstr_t))
5 );
ENAME SAL
KING 5000
TURNER 1500
WARD 1250
SQL> exec :s := 'jones,blake,clark'
PL/SQL procedure successfully completed.
SQL> /
ENAME SAL
BLAKE 2850
CLARK 2450
JONES 2975 -
Strange behavior when searching a phrase using reg exp and dynamic sql
Hi,
I have a strange issue while using dynamic sql for an apex page. I have a requirement to search a string in the database column which is entered by user on a page item. The search process should search the whole phrase only.
I have a query generated dynamically in the back end and use it in a cursor in the stored procedure
SELECT t.group_cn , t.group_desc, t.group_type, t.partner_organization_id, t.partner_organization
FROM vr_idm_group t WHERE regexp_like(t.group_desc,'(^|\W)HR Selection & Assignment(\W|$)', 'i')The pl sql code with the dynamic sql statements are below.
IF p_search_process NOT in ('PARTNER') THEN
OPEN v_cursor FOR v_sql;
ELSE
OPEN v_cursor FOR v_sql USING p_search_id;
END IF;
LOOP
FETCH v_cursor INTo v_obj.group_cn, v_obj.group_desc, v_obj.group_type, v_obj.partner_organization_id,
v_obj.partner_organization, v_obj.match_count;
EXIT WHEN v_cursor%NOTFOUND ;
v_search_array.extend;
v_search_array(v_search_array.last) := v_obj;
dbms_output.put_line(v_sql);
END LOOP;The search works fine if the search string does not contain any special character like &,- etc.
However, if the search string contains any special character, it does not return any thing. This strange issue happens only if I call the procedure from the apex page and the search string contains a special character. (please note that the procedure works fine even from apex if the string does not have a special character). When I debugged this, found that, the cursor does not fetch any rows (it is supposed to fetch two rows) for unknown reason. When I run the query separately, it returns the two rows (in which the column group_desc contains the search string "HR Selection & Assignment") as desired. Also, when I test the procedure in the back end (PLSQL developer), it works fine.
Any idea, what is causing this strange behaviour?
Advance thanks.
Regards,
Natarajani don't see anything about a dataProvider. you're assigning a source for a scrollpane. scrollpane's don't have a dataProvider property.
anyway, other than arrayRun always being false when that last if-statement executes, what's the problem? doesn't that movieclip display when that 2nd branch of the last if-statement executes (assuming instance is defined correctly etc)? -
Bind variables and Dynamic sql
I have this function which works only when i'm not passing bind variables. The moment i add bind variables it is not able to execute the function.
Oracle Db Version: 8.1
Thanks
Source Code
FUNCTION TestFunction( In_Test_id in Number,
In_Asof in Date )
Return ScoreType
IS
LvScore ABC.LV_SCORE.SCORE%TYPE;
DVScore ABC.LV_SCORE.SCORE%TYPE;
Begin
EXECUTE IMMEDIATE
'SELECT SCORE,DVSCORE
FROM
SELECT SCORE,DVSCORE
DENSE_RANK() OVER (PARTITION BY TEST_ID ORDER BY ASOF_DT DESC) AS score_RANK
FROM ABC.LV_SCORE
WHERE TEST_ID = :x
AND ASOF_DT <= :y
) WHERE score_RANK = 1'
INTO LvScore,DVScore
USING In_tEST_ID,In_Asof;
Return ScoreType( LvScore,
DVScore);
End;It just keeps on executing for sometime and then disconnects itself from database What was the indication that told you that it disconnected? Was there a visible indication of this disconnect?
Did you get ORA-03113?
===========================================
ORA-03113: end-of-file on communication channel
Cause: The connection between Client and Server process was broken.
Action: There was a communication error that requires further investigation. First, check for network problems and review the SQL*Net setup. Also, look in the alert.log file for any errors. Finally, test to see whether the server process is dead and whether a trace file was generated at failure time. -
Hello All,
Been looking into this for a couple of days, and I keep hitting brick walls, so I'm hoping someone can offer me a bit of inspiration. What I'm trying to do is write a stored procedure that lets the user specify a list of tables, and an output directory, and the SP creates a series of BCP statements that export these tables to comma delimited files.
This wouldn't be too hard, but I need to output the field headings in the first row of the table (and use quotes as text qualifiers). I'm doing this by looping round sys.columns, pulling out all the fieldnames, creating two select statements, and UNION ALL-ing them together. e.g.......
select 'FIELD1','FIELD2','FIELD3','FIELD4'
union all
select field1,field2,field3,field4 from tablename
It all works fine until you try it on a table with a lot of columns. Although you can build a big SQL statement in an NVARCHAR(MAX), BCP only appears to read the first 4000 characters of it, so it fails.
To get round this, I've moved all of the code that builds the big SQL statement to its own stored procedure (i.e. you pass the tablename, and it returns the table with the field names in the first row). Then, I can just call this new SP in my BCP statement, with a couple of parameters.
The problem I'm getting is BCP is complaining saying '[Microsoft][SQL Native Client]BCP host-files must contain at least one column'. I'm setting no count off, and there are no print statements, so I'm assuming this is because the data is getting returned via an exec sp_executesq (although this is a guess). I can't think of a way round this though, as the SQL need to be dynamic.
alter PROCEDURE [dbo].[sp_QBMultiFileExportGetData]
@tablename varchar(100),
@dbname varchar(100)
AS
BEGIN
declare @Execstring as nvarchar(MAX)
declare @currentfieldname as varchar(100)
declare @selectlist as varchar(8000)
declare @fieldnamelist as varchar(8000)
declare @colnames table
columnname varchar(100)
begin
set nocount on
set @execstring='select COLUMN_NAME '+
'from ' + @dbname + '.INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = ''' + @tablename + ''''
insert into @colnames(columnname)
exec sp_executesql @execstring
set @selectlist=''
set @fieldnamelist=''
--Loop through fieldnames, and build two strings
--One for outputting fieldnames and one for selecting the actual data
while exists(select * from @colnames)
begin
select top 1 @currentfieldname=columnname from @colnames
set @selectlist=@selectlist + 'quotename(['+ @currentfieldname + '],char(34)),'
set @fieldnamelist=@fieldnamelist + '''' + @currentfieldname + ''' [' +@currentfieldname + '],'
delete from @colnames where columnname=@currentfieldname
end
--remove last quote
set @selectlist=substring(@selectlist,1,len(@selectlist)-1)
set @fieldnamelist=substring(@fieldnamelist,1,len(@fieldnamelist)-1)
--Built string to execute, with fieldnames, and select fields
set @execstring='select ' + @fieldnamelist + ' union all select ' + @selectlist + ' from ' + @dbname + '..' + @tablename
return exec sp_executesql @execstring
end
END
this returns exactly what I want, but when I try to use it in a BCP statement, I get the error....
i.e.
EXEC master..xp_cmdshell 'bcp "exec QCDev.dbo.sp_QBMultiFileExportGetData ''tablename'',''dbname''" queryout C:\\outputfile.txt -T -t","'
Error = [Microsoft][SQL Native Client]BCP host-files must contain at least one column
Anyone ever tried this before?Hi Guys,
Thanks for the suggestions. I had been trying to avoid temp tables (don't really like them), but I think eventually, they were the only way to go. Unfortunately, this opened a whole can of scoping worms, and after a couple of hours, its all given me a right headache. However, the good news is I've finally got it working as I wanted.
I was finding I was having issues using temp tables, as the tables being used were dynamic, so I would have to create them in a dynamic SQL string, and they weren't propagating upwards from child to parent. I seemed to be getting the same problem using global temporary tables too, although I'm not sure why, as they should have worked They seemed to be out of scope by the time the SP that was calling my sp_QBMultiFileExportGetData tried to output the data. This might possibly have been because BCP wasn't seeing the same scope, but I've not tested it fully (and its very possible I was making a mistake).
The solution was to abandon sp_QBMultiFileExportGetData, and merge the code back into the calling script. However, rather than trying to pass an enormous SQL string to bcp, running it separately with sp_executesql, and dumping the results in a global temp table. Then let bcp just call a 'select * from temptable', to avoid the select statement getting too long. Its not the most elegant solution, but it seems to work fine.
ALTER PROCEDURE [dbo].[sp_QBMultiFileExport]
-- Add the parameters for the stored procedure here
@tablenames varchar(1000), --list of tables to be exported
@outputpath varchar(1000), --output path ***AS SEEN BY THE SERVER, NOT THE CLIENT***
@servername varchar(100), --Server where data resides
@dbname varchar(100), --database name
@delimiter varchar(1) --output delimiter
AS
BEGIN
declare @Execstring as nvarchar(max)
declare @currenttable as varchar(100)
declare @colnames table
columnname varchar(100)
declare @currentfieldname as varchar(100)
declare @selectlist as varchar(max)
declare @fieldnamelist as varchar(max)
--Get rid of CRLFs in the tablenames parameter
set @tablenames=replace(@tablenames,char(10),'')
set @tablenames=replace(@tablenames,char(13),'')
--add extra comma to the end of the list (needed later for consistency)
set @tablenames=@tablenames+','
--Get first table in the list
set @currenttable=substring(@tablenames,1,charindex(',',@tablenames)-1)
while @tablenames<>''
begin
--Get a list of fieldnames from syscols
insert into @colnames(columnname)
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @currenttable
set @selectlist=''
set @fieldnamelist=''
while exists(select * from @colnames)
begin
--get first column name
select top 1 @currentfieldname=columnname from @colnames
--add to select statement lists
set @selectlist=@selectlist + 'quotename(['+ @currentfieldname + '],char(34)),'
set @fieldnamelist=@fieldnamelist + '''' + @currentfieldname + ''' [' +@currentfieldname + '],'
--remove column from temptable
delete from @colnames where columnname=@currentfieldname
end
--remove last quote from field lists
set @selectlist=substring(@selectlist,1,len(@selectlist)-1)
set @fieldnamelist=substring(@fieldnamelist,1,len(@fieldnamelist)-1)
--check for temp table, and drop if necessary
IF object_id('tempdb..##MultiFileExportTempTable') IS NOT NULL
BEGIN
DROP TABLE ##MultiFileExportTempTable
END
--Build list of fieldnames, and select list, unioned together
--and put the results in temptable
set @execstring='select ' + @fieldnamelist + ' into ##MultiFileExportTempTable union all select ' + @selectlist + ' from ' + @dbname + '..' + @currenttable
exec sp_executesql @execstring
--get BCP to pull data back from ##temptable, and dump in file
set @execstring='EXEC master..xp_cmdshell ''bcp "select * from ##MultiFileExportTempTable" queryout ' + @outputpath + '\' + @currenttable + '.txt' + ' -c -T -t"' + @delimiter + '"'''
exec sp_executesql @execstring
--drop tablename from list
set @tablenames=replace(@tablenames,@currenttable + ',','')
--if tablenames list is not empty, get the next one
if @tablenames<>''
set @currenttable=substring(@tablenames,1,charindex(',',@tablenames)-1)
else
set @currenttable=''
end
IF object_id('tempdb..##MultiFileExportTempTable') IS NOT NULL
BEGIN
DROP TABLE ##MultiFileExportTempTable
END
END
So, you call this with...
exec dbo.[sp_QBMultiFileExport] 'table1,table2,table3',filepath,servername,dbname,delimiter
...and it creates delimited files called table1.txt, table2.txt and table3.txt in the specified folder, with field headings and text qualifiers.
Many thanks for all your suggestions
Maybe you are looking for
-
Creating Dynamic Column Names at Runtime
I have a dynamic query that I'm running under Portal. I would like to assign column headings based on the query results. Example: Select a.x "a.name_x", a.y "a.name_y", a.z "a.name_z" from a where a.q = "user input" I know the above example will not
-
IPod touch 4th generation connection problems
My iPod touch indicates that it is connected to wifi (a connection that I frequently used in the past, and use for all my other deivces), and I even full wifi strength (three 'bars'), but I cannot use various apps that connect to the Internet or conn
-
Details not appearing in the dropdown list in the filter window
Dear All, I have come accross a unique problem. I have made a user defined query. Now there is an item code column. I want to filter the item codes in the generated query. But all the items are not appearing in the filter window> item field> dropd
-
Export data to anothe PDF form
Hello all, I have a research company that needs to keep track of all patients we see by entering their initials, date of visit, date of birth and some other simple data in a cumulative log (a PDF form). When the patient comes to our site we gather th
-
Cannot download apps in app store
every time I try to download an app, itunes 9.1.0.8 hangs and I have to stop force quit the app. running windows vista ultimate fully updated also any solutions? thanks, marianne