gpt4 book ai didi

oracle - 检查 WHERE 子句中的参数是否为 NULL

转载 作者:行者123 更新时间:2023-12-03 15:59:17 25 4
gpt4 key购买 nike

我遇到了一个需要永远执行的存储过程的问题。它相当大,我可以理解我需要一些时间,但这个持续了将近 20 分钟。

经过一些调试和研究,我注意到替换了 WHERE 的这一部分。条款;

((p_DrumNo IS NULL) OR T_ORDER.ORDER_ID IN (SELECT ORDER_ID FROM ORDERDELIVERY))

有很大的不同。因此,只要 p_DrumNo 为 NULL,该过程就可以正常工作,或者我修改上述内容以不检查 p_DrumNo 是否为 NULL;
(T_ORDER.ORDER_ID IN (SELECT ORDER_ID FROM ORDERDELIVERY))

目标与此 WHERE子句是过滤 p_DrumNo 上的结果集,如果它被传递到存储过程。 WHERE然后子句继续进一步的条件,但这个特定的条件会停止查询。

ORDERDELIVERY 只是一个~临时表,包含与参数 p_DrumNo 相关的 ORDER_ID。

这个简单的IS NULL检查怎么会造成如此大的影响?这可能与 OR 的使用有关连同子查询,但我不明白为什么子查询本身工作得很好。

提前致谢!

更新 [2011-09-23 10:13]

我已将问题分解为这个显示相同行为的小查询;

示例 A

SQL查询
SELECT * FROM T_ORDER WHERE
('290427' IS NULL OR ORDER_ID IN (SELECT ORDER_ID FROM T_ORDER WHERE ORDERNO LIKE '290427%') );

执行计划
OPERATION   OBJECT_NAME     OPTIONS     COST
------------------------------------------------------------
SELECT STATEMENT 97
FILTER
TABLE ACCESS T_ORDER FULL 95
TABLE ACCESS T_ORDER BY INDEX ROWID 2
INDEX PK_ORDER UNIQUE SCAN 1

示例 B

SQL查询
SELECT * FROM T_ORDER WHERE
( ORDER_ID IN (SELECT ORDER_ID FROM T_ORDER WHERE ORDERNO LIKE '290427%') );

执行计划
OPERATION   OBJECT_NAME     OPTIONS     COST
------------------------------------------------------------
SELECT STATEMENT 4
NESTED LOOPS 4
TABLE ACCESS T_ORDER BY INDEX ROWID 3
INDEX IX_T_ORDER_ORDERNO RANGE SCAN 2
TABLE ACCESS T_ORDER BY INDEX ROWID 1
INDEX PK_ORDER UNIQUE SCAN 0

正如大家所见,第一个查询(示例 A)进行了全表扫描。关于如何避免这种情况的任何想法?

最佳答案

不要在 SQL 语句本身中评估过程的参数状态,而是将该评估移动到包含的 PL/SQL 块,以便在提交理想的 SQL 语句之前只执行一次。例如:

CREATE OR REPLACE PROCEDURE my_sp (p_DrumNo VARCHAR2)
IS
BEGIN
IF p_DrumNo IS NULL THEN
SELECT ...
INTO ... -- Assumed
FROM ...
WHERE my_column = p_DrumNo;
ELSE
SELECT ...
INTO ... -- Assumed
FROM ...
WHERE ORDER_ID IN (SELECT ORDER_ID FROM ORDERDELIVERY);
END;
END;

我在使用 OR 调整 SQL 语句方面也取得了一些成功。通过使用 UNION ALL 将语句分成两个互斥的语句:
SELECT ...
FROM ...
WHERE p_DrumNo IS NULL
AND ORDER_ID IN (SELECT ORDER_ID FROM ORDERDELIVERY)
UNION ALL
SELECT ...
FROM ...
WHERE p_DrumNo IS NOT NULL
AND my_column = p_DrumNo;

关于oracle - 检查 WHERE 子句中的参数是否为 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7517018/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com