我有一个存储过程,它传递一个用空格分隔的值字符串,然后在表中搜索并返回列中包含任何值的数据。一切顺利,直到用户需要通过' INDEX END UNKNOWN PROCESS'即使存在具有这些值的数据,它也没有返回任何内容:
CREATE OR REPLACE PROCEDURE Searches
(
QUEUE IN TYPES.CHAR50,
P_CURSOR IN OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN P_CURSOR FOR
SELECT *
FROM tablez t
WHERE /* If the subquery returns UNKNOWN, END, PROCESS, INDEX which are Oracle reserved words the main query won't return any results */
/* In order to pass this inconsistency, I concatenated XYZ to both sides when using IN Clause */
CONCAT(LTRIM(RTRIM(t.QUEUECD)),'XYZ') IN ( SELECT CONCAT(LTRIM(RTRIM(tr.prom)),'XYZ')
FROM ( SELECT regexp_substr(QUEUE,'[^ ]+', 1, LEVEL) prom
FROM dual
CONNECT BY regexp_substr(QUEUE, '[^ ]+', 1, LEVEL) IS NOT NULL
) tr
)
;
END Searches;
因此,我将代码更改为使用regexp_substr,并且仅连接' XYZ'进行比较时返回值。但这是一个临时修复,因为QUEUECD是数据库中的索引列,并且在WHERE子句中使用CONCAT导致大数据上的性能问题。 您对如何提高性能或以不同方式传递值列表有任何建议吗?
谢谢!
答案 0 :(得分:0)
传递给Oracle保留字的Oracle SQL存储过程 变量
看起来像是一个不同的问题。看:没有办法通过"保留字"作为变量的值 - 当你有varchar变量时,那么值就是一个文本 - 仅此而已。
我已经制作了一个样本表并测试了一个没有连接的查询&#;; XYZ' - 我没有这样的问题。也许在最后或记录开头有一些白色的,不可打印的字符?
关于:
您对如何提高性能或以不同方式传递值列表有任何建议吗?
是。将集合(嵌套表)作为参数传递。例如:
create or replace type T_TAB_STRING as table of varchar2(4000);
接下来,将QUEUE的类型从TYPES.CHAR50
更改为T_TAB_STRING
。
然后你可以使用table()表达式来取消查询中的集合,如:
SELECT *
FROM tablez t
WHERE t.QUEUECD IN ( SELECT /*+ DYNAMIC_SAMPLING(tr, 2) */
*
FROM TABLE(QUEUE) tr
)
;
动态采样提示用于强制DB检查集合中有多少元素。如果没有该DB,则假设它的大小为1个块(通常为8k),因此CBO可以选择进行全扫描而不是索引扫描。
如果您不能使用该提示,或者由于某种原因它不起作用,还有其他方法可以帮助CBO在查询中使用集合。它正在为该集合实现Extensible Optimiser接口。它是由Adrian Billington在this article中写的,如何做到这一点。