In my stored procedure I use the following query:
SELECT COUNT(*) INTO COL_NO FROM user_tab_columns WHERE table_name='PAY_SLIP_FEB_16';
This query gives no error (because it shouldn't). But the table name here is fixed so I want to use a variable that will provide the table name. So I changed the query like this:
EXECUTE IMMEDIATE 'SELECT COUNT(*) INTO COL_NO FROM user_tab_columns WHERE table_name='''||TBL_NAME||'''';
This query gives error:
ORA-00905: missing keyword
What did I do wrong? TIA.
N.B. : TBL_NAME is the incoming parameter that will provide the table name, and COL_NAME is just a NUMBER(5,0) type variable.
I would expect the code to have the INTO as part of the EXECUTE IMMEDIATE, not in the dynamic query string:
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM user_tab_columns WHERE table_name='''||TBL_NAME||''''
INTO COL_NO ;
As a note: I would write this using a separate variable:
v_sql := 'SELECT COUNT(*) FROM user_tab_columns WHERE table_name = ''#TBL_NAME''';
v_sql := REPLACE(v_sql, '#TBL_NAME', TBL_NAME)
EXECUTE IMMEDIATE v_sql INTO v_COL_NO ;
Related
When try compaile my packages get error.
PLS-00306: wrong number or types of arguments in call to '||'
v_sql := 'select count(*) from table ('|| p_month_ids ||') where column_value = ' || p_month_id;
Execute Immediate v_sql into v_count;
You are trying to concatenate values into a string, but that can only work if each individual value is either a string or can be implicitly converted to a string. If p_month_ids is a collection - as it seems to be from how you're using it - then you would have to add each element individually - as you can't implicitly convert the p_month_ids collection to a string.
But don't do that; use bind variables:
v_sql := 'select count(*) from table (:p_month_ids) where column_value = :p_month_id';
execute immediate v_sql into v_count using p_month_ids, p_month_id;
Or don't use dynamic SQL at all:
select count(*) into v_count
from table (p_month_ids) where column_value = p_month_id;
Or loop over the collection and count matches directly, instead of using a query (and context switch).
db<>fiddle
I'm trying to select information from a group of tables. Originally, I had
SELECT table_name,
to_number(
extractvalue(
xmltype(
dbms_xmlgen.getxml('select count(*) c '|| ' from ' ||owner||'.'||table_name))
,'/ROWSET/ROW/C')) count
from all_tables
where table_name like 'PAY0%' OR table_name like 'PAY1%'
Then looped through all the tables in my code using
foreach(table_name in tables){
SELECT CUST_NUMBER
FROM #table_name#
}
Now I'm trying to combine the two by doing the following in order to get the cust_number from every table, but it's saying '"CUST_NUMBER": invalid identifier'
select CUST_NUMBER
from ( SELECT table_name,
to_number(
extractvalue(
xmltype(
dbms_xmlgen.getxml('select count(*) c '|| ' from ' ||owner||'.'||table_name))
,'/ROWSET/ROW/C')) count
from all_tables
where table_name like 'PAY0%' OR table_name like 'PAY1%') PayTables
I know the problem is the first query gets table names and not the data, but I've no idea how to get the data as well without looping through them seperately.
If I correctly understand your need, something like the following could help:
declare
vSQL varchar2(32767);
type tabNum is table of number;
vResult tabNum;
begin
select listagg( 'select cust_number from ' || owner || '.' || table_name,
' UNION ALL '
) within group ( order by null)
into vSQL
from dba_tables
where table_name like 'PAY0%' OR table_name like 'PAY1%';
--
dbms_output.put_line(vSQL);
--
execute immediate vSQL bulk collect into vResult;
--
for i in vResult.first .. vResult.last loop
dbms_output.put_line(vResult(i));
end loop;
end;
It dynamically builds an SQL statement that extracts values from all the tables matching you criteria; in the example I run the statement fetching the result into a structure, but you can open a cursor, or do whatever you need.
I am new to Oracle and PL/SQL and am trying to do the following.
I am returning the column names from a table name that is stored in a variable
variable v_table varchar2(100)
begin
select 'mytable' into :v_table from dual;
end;
select column_name from all_tab_columns where table_name = :v_table
This returns a rowset
column_name
colname1
colname2
colname3
I would like to loop through the returned rowset and get some stats for each column.
select count distinct(colname1), min(colname1), max(colname1)
from :v_table
group by min(colname1), max(colname1)
However I cannot figure out how to loop through this rowset.
By using below you can display column names of a table and append your sql query as per your requirement...
declare
v_table varchar2(100):='TABLE_NAME';
TYPE NT_VAR1 IS TABLE OF VARCHAR2(30);
TYP_NT NT_VAR1;
begin
select column_name BULK COLLECT INTO TYP_NT from all_tab_columns where table_name =v_table
order by column_id;
FOR I IN 1..TYP_NT.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE('COLUMN '||I||': '||TYP_NT(I));
END LOOP;
end;
Note: You should run select query dynamically means with the use of execute immediate why because you are passing table_name at run time.
Edit
After editing your query in for loop it will look like below.
declare
v_table varchar2(100):='TABLE_NAME';
TYPE NT_VAR1 IS TABLE OF VARCHAR2(30);
TYP_NT NT_VAR1;
var2 varchar2(2000);
var3 varchar2(2000);
begin
select column_name BULK COLLECT INTO TYP_NT from all_tab_columns where table_name =v_table
order by column_id;
FOR I IN 1..TYP_NT.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE('COLUMN '||I||': '||TYP_NT(I));
EXECUTE IMMEDIATE 'SELECT to_char(min('||TYP_NT(I)||')),to_char(max('||TYP_NT(I)||')) from '||v_table into var2,var3;
dbms_output.put_line(var2||' '||var3);
END LOOP;
end;
Note: Find the max data length of a column present in your table and assign same data type to var2 and var3 variables.
I am using with clause in my function where passing table name as parameter. So want use this table name in the query but giving table doesnot exits.Sample query
with EMP_A as(
select EMPNO, SAL
from EMP
where DEPTNO in (select DEPTNO from P_TABLE_NAME))
select * from EMP;
In your below posted query:
With emp_a as (
select empno,sal
from emp
where deptno in(select deptno from p_table_name)
)
select * from emp;
Firstly, you cannot have dynamic table name in SQL. Object names must be static. You need to (ab)use EXECUTE IMMEDIATE in PL/SQL to make it a dynamic SQL.
Secondly, your CTE and tablename are different. Your CTE is emp_a, while the table you are referring to is emp.
Thirdly, you use the WITH clause, i.e. subquery factoring when you have to use the subquery multiple times. Therefore, the CTE would act as a temporary taboe to hold the subquery resultset.
See the documentation to learn more about EXECUTE IMMEDIATE.
http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/executeimmediate_statement.htm
UPDATE An example
You could use a string variable to assign the dynamic query.
DECLARE
p_table_name VARCHAR2(30);
l_sql VARCHAR2(32767);
l_value. NUMBER;
BEGIN
p_table_name := 'DEPARTMENT';
l_sql := 'WITH clause...' || p_table_name || ' with clause contunied';
EXECUTE IMMEDIATE l_sql INTO l_value;
I want to get count(*) value in dynamic plsql statement.
We can write static stmt as:
select count(*) into tmp_cnt from table_info where nbr_entry='0123456789';
but how to get tmp_cnt value while writing the dynamic sql stament?
or any other way to get count(*) value into tmp_cnt variable?
Maybe different oracle version, but what worked for me was:
...
execute immediate 'select count(*) from ' || p_table_name into l_count;
...
You can achieve it with EXECUTE IMMEDIATE ... RETURNING INTO:
function count_rows(p_table_name varchar2)
return number
is
l_count number;
begin
execute immediate 'select count(*) from ' || p_table_name into l_count;
return l_count;
end count_rows;