Execute immediate a sql block of istructions
Hello,
i need to to do something like this:
execute immediate par;
where par is a big file stored in a table that is simply a pl/sql script like this
comment on table SOMETABLE.COLUMN is 'this' ;
comment on table SOMETABLE.COLUMN2 is 'this' ;
and so on for 45 columns. when i try it say that ; is not a valid character. It works only if i put only a row in the table.
How i can put more istructions in a string to be "execute immediate"
Thanks
Edited by: user12195888 on 10-nov-2009 7.59
In the example already provided be aware that if you have commands that aren't supported in PL/SQL like COMMENT this approach may not work. Here is an example that breaks the string up on the semi-colon terminator:
SQL> DROP TABLE A;
Table dropped.
SQL> DROP TABLE B;
Table dropped.
SQL> DROP TABLE C;
Table dropped.
SQL> DROP TABLE INSTRUCTION_TEST;
Table dropped.
SQL>
SQL> CREATE TABLE A (ID NUMBER);
Table created.
SQL> CREATE TABLE B (ID NUMBER);
Table created.
SQL> CREATE TABLE C (ID NUMBER);
Table created.
SQL> CREATE TABLE INSTRUCTION_TEST
2 (
3 INSTRUC VARCHAR2(4000)
4 );
Table created.
SQL>
SQL> INSERT INTO INSTRUCTION_TEST
2 VALUES
3 (
4 'COMMENT ON TABLE A IS ''Table A''; COMMENT ON TABLE B IS ''Table B''; COMMENT ON TABLE C IS ''Table C'';'
5 );
1 row created.
SQL>
SQL> DECLARE
2 BEGIN
3 FOR r IN
4 (
5 WITH instructions AS
6 (
7 SELECT ';' || INSTRUC AS INST
8 FROM INSTRUCTION_TEST
9 )
10 SELECT SUBSTR
11 (
12 INST
13 , INSTR(INST,';',1,LEVEL) + 1
14 , INSTR(INST,';',1,LEVEL+1) - INSTR(INST,';',1,LEVEL) - 1
15 ) AS INDIVIDUAL_STATEMENT
16 FROM instructions
17 CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(INST,'[^;]','')) - 1
18 )
19 LOOP
20 --DBMS_OUTPUT.PUT_LINE(r.INDIVIDUAL_STATEMENT);
21 EXECUTE IMMEDIATE r.INDIVIDUAL_STATEMENT;
22 END LOOP;
23 END;
24 /
PL/SQL procedure successfully completed.
SQL> SELECT * FROM ALL_TAB_COMMENTS WHERE TABLE_NAME IN ('A','B','C');
OWNER TABLE_NAME TABLE_TYPE COMMENTS
TEST_USER C TABLE Table C
TEST_USER B TABLE Table B
TEST_USER A TABLE Table AHTH!
Similar Messages
-
Obtaining a collection as a return from an execute immediate pl/sql block
version 10.2
I need to obtain the collection back from the execute immediate of a pl/sql block:
procedure block(owner varchar2) is
stmt long;
objecttab_coll dbms_stats.objecttab;
begin
stmt := '
begin
dbms_stats.gather_schema_stats(''' || owner || '''
,options => ''LIST AUTO''
,objlist => :objecttab_coll
end;';
execute immediate stmt returning into objecttab_coll;
-- do more stuff here
end block;I have tried this + a few variations but with no luck. In looking through the docs I do not see an example. can this be done?
Thanks
OxI dont find any need for an execute immediate here. This must be just enough.
procedure block(owner varchar2)
is
objecttab_coll dbms_stats.objecttab;
begin
dbms_stats.gather_schema_stats(ownname => owner, options => 'LIST AUTO', objlist => objecttab_coll);
-- do more stuff here
end block;Thanks,
Karthick. -
Executing a PL/SQL block (using Toplink)
I have a scenario where I need to execute some fairly complex PL/SQL blocks. As a tester, I am attempting to execute the following simple block:
declare val NUMBER := 1; begin val := 2; end;
Both wrapping this in an SQLCall, or a DataReadQuery give the following exception. What is the best way to execute a PL/SQL block using Toplink?
Local Exception Stack:
Exception [TOPLINK-4002] (Oracle TopLink - 10g Release 3 (10.1.3.0.0) (Build 060118)): oracle.toplink.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: ORA-00900: invalid SQL statement
Error Code: 900
Call: declare val NUMBER := 1; begin val := 2; end;
Query:DataReadQuery()
at oracle.toplink.exceptions.DatabaseException.sqlException(DatabaseException.java:290)
at oracle.toplink.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:570)
at oracle.toplink.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:442)
at oracle.toplink.threetier.ServerSession.executeCall(ServerSession.java:453)
at oracle.toplink.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:117)
at oracle.toplink.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:103)
at oracle.toplink.internal.queryframework.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:174)
at oracle.toplink.internal.queryframework.DatasourceCallQueryMechanism.executeSelect(DatasourceCallQueryMechanism.java:156)
at oracle.toplink.queryframework.DataReadQuery.executeNonCursor(DataReadQuery.java:118)
at oracle.toplink.queryframework.DataReadQuery.executeDatabaseQuery(DataReadQuery.java:110)
at oracle.toplink.queryframework.DatabaseQuery.execute(DatabaseQuery.java:603)
at oracle.toplink.queryframework.DataReadQuery.execute(DataReadQuery.java:96)
at oracle.toplink.publicinterface.Session.internalExecuteQuery(Session.java:2062)
at oracle.toplink.publicinterface.Session.executeQuery(Session.java:981)
at oracle.toplink.publicinterface.Session.executeQuery(Session.java:938)Could you try the following:
Session s = ...
DataModifyQuery dmq = new DataModifyQuery();
SQLCall sqlCall = new SQLCall();
sqlCall.setQueryString(
"declare\n" +
" val NUMBER := 1;\n" +
"begin\n" +
" val := 2;\n" +
"end;");
sqlCall.setQuery(dmq);
dmq.setCall(sqlCall);
s.executeQuery(dmq); -
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') -
Dyn sql execute immediate A plsql block returning sql%rowcount of rows inserted
I would like to get the number of rows inserted in a dynamic sql statement like following.
execute immediate
'begin insert into a(c1,c2,c3)
(select ac1,ac2,ac3 from ac where ac1=:thekey
UNION select tc1,tc2,tc3 from tc where tc1=:otherkey); end;' using in key1,in key2;
I have tried per the oracle8i dyn sql chapter in doc RETURN sql%rowcount won't compile.
also add this to statement 'returning sql%rowcount into :rowcount'
no luck.
any ideas.?
thanks.Quick comment first - I'm not sure why you are even using dynamic SQL here. There is nothing dynamic about your statement. It is equivalent to just:
insert into a (c1, c2, c3)
select ac1, ac2, ac3
from ac
where ac1 = key1
UNION
select tc1, tc2, tc3
from tc
where tc1 = key2;Unless you are really dynamically changing a table or column name here and just didn't show it in your example, you certainly don't want the overhead of NDS for this insert in this situation.
In any case, you just need to evaluate SQL%ROWCOUNT in the next statement.
insert ...;
if sql%rowcount = 0 then
-- nothing was inserted
end if; -
Help on Execute Immediate Dynamic Sql
Hi all
when i run the following Pl/SQL,nothing is happening
I want to pass array to following procedure
DECLARE
SQL_STMT VARCHAR2(1000);
BEGIN
SQL_STMT := 'Select '|| '''populate_table_test(''' || '|| chr(39)||id_name||chr(39)||' ||''','''||'|| chr(39)||attribute1||chr(39)||' ||''','''||'|| chr(39)||attribute2||chr(39)||' ||''');'''||' from table_test1';
dbms_output.put_line(sql_stmt);
execute immediate sql_stmt;
Exception when others then
dbms_output.put_line(sqlerrm);
end;
SQL> ed
Wrote file afiedt.buf
1 Select 'populate_table_test('|| chr(39)||id_name||chr(39)||','||
2 chr(39)||attribute1||chr(39)||','|| chr(39)||attribute2||chr(39)||');' from
3* table_test
SQL> /
'POPULATE_TABLE_TEST('||CHR(39)||ID_NAME||CHR(39)||','||CHR(
populate_table_test('AAA','AA','AA');
populate_table_test('AAA','AA','AA');
CREATE
TABLE TABLE_TEST1
"ID_NO" NUMBER(10,0) ,
"ID_NAME" VARCHAR2(10 BYTE),
"ATTRIBUTE1" VARCHAR2(10 BYTE),
"ATTRIBUTE2" VARCHAR2(10 BYTE)
Insert into TABLE_TEST1 (ID_NO,ID_NAME,ATTRIBUTE1,ATTRIBUTE2) values (null,'AAA','AA','AA');
Insert into TABLE_TEST1 (ID_NO,ID_NAME,ATTRIBUTE1,ATTRIBUTE2) values (null,'AAA','AA','AA');
commit;
CREATE TABLE TABLE_TEST
(ID_NO NUMBER(10) ,
id_NAME VARCHAR2(10) ,
ATTRIBUTE1 VARCHAR2(10),
ATTRIBUTE2 VARCHAR2(10)
select * from "TABLE_TEST";
CREATE OR REPLACE TYPE T_TYPE IS OBJECT (
id_NAME VARCHAR2(10),
ATTRIBUTE1 VARCHAR2(10),
ATTRIBUTE2 VARCHAR2(10)
Create or replace type TB_T_TYPE as varray(200) of T_TYPE ;
CREATE OR REPLACE
PROCEDURE POPULATE_TABLE_TEST (EXAMPLE IN TB_T_TYPE) AS
begin
FOR I IN 1..EXAMPLE.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(TREAT(EXAMPLE(I) AS T_TYPE).ID_NAME);
DBMS_OUTPUT.PUT_LINE(TREAT(EXAMPLE(I) AS T_TYPE).ATTRIBUTE1);
DBMS_OUtPUT.PUT_LINE(TREAT(EXAMPLE(I) AS T_TYPE).ATTRIBUTE2);
insert into TABLE_TEST(id_name,attribute1,attribute2)
values (treat(example(i) as T_TYPE).id_NAME,
treat(example(i) as T_TYPE).ATTRIBUTE1,
treat(example(i) as T_TYPE).ATTRIBUTE2
end loop;
end; Select 'populate_table_test('|| chr(39)||id_name||chr(39)||','||
chr(39)||attribute1||chr(39)||','|| chr(39)||attribute2||chr(39)||');' from
table_test
Edited by: user1849 on Nov 30, 2011 12:40 PM
Edited by: user1849 on Nov 30, 2011 1:18 PMuser1849 wrote:
Hi all
when i run the following Pl/SQL,nothing is happeningRemember to issue the SQL*Plus command
SET SERVEROUTPUT ONbefore running it; otherwise, you won't see the output from dbms_output.
>
I want to pass array to following procedureIs this a procedure or an anonymous PL/SQL block?
If it's a procedure, post the entire procedure, starting with CREATE [OR REPLACE] PROCEDURE...
Never write, let alone post, unformatted code. Indent the code to show the scope of BEGIN, LOOP, etc.
DECLARE
SQL_STMT VARCHAR2(1000);
BEGIN
SQL_STMT := 'Select '|| '''populate_table_test(''' || '|| chr(39)||id_name||chr(39)||' ||''','''||'|| chr(39)||attribute1||chr(39)||' ||''','''||'|| chr(39)||attribute2||chr(39)||' ||''');'''||' from table_test1';
dbms_output.put_line(sql_stmt);
execute immediate sql_stmt;
Exception when others then
dbms_output.put_line(sqlerrm);
end;
/Only use an EXCEPTION handler when you can improve on the default error handling. The default is to print an error message, so there's no point in you explicitly doing the same.
Why do you need dynamic SQL? Post the output results you want to get from the sample data you posted.
Given that you do need dynamic SQL, why can't you use bind variables, rather than including the values as literals?
Given that you have to use literals, use Q-notation for strings that include single-quote characters.
http://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements003.htm#sthref337
For example:
... SQL_STMT := Q{'Select populate_table_test ('}'
|| id_name
|| Q'{','}'
|| attribute1
|| Q'{','}'
SQL> ed
Wrote file afiedt.buf
1 Select 'populate_table_test('|| chr(39)||id_name||chr(39)||','||
2 chr(39)||attribute1||chr(39)||','|| chr(39)||attribute2||chr(39)||');' from
3* table_test
SQL> /
'POPULATE_TABLE_TEST('||CHR(39)||ID_NAME||CHR(39)||','||CHR(
populate_table_test('AAA','AA','AA');
populate_table_test('AAA','AA','AA');
CREATE
TABLE TABLE_TEST1
"ID_NO" NUMBER(10,0) ,
"ID_NAME" VARCHAR2(10 BYTE),
"ATTRIBUTE1" VARCHAR2(10 BYTE),
"ATTRIBUTE2" VARCHAR2(10 BYTE)
Insert into TABLE_TEST1 (ID_NO,ID_NAME,ATTRIBUTE1,ATTRIBUTE2) values (null,'AAA','AA','AA');
Insert into TABLE_TEST1 (ID_NO,ID_NAME,ATTRIBUTE1,ATTRIBUTE2) values (null,'AAA','AA','AA');
commit;
Thanks for posting the CREATE TABLE and INSERT statements; that's very helpful.
Is that the best sample data for testing? Wouldn't it be better to have at least one row that was not the same as all the others?
CREATE TABLE TABLE_TEST
(ID_NO NUMBER(10) ,
id_NAME VARCHAR2(10) ,
ATTRIBUTE1 VARCHAR2(10),
ATTRIBUTE2 VARCHAR2(10)
select * from "TABLE_TEST";
CREATE OR REPLACE TYPE T_TYPE IS OBJECT (
id_NAME VARCHAR2(10),
ATTRIBUTE1 VARCHAR2(10),
ATTRIBUTE2 VARCHAR2(10)
Create or replace type TB_T_TYPE as varray(200) of T_TYPE ;
CREATE OR REPLACE
PROCEDURE POPULATE_TABLE_TEST (EXAMPLE IN TB_T_TYPE) AS
begin
FOR I IN 1..EXAMPLE.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(TREAT(EXAMPLE(I) AS T_TYPE).ID_NAME);
DBMS_OUTPUT.PUT_LINE(TREAT(EXAMPLE(I) AS T_TYPE).ATTRIBUTE1);
DBMS_OUtPUT.PUT_LINE(TREAT(EXAMPLE(I) AS T_TYPE).ATTRIBUTE2);
insert into TABLE_TEST(id_name,attribute1,attribute2)
values (l_t_seq(i),
treat(example(i) as T_TYPE).id_NAME,
treat(example(i) as T_TYPE).ATTRIBUTE1,
treat(example(i) as T_TYPE).ATTRIBUTE2
end loop;
end; You're trying to INSERT 4 values into 3 columns. Did you mean to say "insert into TABLE_TEST( *id_no,* id_name,attribute1,attribute2)"?
What is l_t_seq? Post complete test scripts that people can run to re-create the problem and test their ideas. -
Execute Immediate with SQL in Stored Procedure
Dear Experts, Please help / guide on below statement which i want to execute in stored procedure,
EXECUTE IMMEDIATE 'INSERT INTO TABLE
SELECT COUNT(AGENTID) FROM TABLE_1 A,
TABLE_2 B, TABLE_3 C
WHERE A.COL = B.COL AND B.COL = C.COL AND
DT BETWEEN TRUNC(SYSDATE-1) + 1/24 + 0/12/60/60 AND TRUNC(SYSDATE-1) + 25/24 - 0/12/60/60';
Edited by: DBA on Dec 3, 2011 3:57 PMSo what's the problem? The only thing I can see is:
INSERT INTO TABLETABLE is reserved word, so name your table differently.
Also, I am assuming the above statement is actually generated from some variables based on some conditions, otherwise why would you need dynamic SQL, just issue:
INSERT INTO TABLE
SELECT COUNT(AGENTID) FROM TABLE_1 A,
TABLE_2 B, TABLE_3 C
WHERE A.COL = B.COL AND B.COL = C.COL AND
DT BETWEEN TRUNC(SYSDATE-1) + 1/24 + 0/12/60/60 AND TRUNC(SYSDATE-1) + 25/24 - 0/12/60/60; -
Using Execute Immediate in PLSQL block Vs Stand alone procedure
I am facing very unusual ( atleast unusual to me ) with usage of "Execute Immediate" statement.
I have a table dynamic_sql with one column plsql_block as VARCHAR2(4000);
I have stored some PLSQL blocks ('DECLARE ..... BEGIN.... END.... ) in this column .
Now I want to execute these PLSQL blocks one after other depending on certain conditions .
In order to archive this I wrote a PLSQL block as below
DECLARE
Cursor c1 is
select plsql_block from dynamic_sql
begin
for irec in c1
loop
<<< Condition >>>
begin
execute_immediate(irec.plsql_block);
exception
when others then
raise_application_error(-20001,'error ' ||irec.plsql_block||' '||sqlerrm);
end loop ;
end ;
With above PLSQL block , "execute immediate" is executing PLSQL block successfully without any error
But When I converted above PLSQL block into standalone procedure as shown below , I am getting error .
CREATE OR REPLACE procedure test AS
Cursor c1 is
select plsql_block from dynamic_sql
begin
for irec in c1
loop
<<< Condition >>>
begin
execute_immediate(irec.plsql_block);
exception
when others then
raise_application_error(-20001,'error ' ||irec.plsql_block||' '||sqlerrm);
end loop ;
end ;
BEGIN
test;
end ;
It is showing the value of irec.plsql_block but not showing sqlerrm...
I found this is very unusual as I am able to execute "execute immediate" statement with PLSQL block but not with similar procedure .
can anybody explain me why this is happening?
Thanks in Advance
AmitHello,
It doesn't make any sense to add SQLERRM for user defined exception, unless you want to raise application error for already defined error (e.g NOT_DATA_FOUND, ..)
Check following piece of code and its output,
CREATE OR REPLACE PROCEDURE myinsert1
AS
v_count NUMBER;
v_sql VARCHAR2 (300);
BEGIN
v_sql :=
'INSERT INTO ENTITY_EMPLOYEE VALUES(0,''TIM'',''LASTNAME'',10000)';
BEGIN
EXECUTE IMMEDIATE v_sql;
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE (SUBSTR (SQLERRM, 1, 300));
RAISE_APPLICATION_ERROR (-20002, 'My Error ' || SQLERRM, TRUE);
RAISE;
END;
END;
Output._
ORA-20002: My Error ORA-00001: unique constraint (ENTITY_EMPLOYEE_PK) violated
ORA-06512: at "MYINSERT1", line 21
ORA-00001: unique constraint (ENTITY_EMPLOYEE_PK) violated
ORA-06512: at line 2
Regrds -
What is the best way to execute immediate particular sql stored in a table
I have a string variable containing row_ids eg "12,24,35,23"
and a table
row_id, sql
1 , "insert into some_table values(23,'Happy');"
6 , "insert into some_other_table values(24,'Sad');"
12 , "insert into some_table values(23,'Crazzzy');"
15 , "insert into some_other_table values(23,'Old');"
23 , "insert into another_table values(23,'Left');"
24 , "insert into stuff_table values(23,'Gold');"
30 , "insert into old_table values(23,'Even');"
35 , "insert into archive_table values(23,"True");"
And I need to write a plsql function that takes the list of row_ids as an argument and executes the sql statements stored in the table that matches.
I am trying a combination of cursor and execute immediate statements to do it at the moment but suspect I am being very inefficient. So any suggestions or examples of similar code anyone knows about would be hugely appreciated.
Cheers
ReubenNot sure why anyone would be doing such a thing as storing their SQL in a table and wanting to dynamically execute it (generally this is bad practice), but if you must...
SQL> select * from testdata;
SQL_ID SQL_TEXT
1 insert into some_table values(23,'Happy');
6 insert into some_other_table values(24,'Sad');
12 insert into some_table values(23,'Crazzzy');
15 insert into some_other_table values(23,'Old');
23 insert into another_table values(23,'Left');
24 insert into stuff_table values(23,'Gold');
30 insert into old_table values(23,'Even');
35 insert into archive_table values(23,'True');
8 rows selected.
SQL> set serverout on
SQL> ed
Wrote file afiedt.buf
1 DECLARE
2 v_ids VARCHAR2(4000) := '12,24,35,23';
3 CURSOR cur_fetch IS
4 SELECT sql_text
5 FROM testdata
6 WHERE sql_id IN (SELECT TO_NUMBER(REGEXP_SUBSTR (v_ids, '[^,]+', 1, rownum))
7 FROM DUAL
8 CONNECT BY ROWNUM <= length(regexp_replace(v_ids,'[^,]*'))+1);
9 BEGIN
10 FOR s IN cur_fetch
11 LOOP
12 DBMS_OUTPUT.PUT_LINE(s.sql_text); -- For demo purposes show the sql text
13 -- EXECUTE IMMEDIATE s.sql_text; -- In reality, uncomment this to execute the sql text
14 END LOOP;
15* END;
16 /
insert into some_table values(23,'Crazzzy');
insert into another_table values(23,'Left');
insert into stuff_table values(23,'Gold');
insert into archive_table values(23,'True');
PL/SQL procedure successfully completed.
SQL> -
How to re-execute anonymous PL/SQL block in package definition ?
Hi all,
I implemented a package which contains procedures and an anonymous PL/SQL block.
This anonymous PL/SQL block is executed only once when the package is called.
and charge in-memory the content of table to avoid multiple SQL access each
time one procedure is called.
As my application open many sessions to the Oracle database, I would like to try
a solution to signal all sessions to reload the content of table when the content
of table is modified. The solution to stop and to restart the connection is not
acceptable.
Best regards
Sylvain> .. to avoid multiple SQL access each time one procedure is called.
As I understand your posting, this is the actual technical requirement. You want to force serialisation of PL/SQL code. Correct? (only one session at a time can run the procedure)
This feature typically used to accomplish this in o/s code is called a semaphore. PL/SQL does not specifically support semaphores. However, it supports a range of IPC (Inter Process Communication) methods - from message queues to pipes.
One of these IPC interfaces is DBMS_LOCK - which allows a unique lock to be defined and processes to manage their resource usage/execution/etc via this lock using the DBMS_LOCK API.
I've found this a pretty clean and manageable solution to enforce serialisation. Of course, it is even better not to enforce serialisation. Rather design the code to be thread safe and capable of multi-processing/parallel processing.
Personally, I would not use a table as an IPC mechanism as Oracle already provides better IPC mechanisms for PL/SQL code. As for "signalling sessions to re-load the table" - not possible as Oracle sessions cannot register callbacks to handle events. Oracle sessions are not event driven processes from a PL/SQL (application development) perspective. -
Executing parameterised PL sql block
hi,
I have a procedure which takes in parameter of a table name.
In the procedure i have a variable (say rowcount).
I want the variable rowcount to have the number of records present in that
particular table (passed as a parameter).
One way of doing this is getting the count in a dummy table and then
querying it.
Is there a better way out ?
Truptiyes, use dynamic sql e.g.
execute immediate 'select count (0) from ' || table_name_parameter into tabcnt_variable; -
Accepting user input and executing a PL/SQL block using it
Hi All,
I am working on a requirement wherein I have to accept values from the user for the various arguments to be supplied to a PL/SQL block and then execute it using these values. For now, I am using the following logic:
PROMPT Enter value for the Category
ACCEPT cCategory CHAR PROMPT 'Category:'
DECLARE
cCategry CHAR(1) := '&cCategory';
BEGIN
DBMS_OUTPUT.PUT_LINE('The value of the Category as entered by you is' || cCategory);
END;
PROMPT Press y if you want to proceed with the current values, or press n if you want to re-enter the values
ACCEPT cChoice CHAR Prompt 'Enter y or n:'
DECLARE
cCategry CHAR(1) := '&cCategory';
sErrorCd VARCHAR2(256);
sErrorDsc VARCHAR2(256);
BEGIN
IF '&cChoice' = 'y'
THEN
DBMS_OUTPUT.PUT_LINE('Starting with the process to execute the stored proc');
--- schema1.package1.sp1(cCategry, sErrorCd, sErrorDsc);
--- DBMS_OUTPUT.PUT_LINE('Error Code :' || sErrorCd);
--- DBMS_OUTPUT.PUT_LINE(' Error Description :' || sErrorDsc);
ELSIF '&cChoice' = 'n'
THEN
Now I want that the proc again start executing in the loop from the 1st line i.e. PROMPT Enter value for the Category. However i see that this is not possible to do that PROMPT statements and accepting user inputs execute only on the SQL prompt and not inside a PL/SQL block.
Is there an alternate method to establish this?
Thanks in advance.Hi,
You can write a genric procedure to achive the desired output. Pass 'Y' or 'N' in the procedure.
Call that procedure in simple pl/sql block during runtime using substituton operator.
For ex
create or replace procedure p1(category_in in varchar2)
IS
BEGIN
if (category_in='Y')
then
prcdr1()
/** Write your logic here ***/
elsif(category_in='N') then
prcdr2()
/** write your logic here***/
end if;
exception
/***write the exception logic ***/
end p1;
Begin
p1('&cat');
end;Regards,
Achyut K
Edited by: Achyut K on Aug 6, 2010 5:20 AM -
How to display result of execute immediate on sql prompt
I wish to create a dynamic select statement where i will give table name and where condition as input parameters at runtime. for this i created following procedure:
CREATE or replace PROCEDURE select_rows (
table_name IN VARCHAR2,
condition IN VARCHAR2 DEFAULT NULL)
AS
where_clause VARCHAR2(100) := ' WHERE ' || condition;
BEGIN
IF condition IS NULL THEN where_clause := NULL; END IF;
EXECUTE IMMEDIATE 'select * FROM ' || table_name || where_clause;
END;
my procedure is successfully created.
my problem is how to get select stmt output at screen (sql prompt)
or how to spool the output in a file.
plz. help me. I am learning oracle .
thanx in adv.
ManiYou could use refcursors. Example :
TEST@db102 > CREATE or replace PROCEDURE select_rows (
2 table_name IN VARCHAR2,
3 condition IN VARCHAR2 DEFAULT NULL,
4 cur1 out sys_refcursor)
5 AS
6 where_clause VARCHAR2(100) := ' WHERE ' || condition;
7 BEGIN
8 IF condition IS NULL THEN where_clause := NULL; END IF;
9 open cur1 for 'select * from '||table_name||where_clause;
10 END;
TEST@db102 > /
Procedure created.
TEST@db102 > var cur refcursor;
TEST@db102 > exec select_rows('emp','deptno=20',:cur);
PL/SQL procedure successfully completed.
TEST@db102 > print cur
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7369 SMITH CLERK 7902 17-DEC-80 800 20
7566 JONES MANAGER 7839 02-APR-81 2975 20
7788 SCOTT ANALYST 7566 09-DEC-82 3000 20
7876 ADAMS CLERK 7788 12-JAN-83 1100 20
7902 FORD ANALYST 7566 03-DEC-81 3000 20
TEST@db102 > -
Execute anonymous PL/SQL block via JDBC - OUT parameter not available
I have a simple proc on the database:
CREATE PROCEDURE TEST(X OUT BINARY_INTEGER, Y IN VARCHAR) AS
BEGIN
X := 33;
END; I am trying to invoke it via JDBC using an anonymous PL/SQL block:
try {
Connection connection =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL",
"scott", "tiger");
CallableStatement stproc_stmt = connection.prepareCall(
"DECLARE\n" +
" X_TARGET BINARY_INTEGER;\n" +
" Y_TARGET VARCHAR(20) := :2;\n" +
"BEGIN\n" +
" TEST(X=>X_TARGET, Y=>Y_TARGET);\n" +
" :1 := X_TARGET;\n" +
"END;"
stproc_stmt.registerOutParameter(1, Types.NUMERIC);
stproc_stmt.setString(2, "test");
stproc_stmt.executeUpdate();
Object o = stproc_stmt.getObject(1);
catch (Exception e) {
e.printStackTrace();
} No exceptions are thrown, but the Object o does not get the value '33' - it is NULL.
Any ideas?
thanks in advance,
Mike NormanI think the issue may be in how JDBC parameter binding is being managed throughout the block's lifecycle.
The slightly-different TEST2 works:
CREATE PROCEDURE TEST2(Y IN VARCHAR, X OUT BINARY_INTEGER) AS
BEGIN
X := 33;
END;
try {
Connection connection =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL",
"scott", "tiger");
CallableStatement stproc_stmt = connection.prepareCall(
"DECLARE\n" +
" Y_TARGET VARCHAR(20) := :1;\n" +
" X_TARGET BINARY_INTEGER;\n" +
"BEGIN\n" +
" TEST2(Y=>Y_TARGET, X=>X_TARGET);\n" +
" :2 := X_TARGET;\n" +
"END;"
stproc_stmt.setString(1, "test");
stproc_stmt.registerOutParameter(2, Types.NUMERIC);
stproc_stmt.executeUpdate();
Object o = stproc_stmt.getObject(1);
catch (Exception e) {
e.printStackTrace();
}The order of the bind indices ':1' and ':2' are reversed in the above anonymous block - we are returning via ':2'.
I am wondering if 'under the covers' there isn't perhaps a cursor issue. When the original block is parsed and the first bind index is found to be position 2, somehow we can't go back to position 1 - a forwards-only cursor? -
hi,
i created a pl/sql block using ed <filename.sql> and tried to execut it useing @<filena.sql> or run <filename.sql>.for the 2nd command the message i got is "nothing
in buffer to run" and for the 1st comm i got nothing. i dint event get prompt.
i am totally new to oracle. please solve my probs.
thanqTo execute the PL/SQL block make sure that you have a "/" at the end of your PL/SQL block and then an <Return character>. Once you have that then you can type C:\..\..\@filename.sql. If you don't put the "/" and "return character" it in your script then after typing C:\..\..\@filename.sql press enter and then type in "/" and then press enter again.
Soji.
Maybe you are looking for
-
Problem re: availability of Trivia Crack (ad free) in US store
Hello: The other day, I purchased and downloaded the ad free version of Trivia Crack. I have not been able to get it to sync to my iphone 4. I went into the app store and it told me that this app was not available in the US store. If this is true, h
-
Album Info and Sort Order?
Two Questions really, both of which I think (I hope!) are just me not quite getting the interface: 1) In iPhoto an album can have comments associated with the it. I tended to put in notes that related to all the pictures in the album, when I did the
-
Find the difference between two dates for the specific month and year
Hi, I have two dates, start date is 30/12/2012 and end date is 04/01/2013. Using datediff I found the difference of days between two dates. But I find the no of days in January 2013. ie output is 4 instead of 6. I input month and year to find the no
-
I am trying to control a screw elevator with labview. I have an array which holds the values for current lift position. Once the lift is at a new position I need to overwrite the old position of the lift with the new value in the array. I went thr
-
Make a custom layout in IH01 transaction for all users profile..
hi guys, i have a problem.. today my co-worked asked me to find a way to make a layout in T IH01 which is the same for all the users who log in the system.. i explain: i choose functional location press F8 and see my functional location selected.. no