the following script gives me an error message:
PLS-00457: expressions have to be of SQL types
DECLARE
type t_num is table of number;
bp_id INTEGER := 14058;
zab_ids t_num;
BEGIN
SELECT zab.ID_ZAB BULK COLLECT
into zab_ids
FROM TB_ZAB zab
left join TB_ZBEZ zbez
on zab.ID_ZBEZ = zbez.ID_ZBEZ
where zbez.ID_BP = bp_id;
EXECUTE IMMEDIATE 'DELETE FROM TB_EGZAB where TB_EGZAB.ID_ZAB in (:ids)' USING zab_ids;
END;
I am quite new to PLSQL so I do not really understand why this error shows up? Maybe I have to convert the ids into a comma separated string? The ids should be reused later, so I thought it is a good id to store them away into a variable.
Thanks and Best Regards
You don't need PL/SQL or a collection:
DELETE FROM TB_EGZAB
WHERE ID_ZAB in (
SELECT zab.ID_ZAB
FROM TB_ZAB zab
INNER JOIN TB_ZBEZ zbez
ON zab.ID_ZBEZ = zbez.ID_ZBEZ
WHERE zbez.ID_BP = 14058
);
Note: WHERE zbez.ID_BP = 14058
will only be true when a zbez
row has been found so your LEFT OUTER JOIN
will be implicitly converted to an INNER JOIN
.
The error message is telling you that you cannot use collections defined in a PL/SQL scope in SQL queries.
If you want to use the ids later then use a collection defined in the SQL scope (not in a PL/SQL scope) and then you can use it in SQL queries (and do not need to use dynamic SQL):
CREATE TYPE number_list IS TABLE OF NUMBER;
Then:
DECLARE
bp_id TB_ZBEZ.ID_ZBEZ%TYPE := 14058;
zab_ids number_list;
BEGIN
SELECT zab.ID_ZAB
BULK COLLECT INTO zab_ids
FROM TB_ZAB zab
INNER JOIN TB_ZBEZ zbez
ON zab.ID_ZBEZ = zbez.ID_ZBEZ
WHERE zbez.ID_BP = bp_id;
DELETE FROM TB_EGZAB
WHERE ID_ZAB MEMBER OF zab_ids;
FOR i IN 1 .. zab_ids.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(zab_ids(i));
END LOOP;
END;
/
If you only want the ids of the deleted rows then do the DELETE
in a single query and use RETURNING ... INTO ...
:
DECLARE
TYPE t_num IS TABLE OF NUMBER;
v_ids t_num;
BEGIN
DELETE FROM TB_EGZAB
WHERE ID_ZAB in (
SELECT zab.ID_ZAB
FROM TB_ZAB zab
INNER JOIN TB_ZBEZ zbez
ON zab.ID_ZBEZ = zbez.ID_ZBEZ
WHERE zbez.ID_BP = 14058
)
RETURNING id_zab BULK COLLECT INTO v_ids;
-- Do something with the array in PL/SQL, since it is only defined in PL/SQL
FOR i IN 1 .. v_ids.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(v_ids(i));
END LOOP;
END;
/