【问题标题】:How to send string with special characters as input to stored procedure in Oracle如何将带有特殊字符的字符串作为输入发送到 Oracle 中的存储过程
【发布时间】:2021-02-03 00:04:42
【问题描述】:

我编写了一个将查询作为输入的过程,当此查询在 Oracle 开发人员上独立运行时,我尝试用于测试的查询由单引号 (') 组成,它可以无缝运行。但是当以字符串格式传递相同的查询来执行过程时,我得到了无效的表达式错误。

为了纠正这个错误,我在使用单引号的地方添加了双引号(''),之后我得到了右括号丢失错误。我什至尝试使用 CHR(39),它是单引号的 ASCII 值,但这也没有缓解。

有什么方法可以传递包含此类特殊字符的查询。

查询供参考:

select c1 as Order,c2 as lineId,
listagg(concat(concat(concat(tkey,' : '),concat(name,' : ')), status), ': ') 
WITHIN GROUP (ORDER BY c2) AS status from ABC 
where 
name in ('XY','LM','GT','GZ','AB') 
AND 
c2 in(select distinct(c2) from LMN
where 
c1 in (select c1 from LMN 
where 
c1 > (select (cast ((systimestamp - numtodsinterval(1,'hour')) at time zone 'UTC' as date) - date '1970-01-01') * 86400 from dual) 
AND 
c1 < (select (cast (systimestamp at time zone 'UTC' as date) - date '1970-01-01') * 86400 from dual)) 
AND 
from_system is not null) GROUP BY c1,c2

以上查询作为execute.proceudre_name('query')传递

PS 在使用 q-quote 机制时,查询如下:

execute getTransactionDetails(q'{select c1 as Order,c2 as lineId,
    listagg(concat(concat(concat(tkey,' : '),concat(name,' : ')), status), ': ') 
    WITHIN GROUP (ORDER BY c2) AS status from ABC 
    where 
    name in ('XY','LM','GT','GZ','AB') 
    AND 
    c2 in(select distinct(c2) from LMN
    where 
    c1 in (select c1 from LMN 
    where 
    c1 > (select (cast ((systimestamp - numtodsinterval(1,'hour')) at time zone 'UTC' as date) - date '1970-01-01') * 86400 from dual) 
    AND 
    c1 < (select (cast (systimestamp at time zone 'UTC' as date) - date '1970-01-01') * 86400 from dual)) 
    AND 
    from_system is not null) GROUP BY c1,c2;}');

得到错误:

Error starting at line : 3 in command -
listagg(concat(concat(concat(tkey,' : '),concat(name,' : ')), status), ': ')
Error report -
Unknown Command

SP2-0044: For a list of known commands enter HELP
and to leave enter EXIT.
>>Query Run In:Query Result 1

【问题讨论】:

  • 你不需要SELECT ... from dual - 只需使用c1 &gt; cast ((systimestamp - numtodsinterval(1,'hour')) at time zone 'UTC' as date) - date '1970-01-01') * 86400
  • 感谢@WernfriedDomscheit 的建议!!

标签: string oracle stored-procedures


【解决方案1】:

使用 q 引用机制。这是一个简单的例子:

这是包含单引号的查询,它将被传递给过程:

SQL> SELECT sal FROM emp WHERE ename = 'KING';

       SAL
----------
     10000

程序:

SQL> CREATE OR REPLACE PROCEDURE p_test (par_query IN VARCHAR2)
  2  IS
  3     l_sal  emp.sal%TYPE;
  4  BEGIN
  5     EXECUTE IMMEDIATE par_query
  6        INTO l_sal;
  7
  8     DBMS_OUTPUT.put_line ('Salary = ' || l_sal);
  9  END;
 10  /

Procedure created.

怎么称呼它?正如我所说 - q-quoting 机制:

SQL> EXEC p_test(q'[select sal from emp where ename = 'KING']');
Salary = 10000

PL/SQL procedure successfully completed.

SQL>

将其应用于您的案例。请注意,我使用了方括号;如果您传递给过程的 string 包含它们,则必须切换到其他内容,例如大括号。

【讨论】:

  • 感谢@littlefoot 的回复,我尝试使用 q-quoting 机制,但没有成功。我在 listagg 函数使用后出现错误。我已经编辑了我的答案。能否请您审核一下
  • 不客气。我不知道为什么 LISTAGG 返回错误;你让它比你应该做的更复杂(使用嵌套的 CONCAT),所以 - 尝试一个更简单的选项,使用双管道 || 连接运算符:LISTAGG (tkey || ' : ' || name || ' : ' || status, ': ') WITHIN GROUP (ORDER BY c2)
  • 没想到。感谢您的建议。
  • 当然,没问题。
  • 如果你有任何关于 LISTAGG 的解决方案。请建议:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
相关资源
最近更新 更多