Assigning multiple fields in a loop using execute immediate - sql

I am using PLPDF's libraries to create spreadsheets for various files - I am trying to get a procedure written to take the values of each field and one-by-one insert them into the spreadsheet. This operation can include many different tables going into many different spreadsheets, so just doing an export is not going to cut it.
This example is has two cursors created from tables - the USER_TAB_COLUMNS to select the column names, and the actual view query to pull the data. I have one loop to go through the data record by record, and second to go field-by-field within the record.
Before doing the actual writing to the spreadsheet blob, I'm simply running the dbms_output.putline to make sure that I am getting the data needed.
declare
q_str varchar2(100);
this_vc varchar2(3000);
cursor diet_table is
select * from vcars_diet where nhp_id = 8573;
cursor diet_stru is
select 'begin :1 := i.' || column_name || '; end;' line_o_code from user_tab_columns where table_name = 'VCARS_DIET';
begin
for i in diet_table loop
DBMS_OUTPUT.PUT_LINE ('--------------------------------------------------------');
for h in diet_stru loop
DBMS_OUTPUT.PUT_LINE ('Varchar Value for i: "' || h.line_o_code || '"');
EXECUTE IMMEDIATE (h.line_o_code) USING out this_vc;
DBMS_OUTPUT.PUT_LINE ('Varchar Value for i.' || h.line_o_code || ' is: '||this_vc);
end loop;
end loop;
end;
The fields in the diet table are:
NHP_ID
DATE_TIME
DIET_NO
FORM_NAME
DATA_TYPE
The results are:
ORA-06550: line 1, column 13:
PLS-00201: identifier 'I.NHP_ID' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
ORA-06512: at line 33
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

I have copied this PL/SQL code from Connor McDonald's solution from this AskTom article.
It uses type dynamic SQL to parse any SQL query and converts the column names as well as values into a collection. I've used a sample query on employees table in HR schema. Replace it with your query.
set serverout on size 999999
set verify off
declare
p_query varchar2(32767) :=
q'{select * from employees
where rownum = 1
}';-- Here you put your query
l_theCursor integer default dbms_sql.open_cursor;
l_columnValue varchar2(4000);
l_status integer;
l_descTbl dbms_sql.desc_tab;
l_colCnt number;
n number := 0;
procedure p(msg varchar2) is
l varchar2(4000) := msg;
begin
while length(l) > 0 loop
dbms_output.put_line(substr(l,1,80));
l := substr(l,81);
end loop;
end;
begin
execute immediate
'alter session set nls_date_format=''dd-mon-yyyy hh24:mi:ss'' ';
dbms_sql.parse( l_theCursor, p_query, dbms_sql.native );
dbms_sql.describe_columns( l_theCursor, l_colCnt, l_descTbl );
for i in 1 .. l_colCnt loop
dbms_sql.define_column(l_theCursor, i, l_columnValue, 4000);
end loop;
l_status := dbms_sql.execute(l_theCursor);
while ( dbms_sql.fetch_rows(l_theCursor) > 0 ) loop
for i in 1 .. l_colCnt loop
dbms_sql.column_value( l_theCursor, i, l_columnValue );
p( 'Value for '|| l_descTbl(i).col_name
|| ' is: ' ||
l_columnValue );
end loop;
dbms_output.put_line( '-----------------' );
n := n + 1;
end loop;
if n = 0 then
dbms_output.put_line( chr(10)||'No data found '||chr(10) );
end if;
end;
/
This gives the output:
Value for EMPLOYEE_ID is: 198
Value for FIRST_NAME is: Donald
Value for LAST_NAME is: OConnell
Value for EMAIL is: DOCONNEL
Value for PHONE_NUMBER is: 650.507.9833
Value for HIRE_DATE is: 21-jun-2007 00:00:00
Value for JOB_ID is: SH_CLERK
Value for SALARY is: 2600
Value for COMMISSION_PCT is:
Value for MANAGER_ID is: 124
Value for DEPARTMENT_ID is: 50
-----------------
PL/SQL procedure successfully completed.

Related

Get column names of the result of a query Oracle SQL

I need a query that will get the column names of the result of another query. The other query can be anything - I can't make any assumptions about it but it will typically be some SELECT statement.
For example, if I have this table Members
Id | Name | Age
---|------|----
1 | John | 25
2 | Amir | 13
And this SELECT statement
SELECT Name, Age FROM Members
Then the result of the query I'm trying to write would be
Name
Age
In SQL Server, there is a function - sys.dm_exec_describe_first_result_set - that does this but I can't find an equivalent in Oracle.
I tried to use this answer but I can't use CREATE TYPE statements because of permissions issues and I probably can't use CREATE FUNCTION statements for the same reason.
Suppose you have a query like this:
select *
from (select deptno, job, sal from scott.emp)
pivot (avg(sal) as avg_sal for job in
('ANALYST' as analyst, 'CLERK' as clerk, 'SALESMAN' as salesman)
)
order by deptno
;
This produces the result:
DEPTNO ANALYST_AVG_SAL CLERK_AVG_SAL SALESMAN_AVG_SAL
---------- --------------- ------------- ----------------
10 1300
20 3000 950
30 950 1400
Notice the column names (like ANALYST_AVG_SAL) - they don't appear exactly in that form anywhere in the query! They are made up from two separate pieces, put together with an underscore.
Now, if you were allowed to create views (note that this does not create any data in your database - it just saves the text of a query), you could do this:
Create the view (just add the first line of code to what we already had):
create view q201028_vw as
select *
from (select deptno, job, sal from scott.emp)
pivot (avg(sal) as avg_sal for job in
('ANALYST' as analyst, 'CLERK' as clerk, 'SALESMAN' as salesman)
)
order by deptno
;
(Here I assumed you have some way to identify the query, an id like Q201028, and used that in the view name. That is not important, unless you need to do this often and for a large number of queries at the same time.)
Then you can find the column names (and also their order, and - if needed - their data type, etc.) by querying *_TAB_COLUMNS. For example:
select column_id, column_name
from user_tab_columns
where table_name = 'Q201028_VW'
order by column_id
;
COLUMN_ID COLUMN_NAME
---------- --------------------
1 DEPTNO
2 ANALYST_AVG_SAL
3 CLERK_AVG_SAL
4 SALESMAN_AVG_SAL
Now you can drop the view if you don't need it for anything else.
As an aside: The "usual" way to "save" queries in the database, in Oracle, is to create views. If they already exist as such in your DB, then all you need is the last step I showed you. Otherwise, were is the "other query" (for which you need to find the columns) coming from in the first place?
I would use the dbms_sql package and the following code example should show you how to start:
DECLARE
cursorID INTEGER;
status INTEGER;
colCount INTEGER;
rowCount INTEGER;
description dbms_sql.desc_tab;
colType INTEGER;
stringValue VARCHAR2(32676);
sqlCmd VARCHAR2(32767);
BEGIN
-- open cursor
cursorID := dbms_sql.open_cursor;
-- parse statement
dbms_sql.parse(cursorID, 'select * from user_tables', dbms_sql.native);
-- describe columns
dbms_sql.describe_columns(cursorID, colCount, description);
-- cursor close
dbms_sql.close_cursor(cursorID);
-- open cursor
cursorID := dbms_sql.open_cursor;
-- assemble a new select only using up to 5 the "text" columns
FOR i IN 1 .. description.COUNT LOOP
IF (i > 5) THEN
EXIT;
END IF;
IF (description(i).col_type IN (1, 112)) THEN
IF (sqlCmd IS NOT NULL) THEN
sqlCmd := sqlCmd || ', ';
END IF;
sqlCmd := sqlCmd || description(i).col_name;
END IF;
END LOOP;
sqlCmd := 'SELECT ' || sqlCmd || ' FROM user_tables';
dbms_output.put_line(sqlCmd);
-- parse statement
dbms_sql.parse(cursorID, sqlCmd, dbms_sql.native);
-- describe columns
dbms_sql.describe_columns(cursorID, colCount, description);
-- define columns
FOR i IN 1 .. description.COUNT LOOP
dbms_sql.define_column(cursorID, i, stringValue, 4000);
END LOOP;
-- execute
status := dbms_sql.execute(cursorID);
-- fetch up to 5 rows
rowCount := 0;
WHILE (dbms_sql.fetch_rows(cursorID) > 0) LOOP
rowCount := rowCount + 1;
IF (rowCount > 5) THEN
EXIT;
END IF;
dbms_output.put_line('row # ' || rowCount);
FOR i IN 1 .. description.COUNT LOOP
dbms_sql.column_value(cursorID, i, stringValue);
dbms_output.put_line('column "' || description(i).col_name || '" = "' || stringValue || '"');
END LOOP;
END LOOP;
-- cursor close
dbms_sql.close_cursor(cursorID);
END;
/
As astentx suggested, you can use a common table expression function to package the PL/SQL code into a SQL statement. This solution is just a single SQL statement, and requires no non-default privileges and does not create any permanent objects.
(The only downside is that not all SQL tools understand these kinds of WITH clauses, and they may throw an error expecting a different statement terminator.)
SQL> create table members(id number, name varchar2(100), age number);
Table created.
SQL> with function get_result_column_names(p_sql varchar2) return sys.odcivarchar2list is
2 v_cursor_id integer;
3 v_col_cnt integer;
4 v_columns dbms_sql.desc_tab;
5 v_column_names sys.odcivarchar2list := sys.odcivarchar2list();
6 begin
7 v_cursor_id := dbms_sql.open_cursor;
8 dbms_sql.parse(v_cursor_id, p_sql, dbms_sql.native);
9 dbms_sql.describe_columns(v_cursor_id, v_col_cnt, v_columns);
10
11 for i in 1 .. v_columns.count loop
12 v_column_names.extend;
13 v_column_names(v_column_names.count) := v_columns(i).col_name;
14 end loop;
15
16 dbms_sql.close_cursor(v_cursor_id);
17
18 return v_column_names;
19 exception when others then
20 dbms_sql.close_cursor(v_cursor_id);
21 raise;
22 end;
23 select *
24 from table(get_result_column_names(q'[select name, age from members]'));
25 /
COLUMN_VALUE
--------------------------------------------------------------------------------
NAME
AGE

EXECUTE IMMEDIATE DROP FUNCTION causes Oracle SQL Developer to hang

I have the following script. But whenever I include the line EXECUTE IMMEDIATE 'DROP FUNCTION table_exists';, SQL Developer seems to hang. Any idea what could be causing it?
If I cancel the task, the script runs to completion but doesn't drop the function. However, I can simply run DROP FUNCTION table_exists; in my DB connection and it drops the table no problem. Is it some quirk of PL/SQL?
CREATE OR REPLACE FUNCTION table_exists(table_name VARCHAR2)
RETURN BOOLEAN
AS
table_count NUMBER := 0;
exists_sql VARCHAR2(255);
BEGIN
exists_sql := 'SELECT COUNT(1) FROM tab WHERE tname = :tab_name';
EXECUTE IMMEDIATE exists_sql INTO table_count USING table_name;
RETURN table_count > 0;
END;
/
DECLARE
TYPE tables_array IS VARRAY(2) OF VARCHAR2(25); -- change varray size if running on dev
tables tables_array;
BEGIN
tables := tables_array(
'FOO',
'BAR'
);
FOR table_element IN 1 .. tables.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Backing up data for ' || tables(table_element));
IF table_exists(tables(table_element) || '_ORIGINAL') THEN
DBMS_OUTPUT.PUT_LINE(tables(table_element) || '_ORIGINAL already exists');
ELSE
EXECUTE IMMEDIATE 'CREATE TABLE ' || tables(table_element) || '_ORIGINAL AS SELECT * FROM '|| tables(table_element);
END IF;
END LOOP;
EXECUTE IMMEDIATE 'DROP FUNCTION table_exists';
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE ('Unexpected error: ' || sqlerrm);
ROLLBACK;
RAISE;
END;
/
Oracle won't drop a function which is being used in this very procedure.
Is there a workaround? Yes, at least one - submit a job which will do it in another session.
Sample tables (so that procedure won't fail because of that)
SQL> create table foo (id number);
Table created.
SQL> create table bar (id number);
Table created.
Create a function:
SQL> CREATE OR REPLACE FUNCTION table_exists(table_name VARCHAR2)
2 RETURN BOOLEAN
3 AS
4 table_count NUMBER := 0;
5 exists_sql VARCHAR2(255);
6 BEGIN
7 exists_sql := 'SELECT COUNT(1) FROM tab WHERE tname = :tab_name';
8 EXECUTE IMMEDIATE exists_sql INTO table_count USING table_name;
9
10 RETURN table_count > 0;
11 END;
12 /
Function created.
Is it here? Yes, it is:
SQL> desc table_Exists;
FUNCTION table_Exists RETURNS BOOLEAN
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
TABLE_NAME VARCHAR2 IN
Run the main piece of code; note line #4 (declaration of a variable which will contain job number) and line #21 which submits a job.
SQL> DECLARE
2 TYPE tables_array IS VARRAY(2) OF VARCHAR2(25); -- change varray size if running on dev
3 tables tables_array;
4 i number; -- job number
5 BEGIN
6 tables := tables_array(
7 'FOO',
8 'BAR'
9 );
10
11 FOR table_element IN 1 .. tables.COUNT LOOP
12 DBMS_OUTPUT.PUT_LINE('Backing up data for ' || tables(table_element));
13 IF table_exists(tables(table_element) || '_ORIGINAL') THEN
14 DBMS_OUTPUT.PUT_LINE(tables(table_element) || '_ORIGINAL already exists');
15 ELSE
16 EXECUTE IMMEDIATE 'CREATE TABLE ' || tables(table_element) || '_ORIGINAL AS SELECT * FROM '|| tables(table_element);
17 END IF;
18 END LOOP;
19
20 -- EXECUTE IMMEDIATE 'DROP FUNCTION table_exists';
21 dbms_job.submit(i, 'begin execute immediate ''drop function table_exists''; end;');
22
23 COMMIT;
24
25 EXCEPTION
26 WHEN OTHERS THEN
27 DBMS_OUTPUT.PUT_LINE ('Unexpected error: ' || sqlerrm);
28 ROLLBACK;
29 RAISE;
30 END;
31 /
PL/SQL procedure successfully completed.
Is the function still here? Nope, it was dropped.
SQL> desc table_exists;
ERROR:
ORA-04043: object table_exists does not exist
SQL>

How to use dynamic where clause in EXECUTE IMMEDIATE

I have a table with columns insert,select,where clause,dynamic where clause,group by clause.
Using procedure i need to execute insert into statement and also use dynamic where clause.
I tried the following one however it is giving me an error missing expression.
create or replace PROCEDURE dynamicWhereClause(Datee IN DATE,processId IN NUMBER)
IS
processName VARCHAR2(100);
tablePrefix CONFIG_DETAILS.SOURCE_TABLE%Type;
sourceTableType CONFIG_DETAILS.SOURCE_TABLE_TYPE%Type;
insertClause CONFIG_DETAILS.INSERT_CLAUSE%Type;
selectClause CONFIG_DETAILS.SELECT_CLAUSE%Type;
whereClause CONFIG_DETAILS.WHERE_CLAUSE%Type;
onUpdateClause CONFIG_DETAILS.ON_UPDATE_CLAUSE%Type;
groupByClause CONFIG_DETAILS.GROUP_BY_CLAUSE%Type;
orderByClause CONFIG_DETAILS.ORDER_BY_CLAUSE%Type;
isDynamicWhereClause CONFIG_DETAILS.IS_DYNAMIC_WHERE_CLAUSE%Type;
tableName VARCHAR2(50);
Process_Date DATE;
processQuery VARCHAR2(6000 BYTE);
CURSOR Process_Report IS
select NAME,SOURCE_TABLE,SOURCE_TABLE_TYPE,INSERT_CLAUSE,SELECT_CLAUSE,WHERE_CLAUSE,ON_UPDATE_CLAUSE,GROUP_BY_CLAUSE,ORDER_BY_CLAUSE,IS_DYNAMIC_WHERE_CLAUSE FROM
CONFIG_DETAILS where ID=processId;
BEGIN
OPEN Process_Report;
LOOP
FETCH Process_Report INTO processName,tablePrefix,sourceTableType,insertClause,selectClause,whereClause,onUpdateClause,groupByClause,orderByClause,isDynamicWhereClause;
EXIT when Process_Report%NOTFOUND;
tableName := getSourceTableName(tablePrefix,sourceTableType,processDate);
Process_Date := processDate;
processQuery := insertClause || selectClause ||' from ' || tableName ||' ' ||
nvl(whereClause,'') ||''||nvl(groupByClause,'') ||''||nvl(orderByClause,'') ||''||nvl(onUpdateClause,'');
dbms_output.put_line(processQuery);
IF isDynamicWhereClause = 'Y'
THEN
dbms_output.put_line(processQuery);
EXECUTE IMMEDIATE processQuery USING Process_Date;
ELSE
EXECUTE IMMEDIATE processQuery;
END IF;
END LOOP;
CLOSE Process_Report;
END;
While executing the proc it is giving me the below error.
Error report -
ORA-00936: missing expression
ORA-06512: at "Mytest.dynamicWhereClause", line 44
ORA-06512: at line 1
00936. 00000 - "missing expression"
Please assist me further
Thanks
Your questions is not 100% clear . you saying after DATEE is being empty, are you assigning a variable after date ? the below is example of how using execute immediate with a variable. Note how is the bind variable :i is showing in the print.
set serveroutput on size 1000
/
declare t number(4) :=10;
txt varchar2(100);
begin
txt :='INSERT INTO TAB (ID) values (:i)';
dbms_output.put_line(t || ' ' || txt);
execute immediate txt using T;
end;
/
PL/SQL procedure successfully completed
10 INSERT INTO TAB (ID) values (:i)

What is wrong with my PLSQL dynamic code?

I'm learning PLSQL since 3 or 4 months, and now I'm practicing Dynamic SQL and I've write a simple procedure to update last name of an employee with Dynamic SQL. I don´t know what is the problem because when I call the procedure and insert the parameters I receive an error.
CREATE OR REPLACE PROCEDURE upd_emp_dyn(
p_tname VARCHAR2,
p_lname employees.last_name%TYPE,
p_empid employees.employee_id%TYPE)
IS
v_dyn_stmt VARCHAR2(200) := 'UPDATE ' || p_tname ||
' SET last_name = ' ||
p_lname || ' WHERE employee_id = ' ||
p_empid;
v_confirm_stmt VARCHAR2(200) := 'SELECT * FROM ' || p_tname ||
' WHERE employee_id = ' ||
p_empid;
BEGIN
EXECUTE IMMEDIATE v_dyn_stmt;
DBMS_OUTPUT.PUT_LINE(v_confirm_stmt);
END upd_emp_dyn;
/
SHOW ERRORS;
SET SERVEROUTPUT ON
BEGIN
upd_emp_dyn('employees', 'Rooney', 120);
END;
/
Error que empieza en la línea: 2 del comando :
BEGIN
upd_emp_dyn('employees', 'Rooney', 120);
END;
Informe de error -
ORA-00904: "ROONEY": invalid identifier
ORA-06512: at "HR.UPD_EMP_DYN", line 14
ORA-06512: at line 2
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
The best practice (for both performance and security) is to use parameters:
CREATE OR REPLACE PROCEDURE upd_emp_dyn(
p_tname VARCHAR2,
p_lname employees.last_name%TYPE,
p_empid employees.employee_id%TYPE)
IS
v_dyn_stmt VARCHAR2(200) := 'UPDATE ' || p_tname ||
' SET last_name = :1 WHERE employee_id = :2';
v_confirm_stmt VARCHAR2(200) := 'SELECT * FROM ' || p_tname ||
' WHERE employee_id = :1';
BEGIN
EXECUTE IMMEDIATE v_dyn_stmt using p_lname, p_empid;
DBMS_OUTPUT.PUT_LINE(v_confirm_stmt);
END upd_emp_dyn;
/
SHOW ERRORS;
SET SERVEROUTPUT ON
BEGIN
upd_emp_dyn('employees', 'Rooney', 120);
END;
/
For select statements use following:
declare
result my_table%rowtype;
id number := 123;
begin
execute immediate 'select * from my_table where id = :1' into result using id;
end;
/
Also, it helps you to avoid typo errors (like which caused this question). And of course, you should avoid the use of dynamic SQL if it is possible to use static.
Instead of declaring table name as separate variable as parameter in your procedure..you can write a cursor for employees table & call that cursor in your dynamic query to print the output. So your dynamic sql in your proc will be more simple.

How do you specify IN clause in a dynamic query using a variable?

In PL/SQL, you can specify the values for the IN operator using concatenation:
v_sql := 'select field1
from table1
where field2 in (' || v_list || ')';
Is it possible to do the same using a variable?
v_sql := 'select field1
from table1
where field2 in (:v_list)';
If so, how?
EDIT: With reference to Marcin's answer, how do I select from the resultant table?
declare
cursor c_get_csv_as_tables is
select in_list(food_list) food_list
from emp_food
where emp_type = 'PERM';
cursor c_get_food_list (v_food_table varchar2Table)is
select *
from v_food_table;
begin
for i in c_get_csv_as_tables loop
for j in c_get_food_list(i.food_list) loop
dbms_output.put_line(j.element);
end loop;
end loop;
end;
I get the following error:
ORA-06550: line 10, column 6:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 9, column 1:
PL/SQL: SQL Statement ignored
ORA-06550: line 15, column 34:
PLS-00364: loop index variable 'J' use is invalid
ORA-06550: line 15, column 13:
PL/SQL: Statement ignored
Like in #Sathya link, you can bind the varray (I took #Codo example):
CREATE OR REPLACE TYPE str_tab_type IS VARRAY(10) OF VARCHAR2(200);
/
DECLARE
l_str_tab str_tab_type;
l_count NUMBER;
v_sql varchar2(3000);
BEGIN
l_str_tab := str_tab_type();
l_str_tab.extend(2);
l_str_tab(1) := 'TABLE';
l_str_tab(2) := 'INDEX';
v_sql := 'SELECT COUNT(*) FROM all_objects WHERE object_type IN (SELECT COLUMN_VALUE FROM TABLE(:v_list))';
execute immediate v_sql into l_count using l_str_tab;
dbms_output.put_line(l_count);
END;
/
UPDATE: the first command can be replaced with:
CREATE OR REPLACE TYPE str_tab_type IS TABLE OF VARCHAR2(200);
/
then call:
l_str_tab.extend(1);
when ever you add a value
Unfortunately you cannot bind a list like this, however you can use a table function. Read this
Here's an example of usage based on your code:
declare
cursor c_get_csv_as_tables is
select in_list(food_list) food_list
from emp_food
where emp_type = 'PERM';
cursor c_get_food_list (v_food_table varchar2Table)is
select column_value food
from TABLE(v_food_table);
begin
for i in c_get_csv_as_tables loop
for j in c_get_food_list(i.food_list) loop
dbms_output.put_line(j.food);
end loop;
end loop;
end;
I used here a column_value pseudocolumn
Bind variable can be used in Oracle SQL query with "in" clause.
Works in 10g; I don't know about other versions.
Bind variable is varchar up to 4000 characters.
Example: Bind variable containing comma-separated list of values, e.g.
:bindvar = 1,2,3,4,5
select * from mytable
where myfield in
(
SELECT regexp_substr(:bindvar,'[^,]+', 1, level) items
FROM dual
CONNECT BY regexp_substr(:bindvar, '[^,]+', 1, level) is not null
);
As per #Marcin's answer you can't do this, however, there's a fair bit to add to that, as your query should actually work, i.e. run.
Simply put, you cannot use a bind variable for a table or column. Not only that, bind variables they are assumed to be a character, so if you want a number you have to use to_number(:b1) etc.
This is where your query falls down. As you're passing in a string Oracle assumes that your entire list is a single string. Thus you are effectively running:
select field1
from table1
where field2 = v_list
There is no reason why you can't do this a different way though. I'm going to assume you're dynamically creating v_list, which means that all you need to do is create this list differently. A series of or conditions is, purportedly :-), no different to using an in.
By purportedly, I mean never rely on something that's untested. Although Tom does say in the link that there may be performance constraints there's no guarantee that it wasn't quicker than using in to begin with. The best thing to do is to run the trace on your query and his and see what difference there is, if any.
SQL> set serveroutput on
SQL>
SQL> declare
2
3 l_string varchar2(32767);
4 l_count number;
5
6 begin
7
8 for xx in ( select rownum as rnum, a.*
9 from user_tables a
10 where rownum < 20 ) loop
11
12 if xx.rnum = 1 then
13 l_string := 'table_name = ''' || xx.table_name || '''';
14 else
15 l_string := l_string || ' or table_name = ''' || xx.table_name || '
''';
16 end if;
17
18 end loop;
19
20 execute immediate 'select count(*)
21 from user_tables
22 where ' || l_string
23 into l_count
24 ;
25
26 dbms_output.put_line('count is ' || l_count);
27
28 end;
29 /
count is 19
PL/SQL procedure successfully completed.