Execute immediate ignoring hints
Hi
I'm looking for help about an unexpected behavior in oracle. I have a query that it is executed by a stored procedure, and this query has some hints to improve its performance. When I execute the procedure with sqlplus or any other tool, using "exec myprocedure;", the process took between 30 and 40 minutes to complete. But if I call this procedure inside another procedure with execute immediate command, it took more than 5 hours to complete.
The procedure code is
execute immediate 'begin '||proc||'; end;';
proc is a variable that contain the procedure name to run
It seems that oracle are ignoring my hints when it is executed by execute immediate command. In all tests that I've done I used the same user to connect.
The version of oracle is 9.2.0
Tks for any help
> Why would you do this?
Presumably he has a variable like "v_which_procedure" which could have the values 'RAISE_PAY()' or 'FIRE_ALL_EMPLOYEES()', and some logic that determines which to use.
I would agree though that in general it would be better to structure things so that you are not in the position of slotting the name of a procedure dynamically into an EXECUTE IMMEDIATE call.
I don't see how SQL inside a procedure would know that the procedure itself was called dynamically, so the fact that it seems to be performing differently is a bit of a mystery. I would want to be absolutely sure that that was actually what it was doing.
Similar Messages
-
Can't create a sequence within a pl/sql block with execute immediate.
Hi All. I created a user and granted it the 'create sequence' privilege though a role. In a pl/sql block I try to create a sequence using 'execute immediate' but get a 1031-insufficient privileges error. If I grant create sequence directly to the user, the pl/sql block completes successfully. Can anyone explain this behavior? We're running 11.2 Enterprise Editon.
Thanks,
MarkIn a definer's rights stored procedure (the default), you only have access to privileges that have been granted directly, not via a role.
There are two basic reasons for that. First, roles can be enabled or disabled, default and non-default, password-protected, etc. so the set of roles a particular user actually has is session-specific. Oracle needs to know at compile time what privileges the owner of the procedure has. The only way to do that (without deferring the privilege check) is to ignore privileges granted through roles.
Second, since 99% of privilege management DBAs do involves granting and revoking roles, it's helpful that changing role privileges will never cause objects to be marked invalid and recompiled which can have side-effects on applications. DBAs only need to worry about causing problems on those rare cases where they are granting or revoking direct privileges to users.
You can create an invoker's rights stored procedure by adding the clause (AUTHID CURRENT_USER). That defer's the security check to run-time but allows the procedure to see privileges granted through roles in the current session. But that means that the caller of the procedure would need to have the CREATE SEQUENCE privilege through the role, not the owner of the procedure.
And just to make the point, dynamic object creation in PL/SQL is almost always a red flag that there is something problematic in your design. If you are creating sequences dynamically, that means that you'd have to refer to them dynamically throughout your code which means that your inserts would need to use dynamic SQL. That's not a particularly easy or safe way to develop code.
Justin -
How to use using clause in execute immediate statement??
Hi ALL,
Can u help me ....
This is the code which I have written...
declare
type rec_typ is table of forall_test%rowtype;
v_rectype rec_typ:=rec_typ();
begin
--poputating records
for i in 1..10000 loop
v_rectype.extend;
v_rectype(v_rectype.last).id:=i;
v_rectype(v_rectype.last).code:=to_char(i);
v_rectype(v_rectype.last).description:='Description :'||to_char(i);
end loop;
execute immediate 'truncate table forall_test';
forall i in v_rectype.first..v_rectype.last
execute immediate 'insert into forall_test values :1' using v_rectype(i);
commit;
end;
But I am getting this ERROR....
execute immediate 'insert into forall_test values :1' using v_rectype(i);
ERROR at line 14:
ORA-06550: line 14, column 61:
PLS-00457: expressions have to be of SQL types
ORA-06550: line 14, column 1:
PL/SQL: Statement ignored
Thanks & Regards,
T.HalderThatmeans using statement cannot be a non sql type.True: You need an sql type for this:
e.g. with
create or replace type emp_typ
as
object (empno number (4),
ename varchar2 (10 byte),
job varchar2 (9 byte),
mgr number (4),
hiredate date,
sal number (7, 2),
comm number (7, 2),
deptno number (2))
create or replace type emp_tab as table of emp_typ
/you can do
--- an empty test table
SQL> create table emp2
as
select *
from emp
where 1 = 2
Table created.
SQL> declare
emp2_tab emp_tab;
begin
/* fill the collection */
select emp_typ (empno,
ename,
job,
mgr,
hiredate,
sal,
comm,
deptno)
bulk collect into emp2_tab
from emp
where empno like '77%';
-- forall loop
forall c in 1 .. emp2_tab.count
execute immediate 'begin
insert into emp2 select * from table(cast(emp_tab(:1) as emp_tab)) t;
update emp2 set sal = null where empno = (:1).empno and empno = 7788;
end;' using emp2_tab (c);
end;
PL/SQL procedure successfully completed.
SQL> select empno, ename, sal from emp2
EMPNO ENAME SAL
7782 CLARK 2450
7788 SCOTT
2 rows selected. -
Pass Pl/sql table into USING clause in EXECUTE IMMEDIATE statment
Getting error when I try to pass the PL/SQL table into USING clause in EXECUTE IMMEDIATE statment:
Declare
result NUMBER;
TYPE values_tab IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
lv_tab values_tab;
lv_exp varchar2(300);
lv_exec varchar2(300);
BEGIN
lv_tab(1) := 5;
lv_tab(2) := 48;
lv_tab(3) := 7;
lv_tab(4) := 6;
lv_exp := ':b1+:b2+(:b3*:b4)';
lv_exec := 'SELECT '||lv_exp ||' FROM DUAL';
EXECUTE IMMEDIATE
lv_exec
INTO
result
USING
lv_tab;
DBMS_OUTPUT.PUT_LINE(result);
END;
Error at line 1
ORA-06550: line 20, column 12:
PLS-00457: expressions have to be of SQL types
ORA-06550: line 15, column 8:
PL/SQL: Statement ignored
I am trying to evaluate the expression ":b1+:b2+(:b3*:b4)" which is stored in table. This table has different expressions (around 300 expressions). I want to use the bind variables in expression because each expression evaluated thousand of time may be more in some case. If I don't use bind variable then it fill shared pool.
Is there any way I can pass the USING (IN) parameters dynamically instead of writing "USING lv_tab(1), lv_tab(2), lv_tab(3), lv_tab(4)"? As number of input parameters change depend on the expression in the table.
If not possible please suggest any other ideas/approches
Please help..
Edited by: satnam on Jun 11, 2009 11:50 AMWell, you keep changing reqs faster I can keep up. Anyway, assuming N-th bind variable (left-to-right) corresponds to collection N-th element:
Declare
result NUMBER;
lv_tab values_tab := values_tab();
lv_exp varchar2(300);
lv_exec varchar2(300);
lv_i number := 0;
BEGIN
lv_tab.extend(4);
lv_tab(1) := 5;
lv_tab(2) := 48;
lv_tab(3) := 7;
lv_tab(4) := 6;
lv_exp := ':5000135+:5403456+(:5900111*:5200456)';
lv_exec := lv_exp;
While regexp_like(lv_exec,':\d+') loop
lv_i := lv_i + 1;
lv_exec := REGEXP_REPLACE(lv_exec,':\d+',':b(' || lv_i || ')',1,1);
end loop;
lv_exec := 'BEGIN :a := ' || lv_exec || '; END;';
DBMS_OUTPUT.PUT_LINE(lv_exec);
EXECUTE IMMEDIATE lv_exec USING OUT result,IN lv_tab;
DBMS_OUTPUT.PUT_LINE(result);
END;
BEGIN :a := :b(1)+:b(2)+(:b(3)*:b(4)); END;
95
PL/SQL procedure successfully completed.
SQL> SY. -
Execute immediate 'alter session set current_schema = ' failed in PL/SQL
Hi
I am trying to run
EXECUTE IMMEDIATE 'ALTER SESSION SET CURRENT_SCHEMA = TEST ' ;
in a pl/sql block but it is failing.Can anyone update me on this.
CREATE OR REPLACE PROCEDURE test3
IS
A_COUNT NUMBER(15);
BEGIN
EXECUTE IMMEDIATE 'ALTER SESSION SET CURRENT_SCHEMA = TEST ' ;
SELECT COUNT(*) INTO A_COUNT FROM (
select id from solutions );
END;
/The user who owns the procedure needs to be granted direct select rights on table test.solutions (not via a role). Still will not help. Look what OP is trying to do. In a stored procedure owned by some user (other than TEST) OP is trying to reference user TEST owned table solution without prefixing it with owner. Something like:
SQL> create table u1.test_tbl(x number);
Table created.
SQL> select * from test_tbl;
select * from test_tbl
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> alter session set current_schema = U1;
Session altered.
SQL> select * from test_tbl;
no rows selected
SQL> However, OP tries to do it in a SP using dynamic SQL to change current schema to test. Such change will occur when SP will be executed, not when is it compiled. At compile time we are still under SP owner's schema and therefore select from solutions implies table solutions owned by SP owner, not by TEST. The only way to make SP compile and work OK is to select from solutions also dynamically:
SQL> select sys_context('userenv','current_schema') from dual
2 /
SYS_CONTEXT('USERENV','CURRENT_SCHEMA')
SCOTT
SQL> CREATE OR REPLACE PROCEDURE test3
2 IS
3 A_COUNT NUMBER(15);
4 BEGIN
5 EXECUTE IMMEDIATE 'ALTER SESSION SET CURRENT_SCHEMA = U1' ;
6 SELECT COUNT(*) INTO A_COUNT FROM (
7 select x from test_tbl );
8 END;
9 /
Warning: Procedure created with compilation errors.
SQL> sho err
Errors for PROCEDURE TEST3:
LINE/COL ERROR
6/1 PL/SQL: SQL Statement ignored
7/15 PL/SQL: ORA-00942: table or view does not exist
SQL> set serveroutput on
SQL> CREATE OR REPLACE PROCEDURE test3
2 IS
3 A_COUNT NUMBER(15);
4 c sys_refcursor;
5 BEGIN
6 EXECUTE IMMEDIATE 'ALTER SESSION SET CURRENT_SCHEMA = U1' ;
7 OPEN C FOR 'SELECT COUNT(*) FROM (select x from test_tbl )';
8 FETCH c INTO A_COUNT;
9 dbms_output.put_line(a_count);
10 CLOSE c;
11 END;
12 /
Procedure created.
SQL> insert into u1.test_tbl select rownum from emp;
14 rows created.
SQL> exec test3
14
PL/SQL procedure successfully completed.
SQL> Obviously, as you noted SP owner must have directly granted select on test3.solutions.
SY. -
Can I issue this command in PL/SQL: EXECUTE IMMEDIATE '@filename.sql';
can I issue this command in PL/SQL: EXECUTE IMMEDIATE '@filename.sql';
Hi,
Rather the opening a new process (sqlplus), a new connection (need password) etc... I would rather read and execute the file in pl/sql.
I do not know if someone wrote it already, but here is a quick and dirty code for doing that with UTL_FILE.GET_LINE
Here, I am only processing some DML statements and no SELECT statements. Correct it as you like !
CREATE OR REPLACE PROCEDURE run_script ( dir_name IN VARCHAR2,file_name IN VARCHAR2)
IS
vSFile UTL_FILE.FILE_TYPE;
vCmd VARCHAR2(200);
vNewLine VARCHAR2(200);
BEGIN
vSFile := UTL_FILE.FOPEN(dir_name, file_name,'r');
vCmd := NULL;
IF UTL_FILE.IS_OPEN(vSFile) THEN
LOOP
BEGIN
UTL_FILE.GET_LINE(vSFile, vNewLine);
if (vCmd is null) THEN
if (upper(vNewLine) like 'INSERT%' or upper(vNewLine) like 'UPDATE%' or upper(vNewLine) like 'DELETE%') THEN
if (vNewLine like '%;') THEN
/* we have a single line command, execute it now */
dbms_output.put_line(substr(vNewLine,1, length(vNewLine)-1));
execute immediate substr(vNewLine,1, length(vNewLine)-1);
else
/* we have a command over multiple line, set vCmd */
vCmd := vNewLine;
end if;
else
/* ignore the rest like spool, prompt, accept, errors, host, @, ... */
null;
end if;
else
if (vNewLine like '%;') THEN
/* we have a the last line of the command, execute it now */
vCmd := vCmd || ' ' || substr(vNewLine,1, length(vNewLine)-1);
dbms_output.put_line(vCmd);
execute immediate vCmd;
vCmd := null;
else
/* keep concatenating to vCmd */
vCmd := vCmd ||' '|| vNewLine;
end if;
end if;
EXCEPTION
WHEN NO_DATA_FOUND THEN
EXIT;
END;
END LOOP;
COMMIT;
END IF;
UTL_FILE.FCLOSE(vSFile);
EXCEPTION
WHEN utl_file.invalid_path THEN
RAISE_APPLICATION_ERROR (-20052, 'Invalid File Location');
WHEN utl_file.read_error THEN
RAISE_APPLICATION_ERROR (-20055, 'Read Error');
WHEN others THEN
RAISE_APPLICATION_ERROR (-20099, 'Unknown Error');
END run_script;
set serverout on
create directory scriptdir as '/home/oracle';
grant read,write on directory to scott;
exec run_script('SCRIPTDIR', 'test.sql') -
Creating cursor using Execute immediate
I am trying to create one cursor using a for loop, but I am not able to do so, could you please help me with the approach to get it done.
Here is the scenario:
I have one table table_1,it contains 2 columns source_query , target_query.
source_query and target_query are Select statements like source_query is Select name, age , valid from customer where customer_id=123456;
I fetched the data from these columns into 2 strings
select source_query into source_data from table_1;
select target_query into target_data from table_1;
Now out of these 2 I want to create 2 cursors, so that I can compare the column values one by one ( I am not using the source minus target approach because of difference in the data type).
I have to individually check the values.
So here are the cursors:
For source_data_value in ( EXECUTE immediate source_data)
LOOP
For target_data_value in (EXECUTE IMMEDIATE target_data)
LOOP
<executable statements>;
END LOOP;
END LOOP;
But the cursor creation is failing in the procedure.
Please let me know if it is possible to create a cursor using the execute immediate , if not what approach I should use other than this?Why exactly you are doing this inside a procedure. You can take the SQL's out and write a simple query to retrieve the data. Anyways, to work it out in a procedure, I can think of the below solution. I am trying to do away with Execute Immediate and use REF cursor. Please note that this is untested and just a try to present a possible solution which can be changed to implement your original requirement. I haven't done anything sort of this before, so if this approach doesn't approach, kindly ignore
DECLARE
TYPE TempTyp IS REF CURSOR;
temp_cv TempTyp;
temp_cv_2 Temptyp;
emp_rec emp%ROWTYPE;
source_data VARCHAR2(200);
target_data VARCHAR2(200);
BEGIN
source_data:= 'SELECT * FROM source tablej';
target_Date :='select * from target table';
OPEN temp_cv FOR source_data;
LOOP
FETCH temp_cv INTO emp_rec;
EXIT WHEN emp_cv%NOTFOUND;
OPEN temp_cv_2 FOR target_data;
FETCH Temp_cv_2 into emp_rec emp%ROWTYPE
loop
< And then your comparisons here >
END LOOP:
CLOST TEMP_CV_2;
END LOOP;
CLOSE temp_cv;
END;
Ishan -
Execute immediate a procedure call
Hi,
I need some help, can some one EXPLAIN why its failing when i don't specify the test_proc in spec.
i know this is not the right way of doing things. want to know why i need to specify the procedure name in spec.
SQL> select * from v$version;
BANNER
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE 11.2.0.2.0 Production
TNS for Linux: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
SQL> CREATE OR REPLACE PACKAGE PkgTest AS
2
3 --PROCEDURE test_proc;
4 PROCEDURE run_proc;
5 END PkgTest;
6 /
Package created.
SQL>
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY PkgTest AS
2
3 PROCEDURE test_proc IS
4 BEGIN
5 dbms_output.put_line(' Test Proc');
6 END test_proc;
7
8 PROCEDURE run_proc IS
9 BEGIN
10 EXECUTE IMMEDIATE 'begin PkgTest.test_proc; end;';
11 END run_proc;
12 END PkgTest;
13 /
Package body created.
SQL> exec pkgtest.run_proc;
BEGIN pkgtest.run_proc; END;
ERROR at line 1:
ORA-06550: line 1, column 16:
PLS-00302: component 'TEST_PROC' must be declared
ORA-06550: line 1, column 8:
PL/SQL: Statement ignored
ORA-06512: at "MPIEFP_DEV.PKGTEST", line 10
ORA-06512: at line 1
SQL> CREATE OR REPLACE PACKAGE PkgTest AS
2
3 PROCEDURE test_proc;
4 PROCEDURE run_proc;
5 END PkgTest;
6 /
Package created.
SQL> exec pkgtest.run_proc;
Test Proc
PL/SQL procedure successfully completed.
SQL> spool offHi,
If you tried to run this command from PL/SQL
SQL> EXEC PkgTest.test_proc;
do you understand why it would fail? It fails in EXECUTE IMMEDIATE for the same reason.
When you use EXECUTE IMMEDIATE, Oracle runs the dynamic command in a new, separate environment. It knows nothing about the context from which it was called. In particular, it doesn't know if it was called from inside a package or not, so procedures that are private to that package can't be called.
Do you really need to use EXECUTE IMMEDIATE? You obviously don't in the simple test scenario you posted, but I assume your real package is much more complicated.
Why not simply include test_proc in the package spec?
Is the problem that end users, who are allowed to cal run_proc, are not supposed to call test_proc direrctly? If so, put them in different pacakges. Declare test_proc in the spec of its package, but don't grant privileges on the package that end users. -
Disadvantage with 'Execute Immediate'
What is the disadvantage with 'EXECUTE IMMEDIATE'.
I think you guys are missing the point here.
None of the issues listed are 'EXECUTE IMMEDIATE' disadvantages.
'EXECUTE IMMEDIATE' is a tool. Like DMS_SQL. Like ref cursors. Like explicit cursor. Like implicit cursors.
A tool, any tool, needs to be used correctly. If you use a hammer and hit a nail so hard that it bents, causing the hammer to slip doing some serious damage to your thumb... whose fault it is?
Is it The Hammer that is at fault here? Or is the user of that tool?
There are no disadvantages to using 'EXECUTE IMMEDIATE'. It is a tool. But like all tools it needs to be used correctly and safely. Things like excessive hard parsing because of a severe lack of bind variables, or opening a hole for SQL injection, etc.. all these are symptoms of - and let's be blunt here - an ignorant developer. It has nothing to do with the tool 'EXECUTE IMMEDIATE'.
And those same type of errors will be made by Mr Ignorant Developer using other tools in Oracle.
Shoddy workmanship is not because of poor tools. Shoddy code is not because of using a specific feature (like execute immediate).
The proper question to ask is thus not "what are the disadvantages of execute immediate", but rather "where should I typically use execute immediate and how?".
Not every developer will know how to use every single tool in the toolbox (I sure don't know all the tools in the Oracle toolbox). So there is nothing wrong with asking.
But asking what is "wrong" with a tool (aka "what are the disadvantages") is in my view seriously missing the point that a tool is there to solve very specific types of problems...
That is what a developer should be after - How to use the tool correctly. -
Problems using DDL & EXECUTE IMMEDIATE in package
Hi...
I have an 8i package in which I am trying to execute some DDL via EXECUTE IMMEDIATE to create temporary tables from which I then populate a REF_CURSOR by selecting from the last table created in the DDL. The problem is that the compiler doesn't seem to like the DDL.
Here's what I'm using:
CREATE OR REPLACE PACKAGE BODY NEREP_REF
AS
Procedure GetNE_REF (
i_Node IN VARCHAR2,
io_cursor IN OUT t_cursor )
IS
sql_stmt varchar2(200);
v_cursor t_cursor;
BEGIN
sql_stmt := 'CREATE TABLE tmp AS SELECT * FROM nerep4;';
EXECUTE IMMEDIATE sql_stmt;
OPEN v_cursor FOR
SELECT NE_Node, NE_Type, EHA, Status, Curr_Func, TP_Name,
Order_Item_Name, Required_Start, Required_End, Trail_Name
FROM tmp
WHERE NE_Node = i_Node ;
io_cursor := v_cursor;
END GetNE_REF;
END NEREP_REF;
The problem is that when I compile the package I get the errors below:
SQL> @sp_nerep_body
Warning: Package Body created with compilation errors.
SQL> show err
Errors for PACKAGE BODY NEREP_REF:
LINE/COL ERROR
20/7 PL/SQL: SQL Statement ignored
23/14 PLS-00201: identifier 'NE_NODE' must be declared
So it seems that it doesn't like the DDL (have I got the sql_stmt assignment in the wrong place maybe?) and then it complains it can't find the columns, which is reasonable because of course it doesn't know that the table 'tmp' comes from the result of the DDL statement!
If I change the table name in the 'OPEN v_cursor FOR' select clause to a table that already exists (ie: not created in this package) it runs just fine and I get the data I asked for... the problem is that I need to create this table on the fly by using DDL in my package!
This is driving me crazy - basically I need to be able to execute DDL to do various 'create table ... as select ... from ...' statements which eventually builds a final table which I then want to populate using a REF_CURSOR so I can return the results back to ASP via ADO... but I just can't get the DDL bit to work no matter what I try!!
Can anyone see what I'm doing wrong here?
Mike.
nullHere are a some ideas to try:
Remove the extra semicolon from your sql_stmt, so that line reads:
sql_stmt := 'CREATE TABLE tmp AS SELECT * FROM nerep4';
Ensure that you have proper privileges as an individual user, not just through a role, by:
connecting to the database using username system and password manager and granting yourself the proper privileges. For example, if you are user SCOTT, then:
SQL> GRANT CREATE TABLE TO SCOTT;
Then, exit and connect as yourself and try to compile and execute your procedure again.
If that still doesn't work, try testing one little piece at a time until you can identify the part that causes trouble. For example, start with a procedure that does nothing but try to create the tmp table using execute immediate, then add the other pieces, then try to put the procedure in a package. -
EXECUTE IMMEDIATE within Procedure doesn't work!!
Hi,
I have a code in which the procedure is successfully created, but when I try to check if the table TEST_TABLE is created (ex, DESC TEST_TABLE) it generates an error:
ORA-04043: object TEST_TABLE does not exist
Which means that my EXECUTE IMMEDIATE didn't work within the procedure for some reason, while it works perfectly alone without the procedure!!
Hope you help me with this..
Here's the my code:
CREATE OR REPLACE PROCEDURE TEST_IMM1
AS
BEGIN
EXECUTE IMMEDIATE ' CREATE TABLE TEST_TABLE (ITEM_DESC VARCHAR2(10))';
END;
--Procedure created.
DESC TEST_TABLE
ERROR:
ORA-04043: object TEST_TABLE does not existuser11921409 wrote:
Thanks a lot Ahmed, yes it worked after executing the procedure and table is created. But that's only one part of the problem, in which after dynamically creating the table TEST_TABLE, I should be able to insert data to it such as:
CREATE OR REPLACE PROCEDURE TEST_IMM1
AS
BEGIN
EXECUTE IMMEDIATE ' CREATE TABLE TEST_TABLE (ITEM_DESC VARCHAR2(10))';
END;
--Procedure created.
CREATE OR REPLACE PROCEDURE INSERT_TEST_TABLE
AS
BEGIN
TEST_IMM1;
INSERT INTO TEST_TABLE VALUES ('A');
END;
--Warning: Procedure created with compilation errors.
PL/SQL: SQL Statement ignored
PL/SQL: ORA-00942: table or view does not exist
Can you tell me how to use INSERT with EXECUTE IMMEDIATE.
Thanks :)Just as an FYI, this is really not a good methodology to program in Oracle. If you're doing this for purely learning purposes then it's less 'bad', but if you plan on programming as a career in Oracle, this isn't the method you'd want to adopt (i'll not say there is NEVER a case for something like this, but it's a small percentage of the typical use cases).
You would do better to create a global temporary table if you need a table to muck around with in a session, or create a permanent table (likely not via procedures) and have it persist in the schema of your choice.
Utilizing execute immediate for insert statements, especially without BIND VARIABLES, will create a sad day for your database. -
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. -
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 -
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. -
Hi!
I created a dynamically generated tabular form - the number of columns is not known in advanced. Each cell of the form is a text item generated with apex_item.text().
I want to write an after-submit process that saves the values from the form into a database table. In this process I already know how many columns there are in the report so I want to do the following:
--for each row...
for i in 1..apex_application.g_f01.count loop
-- and for each column in that row (number of columns is in v_col_count)
for j in 1..v_col_count loop
-- get the value of text item
v_query := 'select apex_application.g_f0' || j || '(' || i || ')' || ' from dual';
execute immediate v_query into v_value;
-- now do some DML with v_value
end loop;
end loop;The problem is that I get an error: ORA-06553: PLS-221: 'G_Fxx' is not a procedure or is undefined where xx is the number from the generated query.
My question is - am I doing something wrong or is is just not possible to reference apex_application.g_fxx in "execute immediate"? Will I have to manually check for all 50 possibilites of apex_application.g_fxx? Is there another way?
TIA,
JureWell now I know what was wrong and what you were trying to tell me - apex_application.g_fxx is not visible in "plain" SQL. And now I also have a solution to this problem. The point is to wrap the select statement with begin - end block so that the statement is rendered as pl/sql:
--for each row...
for i in 1..apex_application.g_f01.count loop
-- and for each column in that row (number of columns is in v_col_count)
for j in 1..v_col_count loop
-- get the value of text item
v_query := 'begin select apex_application.g_f0' || j || '(:i)' || ' into :x from dual; end;';
execute immediate v_query using i, out v_value;
-- now do some DML with v_value
end loop;
end loop;This works great :).
Jure
Maybe you are looking for
-
How can i reset my IPad password if i am locked out
My Ipad is disbled and i dont have the computer that i last synced it on how can i restore my IPad or change the password so i can get into it?
-
SQL Server 2012 - Clustered installation fails - cannot locate MSIs
Hi forum I have a query relating to SQL Server 2012 installation, on Windows Server 2012 R2 - SQL Server is Enterprise, Windows is SQL Server Standard Edition. Our windows team have created two Windows Server 2012 machines, and installed and got clus
-
Where will we find the attached docs for SC or PO?
Hi All, We have a requirement in which we need to send the approval offline email with the attached docs for PO or SC . i checked the FM BBP_PD_SC_GETDETAIL in the table ET_ATTACH . but in these i am getting the attached doc in some other format (D0C
-
Maps not working in lumia 620 after phone udate
My maps r not working after phone update. Plz help
-
Schedule line confirmation on next working day
Hi, For a sales org, (IE93) in a sales order if we request delivery on 25.12.2009 (Xmas day), APO availability check is performed and it is confirming on the next/prior working day. But in case of other sales org(GB93) it is confirming on the same da