How do I declare my select query in PL/SQL? - oracle

I want to declare a select query to use it in a trigger but I am a noob in sql in general :P Can somebody help me?
My code (example):
DECLARE Primary_Keys VARCHAR(20);
BEGIN
SELECT cons.constraint_type
FROM all_constraints cons, all_cons_columns cols
WHERE cols.owner = 'DAB_NAME'
AND cons.constraint_type = 'P'
AND cons.constraint_name = cols.constraint_name
AND cons.owner = cols.owner;
END;

You may use a PROCEDURE composed of BULK COLLECT with FORALL :
SQL> set serveroutput on;
SQL> CREATE OR REPLACE PROCEDURE pr_list_constraints(
i_owner IN all_cons_columns.owner%TYPE
)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Constraint Types for '||i_owner);
DBMS_OUTPUT.PUT_LINE('------------------------------- ');
FOR constraint_rec
IN (SELECT distinct cons.constraint_type
FROM all_constraints cons, all_cons_columns cols
WHERE cols.owner = i_owner --'DAB_NAME'
--AND cons.constraint_type = 'P'
AND cons.constraint_name = cols.constraint_name
AND cons.owner = cols.owner)
LOOP
DBMS_OUTPUT.PUT_LINE(constraint_rec.constraint_type);
END LOOP;
END;
/
SQL> var p_owner varchar2(50);
SQL> exec pr_list_constraints(:p_owner);
Constraint Types for DAB_NAME
-------------------------------
R
U
P
C
P.S. Using a DB trigger is irrelevant for such type of tasks.

Related

Update a table with dynamic query using bulk collect

I want update a table using a dynamic query, cursor and bulk collect. But I don't know the syntax:
declare
my_cursor ?;
-- other objects;
begin
execute immediate
"select s.col1, s.col2, rowid, d.rowid
from source_table s, destination_table d
where s.id = d.id "
BULK COLLECT INTO my_cursor;
FORALL i IN my_cursor.FIRST..my_cursor.LAST
UPDATE destination_table set col_a=my_cursor(i).col1 , col_b=my_cursor(i).col2
WHERE rowid = my_cursor(i).rowid;
commit;
end;
what would be the correct syntax and oracle objects
please help.
You can use something like this:
declare
type REC_TYPE is record (
ID SOURCE_TABLE.ID%type,
COL1 SOURCE_TABLE.COL1%type,
COL2 SOURCE_TABLE.COL2%type
);
type REC_CURSOR is ref cursor;
ref_cursor REC_CURSOR;
rec REC_TYPE;
sql_query VARCHAR2(4000);
begin
sql_query := 'select s.ID, COL1, COL2 from SOURCE_TABLE s, DESTINATION_TABLE d where s.ID = d.ID';
open ref_cursor for sql_query;
loop
fetch ref_cursor into rec;
exit when ref_cursor%NOTFOUND;
update DESTINATION_TABLE
set COL_A = rec.COL1, COL_B = rec.COL2
WHERE ID = rec.ID;
end loop;
close ref_cursor;
commit;
end;
/
or with bulk collect:
declare
type REC_TYPE is record (
ID SOURCE_TABLE.ID%type,
COL1 SOURCE_TABLE.COL1%type,
COL2 SOURCE_TABLE.COL2%type
);
type REC_TYPES is table of REC_TYPE;
type REC_CURSOR is ref cursor;
ref_cursor REC_CURSOR;
recs REC_TYPES;
sql_query VARCHAR2(4000);
begin
sql_query := 'select s.ID, COL1, COL2 from SOURCE_TABLE s, DESTINATION_TABLE d where s.ID = d.ID';
open ref_cursor for sql_query;
fetch ref_cursor bulk collect into recs;
close ref_cursor;
FOR ind IN recs.FIRST .. recs.LAST
loop
update DESTINATION_TABLE
set COL_A = recs(ind).COL1, COL_B = recs(ind).COL2
WHERE ID = recs(ind).ID;
end loop;
commit;
end;
/

Error while executing query stored in a variable within FOR loop in stored procedure

While running this prepared statement
DECLARE
BEGIN
-- Get the list of dependent tables and store it in a variable.
FOR cons IN (SELECT A.TABLE_NAME
FROM ALL_CONSTRAINTS A, ALL_CONSTRAINTS B
WHERE A.CONSTRAINT_TYPE = 'xxx'
AND A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME
AND A.R_OWNER = B.OWNER
AND B.TABLE_NAME = 'MY_TABLE'
AND B.OWNER = 'DBA')
LOOP
SET #querytext = CONCAT('SELECT * FROM ',cons.TABLE_NAME);
PREPARE stamquery FROM #querytext;
EXECUTE stamquery;
DEALLOCATE PREPARE stamquery;
END LOOP;
END;
I am getting the error stating:
Encountered the symbol "STAMQUERY" when expecting one of the following:
:= . ( # % ;
I am new with procedures but looks like this is the way to do it based on my research on the internet.
Please let me know what am I doing wrong..
The Syntax you are using for PL/SQL is not correct. It should be something like this.
DECLARE
querytext VARCHAR2(1000); --declare the variable to store query.
v_tab_count NUMBER;
BEGIN
-- Get the list of dependent tables and store it in a variable.
FOR cons IN
(
SELECT
A.TABLE_NAME
FROM
ALL_CONSTRAINTS A,
ALL_CONSTRAINTS B
WHERE
A.CONSTRAINT_TYPE = 'xxx'
AND A.R_CONSTRAINT_NAME = B.CONSTRAINT_NAME
AND A.R_OWNER = B.OWNER
AND B.TABLE_NAME = 'MY_TABLE'
AND B.OWNER = 'DBA'
)
LOOP
querytext := CONCAT('SELECT COUNT(*) FROM ',cons.TABLE_NAME);
EXECUTE IMMEDIATE querytext INTO v_tab_count ; --dynamicall execute the
-- select statement.
DBMS_OUTPUT.PUT_LINE( 'TABLE ' ||cons.TABLE_NAME||' COUNT '||v_tab_count);
-- Display the table name and its count of rows.
END LOOP;
END;

query to find number of empty tables in my schema name HR

I want to find the number of empty tables in my schema hr and i have written a code for it:
set serveroutput on;
Declare
d Number;
c varchar2(25);
cursor c1 is SELECT DISTINCT OWNER, OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_TYPE = 'TABLE' AND OWNER = 'HR';
Begin
for r in c1
Loop
select count(*) into d
from (r.object_name);
if (d = 0) then
dbms_output.put_line(r.object_name||'is Empty');
end if;
end loop;
end;
but its throwing error at this line from (r.object_name). can anyone help me in this?
Querying dba_tables.num_rows is not reliable as that is an estimate. If the table has never been analyzed, it might not reflect the correct row count.
Dynamic SQL is also not required for this. Based on my answer that calculates the row count for all tables, you can simply add a where condition:
select table_name
from (
select table_name,
to_number(extractvalue(xmltype(dbms_xmlgen.getxml('select count(*) c from '||owner||'.'||table_name)),'/ROWSET/ROW/C')) as row_count
from all_tables
where owner = 'HR'
)
where row_count = 0;
You need dynamic SQL (execute immediate) for that:
declare
d number;
v_sql varchar2(1000);
cursor c1 is select object_name
from all_objects
where object_type = 'TABLE' and owner = 'HR';
begin
for r in c1 loop
v_sql := 'select count(*) from HR.'||r.object_name;
execute immediate v_sql into d;
if d = 0 then
dbms_output.put_line(r.object_name||' is empty');
end if;
end loop;
end;
In Oracle , you can use below query.
select count(*) from dba_tables where OWNER = 'XXXX' and num_rows =0;

oracle read column names from select statement

I wonder how read column names in oracle. Ok, I know that there is table named USER_TAB_COLUMNS which gives info about it, but if I have 2 or 3 level nested query and I don't know column names. Or I just have simple query with join statement and i want to get column names. How to do that? any idey?
select * from person a
join person_details b where a.person_id = b.person_id
thanks
I would go for:
select 'select ' || LISTAGG(column_name , ',') within group (order by column_id) || ' from T1'
from user_tab_columns
where table_name = 'T1';
to get a query from database. To get columns with types to fill map you can use just:
select column_name , data_type
from user_tab_columns
where table_name = 'T1';
I assume you are looking for this:
DECLARE
sqlStr VARCHAR2(1000);
cur INTEGER;
columnCount INTEGER;
describeColumns DBMS_SQL.DESC_TAB2;
BEGIN
sqlStr := 'SELECT a.*, b.*, SYSDATE as "Customized column name"
FROM person a JOIN person_details b
WHERE a.person_id = b.person_id';
cur := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cur, sqlStr, DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS2(cur, columnCount, describeColumns);
FOR i IN 1..columnCount LOOP
DBMS_OUTPUT.PUT_LINE ( describeColumns(i).COL_NAME );
END LOOP;
DBMS_SQL.CLOSE_CURSOR(cur);
END;

table name in loop oracle pl/sql

declare
v_cnt NUMBER;
C SYS_REFCURSOR;
TMP_TBL_NM VARCHAR2(100);
stmt VARCHAR2(1000);
the_name varchar2 (50);
cursor c_table is
(SELECT a.table_name
--, a.column_name, a.constraint_name, c.owner,
--c.r_owner , c_pk.table_name r_table_name, c_pk.constraint_name r_pk
FROM all_cons_columns a
JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name
JOIN all_constraints c_pk ON c.r_owner = c_pk.owner AND c.r_constraint_name = c_pk.constraint_name
WHERE c.owner like '%LTR' and c_pk.table_name like '%EnumerationValue%');
begin
stmt := 'SELECT table_name FROM ' || TMP_TBL_NM || ' ORDER BY 1';
OPEN C FOR stmt;
for t in C
loop
FETCH C INTO the_name;
EXIT WHEN C%NOTFOUND;
--my query for each table goes here
end loop;
end;
i want to use table names in loop as to check the records as per my query.
it is giving me error only by getting table name in the loop.
how can i get table name in a loop so that i can fetch rows as per my requirement from each table in a loop.
thanks in advance.
I'm not entirely sure what you want to achieve here, but if it's just the table names you're interested in, you can make your code a lot less complicated doing it this way:
declare
cursor c_table is
SELECT a.table_name
--, a.column_name, a.constraint_name, c.owner,
--c.r_owner , c_pk.table_name r_table_name, c_pk.constraint_name r_pk
FROM all_cons_columns a
JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name
JOIN all_constraints c_pk ON c.r_owner = c_pk.owner AND c.r_constraint_name = c_pk.constraint_name
begin
for t in c_table loop
--do something with the table name
dbms_output.put_line(t.table_name);
end loop;
end;
This kind of for loop also handles the opening and closing of the cursor and is the recommended way to do these kind of operations.

Resources