如何使用 Collection 作为 table 用于带有 IN 子句的 UPDATE

How to use Collection as a table for UPDATE with an IN clause

我需要在存储过程中使用这段代码,这样我就可以传递一个 ID 数组并更新相关记录。我想知道我是否必须使用循环而不是在 sp 中使用 IN 子句。

SET SERVEROUTPUT ON

DECLARE 
  P_IDS PKGINFO.t_ids; --type: table of NUMBER index by pls_integer;
  P_RESULT NUMBER;  

BEGIN 
  p_IDS(1) := 12345;

--this works fine:  
  for i in ( select * from table(p_ids))
    loop    
    UPDATE TABLE1
    SET FD1 = 'test'    
    WHERE     P_ID = i.column_value;
   end loop;

--this works fine too:   
   SELECT COUNT(*) INTO p_RESULT FROM TABLE1
   WHERE  P_ID IN (SELECT * FROM TABLE (p_ids));

--but this does not work, why????? how to make it work?
  UPDATE TABLE1
    SET FD1 = 'test'    
    WHERE  P_ID IN (SELECT * FROM TABLE (p_ids));

END;

--==================PKGINFO.t_ids==================
CREATE OR REPLACE package dbname.PKGINFO as
  -- package created to perform Associative array calls
  type t_ids is table of NUMBER index by pls_integer;
end PKGINFO;
/

我希望 UPDATE 可以使用 IN 子句,但它给了我一个 INVALID TYPE 错误。

直到最近 Oracle 才不允许 SQL 语句中的 PL/SQL 类型,包括 table collection expression 中的类型。您似乎使用的版本已经为 select 添加了支持,但(还)没有为 update 添加支持。如果您有可用的,那么您可以使用 schema-level 类型。也看看 member of.

使用您现在拥有的类型,您可以使用 FORALL,这比使用单独更新的循环更有效::

FORALL i IN p_ids.first..p_ids.last
UPDATE TABLE1
  SET FD1 = 'test'    
  WHERE P_ID = p_ids(i);