在 WHERE 子句中使用变量的存储过程中的 DELETE 问题

Posted

技术标签:

【中文标题】在 WHERE 子句中使用变量的存储过程中的 DELETE 问题【英文标题】:Problem with DELETE in stored procedure using variable in WHERE clause 【发布时间】:2019-09-06 15:21:58 【问题描述】:

我试图在进行后续插入之前删除 SP 中的一些记录。 当我在 DELETE 的 WHERE 子句中使用变量时,它不起作用。当我用它的值替换变量时,它会删除记录。我猜这是我将变量放在 WHERE 子句中所做的事情,但无法弄清楚它是什么。我尝试了不同的方法,但都没有奏效。

PROCEDURE USPGETOUTCOME
(
IPSITEMIDS                VARCHAR2,
....
CUR_OUT                   OUT GETDATACURSOR
)
IS
....
....    
V_TEMP VARCHAR(200);
V_NEWITEMSLIST VARCHAR2(4000) := REPLACE(IPSITEMIDS, '''', '');


CURSOR cur IS
SELECT  REGEXP_SUBSTR(V_NEWITEMSLIST, '[^,]+', 1, LEVEL) V_NEWITEM2 FROM DUAL CONNECT BY instr(V_NEWITEMSLIST, ',',1, LEVEL -1) > 0;

BEGIN

-- IPSITEMIDS is ''EM060500103','LP060500105''   
V_TEMP := TRIM(BOTH '''' FROM IPSITEMIDS);

-- After above statement V_TEMP shows as 'EM060500103','LP060500105'

-- These don't work
--    DELETE FROM TEMPOUTCOME WHERE ITEMID IN (IPSITEMIDS);
--    DELETE FROM TEMPOUTCOME WHERE ITEMID IN (V_TEMP);
--    DELETE FROM TEMPOUTCOME WHERE ITEMID IN ('''|| V_TEMP ||''');
-- This works   
      DELETE FROM TEMPOUTCOME WHERE ITEMID IN ('EM060500103','LP060500105');
COMMIT;

-- This is using cursor to loop through each item and delete one by one; works but seems a waste!

-- Delete existing records from temp table for given ITEM IDs
FOR rec IN cur LOOP   
    V_NEWITEM := rec.V_NEWITEM2;
    DELETE FROM IDCTEMPOUTCOME WHERE ITEMID IN (V_NEWITEM);
END LOOP;
COMMIT;

【问题讨论】:

How to use parameters in a 'where value in...' clause?的可能重复 它似乎不适用于我的问题。 为什么不呢?您的变量版本最终是带有逗号的单个字符串,而不是您的工作版本中的逗号分隔字符串列表。这和那个重复的问题是一样的。 我可以使用游标循环遍历每个Item ID并一个一个删除记录,但是在我看来,当整个事情可以在查询中完成时,一个一个删除会很浪费.我更新问题以显示光标版本。 当我修剪''A','B''时,我没有得到像'A,B'这样的单个字符串;我得到 'A','B' 看起来像硬编码版本,但不知何故它不起作用,而硬编码版本起作用。 【参考方案1】:

您必须拆分值。

查看我的示例

--      BANNER
-- 1    Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
-- 2    PL/SQL Release 11.2.0.2.0 - Production
-- 3    CORE    11.2.0.2.0  Production
-- 4    TNS for 64-bit Windows: Version 11.2.0.2.0 - Production
-- 5    NLSRTL Version 11.2.0.2.0 - Production

DECLARE
  l_n NUMBER;
  l_filter VARCHAR2(100) := '''PL/SQL Release 11.2.0.2.0 - Production'',''NLSRTL Version 11.2.0.2.0 - Production''';
BEGIN
  SELECT COUNT(banner) AS n INTO l_n FROM v$version where banner IN (select REGEXP_SUBSTR(l_filter, '\''(.*?)\''(?:\,)?', 1, LEVEL, NULL, 1) FROM dual CONNECT BY LEVEL <= REGEXP_COUNT(l_filter, '''(?: +)?(\,)(?: +)?''', 1) + 1);
  DBMS_OUTPUT.put_line(l_n);
END;

【讨论】:

然后一一删除?你能用我在原帖中声明的变量举个例子吗?不是 Oracle 人,而是负责更新 SP 的 C# 开发人员! 你好@NoBullMan。您可以将我的 SELECT 语句更改为 DELETE 并一次将它们全部删除。这只是一个示例,根据变量的值显示匹配的数量(就像您的示例一样)。如果它不起作用,请告诉我。 l_filter 更改为 IPSITEMIDS,这是项目 ID 列表,作为用单引号括起来的字符串,并将 SLEECT 更改为 DELETE,它无需遍历每个项目 ID 即可工作。谢谢。

以上是关于在 WHERE 子句中使用变量的存储过程中的 DELETE 问题的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 case 语句来确定存储过程中的 from 和 where 子句?

在MySQL存储过程中的WHERE子句中使用IN param

使用来自存储参数的输入参数作为 MySQL where 子句中的变量

在 PL/SQL 存储过程中将多个变量传递给 WHERE 条件

变量作为 Oracle PL/SQL 中 where 子句中的列名

希望 Where 子句中的“存在”仅在传递的参数有值时使用