【问题标题】:How to pass varchar with single quotes to Stored Proc in Oracle [duplicate]如何将带单引号的varchar传递给Oracle中的存储过程[重复]
【发布时间】:2017-12-01 14:08:59
【问题描述】:

我有这样的存储过程:

调用 packagename.StoredProc('''A'',''B''')

'A', 'B' 部分意味着在 IN 子句的过程代码中用作参数。

当我使用 in 子句作为 paramvalue IN ('A', 'B') 运行该代码时,它会按预期返回行。

但是当调用存储过程时没有行这让我认为这些引号一定是错误的,但我显然无法正确。谁能看到为什么这不起作用?谢谢

来自proc的代码:

SELECT COUNT(*) 
            INTO v_PendingCheckCount
            FROM FUND_CHANGE_REQUEST
            WHERE STATUS IN ('PENDING_CHK', 'PEND_2ND_CHK')
            AND PROVIDER IN (pProviderList);

过程调用:

CALL PackageName.ProcedureName('''A'',''B''')

pProviderList 是传递给过程的参数。

【问题讨论】:

  • 您是否将 pProviderList 作为 VARCHAR 传递?类似的东西 - CREATE PROCEDURE ProcedureName(pProviderList VARCHAR)。
  • 是的,它作为 Varchar2 传递
  • 我认为您的问题是您传递给过程的字符串没有被解析为逗号分隔的列表 - 这与单引号无关。您可以通过使用 DBMS_OUTPUT 打印参数值来证明这一点 - 很确定您会看到单引号。
  • thisthisthisthis 可能重复
  • 显然,恰好包含 SQL 语法的 单个字符串 与单独值的实际列表不同。如果它以这种方式工作,那将是完全灾难性的。我很困惑,有人会觉得这令人费解。

标签: oracle stored-procedures plsql


【解决方案1】:

传递集合而不是字符串并使用MEMBER OF 而不是IN

CREATE OR REPLACE TYPE characterlist IS TABLE OF CHAR(1);
/

CREATE PACKAGE your_package AS
  PROCEDURE countPending(
    pProviderList IN  characterlist
    pCount        OUT INTEGER
  )
  AS
  BEGIN
    SELECT COUNT(*) 
    INTO pCount
    FROM FUND_CHANGE_REQUEST
    WHERE STATUS IN ('PENDING_CHK', 'PEND_2ND_CHK')
    AND PROVIDER  MEMBER OF pProviderList;
  END;
END;
/

那么你可以这样称呼它:

DECLARE
  vCount INTEGER;
BEGIN
  your_package.countPending(
    characterlist( 'A', 'B' ),
    vCount
  );
  DBMS_OUTPUT.PUT_LINE( vCount );
END;
/

谁能明白为什么这不起作用?

您传递的是单个字符串而不是值列表 - 因此 IN 条件正在测试以查看 PROVIDER 列是否与您的整个输入字符串完全匹配,而不是您假设的每个元素带引号的分隔列表。

 WHERE 'A' IN ( q'['A', 'B']' )

永远不会匹配,因为'A' 不等于q'['A', 'B']'(或'''A'', ''B''')并且计数将始终为零。

 WHERE 'A' IN ( 'A', 'B' )

将匹配但IN 条件的表达式列表中有两个术语。

【讨论】:

  • +1 感谢您的回答。我们让它用 INSTR 替换 IN 子句,这似乎是最简单的。所以它是这样的: INSTR(pProviderList, PROVIDER, 1, 1) > 0。我想你的解决方案在更大的数据上工作得更快,所以我接受你的回答。还要感谢您解释为什么它不适用于 IN。
【解决方案2】:

不,您不能(好吧,您可以,但它会被视为一个字符串文字,而不是值列表)在查询的 IN 子句中使用由逗号分隔的纯字符串。在这种情况下,您可以(应该)做的(作为选项之一)是将逗号分隔的字符串转换为集合并相应地使用它。这是一个例子:

注意:这里我使用了内置的apex_application_globalvc_arr2集合。 您可能决定创建自己的。由你决定。 如果您选择使用 apex_util 软件包,您可能需要被授予 execute 特权。

只是演示

set serveroutput on;
declare
   -- your source string
   l_str varchar2(100) := 'X, B, C';
   -- collection  the source string will be turned into  
   l_str_tab apex_application_global.vc_arr2;
   l_result number;
 begin
   -- convert the comma separated string of values
   -- into a collection 

   l_str_tab := apex_util.string_to_table(l_str, ',');

   -- Querying the collection using TABLE operator
   -- and passing result into the IN clause of the main query 

   select count(*)
     into l_result
     from dual
    where dummy in (select column_value
                      from table(l_str_tab));

    dbms_output.put_line(to_char(l_result));                  
 end;

结果:

1
PL/SQL procedure successfully completed.

【讨论】:

  • 如果apex_util.string_to_table 是一个集合(而不是VARRAY),那么您可以简化它(根据my answer)以摆脱表集合表达式,而使用WHERE dummy MEMBER OF l_str_tab
  • 拆分分隔字符串的非顶点方法有很多 - 上面有一个完整的SO documentation page,包括this PL/SQL function
  • +1 感谢您的回答。与 MT0 相比,我发现您的解决方案更难阅读,而且可能同事也不知道 apex_util,我希望让事情尽可能简单。
猜你喜欢
  • 2018-05-09
  • 2021-02-20
  • 1970-01-01
  • 2011-10-23
  • 1970-01-01
  • 2014-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多