I’m attempting to write a query script where I declare a variable and then use them in a select statement in Oracle SQL.
Basically script should check if parent tables’ entries are used in referenced table or not.
if not –> delete the entry from REF table.
So far I have this
x
DECLARE
tableToCompare sys_refcursor;
TYPE TableNameType IS RECORD (
table_name ALL_TABLES.TABLE_NAME%TYPE
, ref_table_name ALL_CONSTRAINTS.r_constraint_name%TYPE
);
tableName TableNameType;
PROCEDURE LOG_MSG(msg VARCHAR2)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('->'||msg);
END;
BEGIN
LOG_MSG('[PROCESS] -> starts');
-- find all parent tables for reference tables starting with REF_
OPEN tableToCompare FOR
SELECT ac.table_name, substr(ac.r_constraint_name, 0, LENGTH(ac.r_constraint_name) - 3) as ref_table_name
FROM all_constraints ac
WHERE 1 = 1 AND ac.constraint_type = 'R'
AND ac.r_constraint_name IN
(SELECT constraint_name
FROM all_constraints
WHERE table_name like 'REF_%');
LOOP
FETCH tableToCompare INTO tableName;
EXIT WHEN tableToCompare%NOTFOUND;
LOG_MSG('Parent table: ' || tableName.table_name || ' , of Reference table: ' || tableName.ref_table_name );
DELETE REF_STYLE_TYPE rst
WHERE NOT EXISTS (SELECT TYP_CD from STYLE_FORMAT rp WHERE rp.TYP_CD = rst.TYP_CD)
AND NOT EXISTS (SELECT TYP_CD from STYLE_REQ rp WHERE rp.TYP_CD = rst.TYP_CD)
AND NOT EXISTS (SELECT TYP_CD from STYLE_ADD_EX rp WHERE rp.TYP_CD = rst.TYP_CD);
-- DELETE tableName.ref_table_name rst
-- WHERE NOT EXISTS (SELECT TYP_CD from tableName.table_name rp WHERE rp.TYP_CD = rst.TYP_CD)
-- AND NOT EXISTS (SELECT TYP_CD from tableName.table_name+1 rp WHERE rp.TYP_CD = rst.TYP_CD)
-- AND NOT EXISTS (SELECT TYP_CD from tableName.table_name+2 rp WHERE rp.TYP_CD = rst.TYP_CD);
LOG_MSG('DONE!');
END LOOP;
END;
So far LOG_MSG('Parent table: ' || tableName.table_name || ' , of Reference table: ' || tableName.ref_table_name );
I got a msg log that lists me the variables but I have no idea how to combine that in query DELETE above.
Any ideas or suggestions how it could be automized to this ?
-- DELETE tableName.ref_table_name rst
-- WHERE NOT EXISTS (SELECT TYP_CD from tableName.table_name rp WHERE rp.TYP_CD = rst.TYP_CD)
-- AND NOT EXISTS (SELECT TYP_CD from tableName.table_name+1 rp WHERE rp.TYP_CD = rst.TYP_CD)
-- AND NOT EXISTS (SELECT TYP_CD from tableName.table_name+2 rp WHERE rp.TYP_CD = rst.TYP_CD);
Advertisement
Answer
You can’t reference table names as bind variables. In that case, use EXECUTE IMMEDIATE
. I’m a big fan of cursor for loops so I used that. Note that this code is not tested.
DECLARE
PROCEDURE LOG_MSG(msg VARCHAR2)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('->'||msg);
END;
l_delete_stmt VARCHAR2(4000);
BEGIN
log_msg('[PROCESS] -> starts');
l_delete_stmt :=
q'!DELETE #TABLE_NAME# rst
WHERE NOT EXISTS (SELECT TYP_CD from STYLE_FORMAT rp WHERE rp.TYP_CD = rst.TYP_CD)
AND NOT EXISTS (SELECT TYP_CD from STYLE_REQ rp WHERE rp.TYP_CD = rst.TYP_CD)
AND NOT EXISTS (SELECT TYP_CD from STYLE_ADD_EX rp WHERE rp.TYP_CD = rst.TYP_CD)!';
FOR r IN
(
SELECT ac.table_name, substr(ac.r_constraint_name, 0, LENGTH(ac.r_constraint_name) - 3) as ref_table_name
FROM all_constraints ac
WHERE 1 = 1 AND ac.constraint_type = 'R'
AND ac.r_constraint_name IN
(SELECT constraint_name
FROM all_constraints
WHERE table_name like 'REF_%')
) LOOP
log_msg('Parent table: ' || tableName.table_name || ' , of Reference table: ' || tableName.ref_table_name );
log_msg('Delete statement: ' || REPLACE(l_delete_stmt,'#TABLE_NAME#',r.ref_table_name) );
EXECUTE IMMEDIATE REPLACE(l_delete_stmt,'#TABLE_NAME#',r.ref_table_name);
log_msg('DONE!');
END LOOP;
END;