Oracle条件优先级

时间:2012-03-29 07:22:40

标签: sql oracle plsql

我有一个带有varchar列(A)的表和另一个表示A中存在的数据类型的整数列(B)。如果B为0,则A将始终包含数字。

所以当我形成像这样的SQL时

SELECT COUNT(*) FROM TAB WHERE B = 0 AND TO_NUMBER(A) = 123;

我收到例外无效号码。

我希望首先评估B = 0,然后再评估TO_NUMBER(A),但是从上面的场景我怀疑首先评估TO_NUMBER(A)。我的猜测是否正确?

5 个答案:

答案 0 :(得分:2)

与C,C#,Java等编程语言相比,SQL没有所谓的条件逻辑运算符。对于条件逻辑运算符,仅在可以影响结果的情况下评估右操作数。因此,如果左操作数返回false,则&&的评估将停止。对于||,如果左操作数返回true,它将停止。

在SQL中,始终会评估两个操作数。并且由查询优化器决定首先评估哪一个。

我建议你创建以下函数,这在很多情况下很有用:

FUNCTION IS_NUMBER(P_NUMBER VARCHAR2)
RETURN NUMBER DETERMINISTIC
IS
  X NUMBER;
BEGIN
  X := TO_NUMBER(P_NUMBER);
  RETURN X;
EXCEPTION
  WHEN OTHERS THEN RETURN NULL;
END IS_NUMBER;

然后您可以将查询重写为:

SELECT COUNT(*) FROM TAB WHERE B = 0 AND IS_NUMBER(A) = 123;

您也可以使用该功能检查字符串是否为数字。

答案 1 :(得分:2)

这是一种强制检查B首先发生的简单方法。

SELECT COUNT(*) FROM TAB
WHERE 123 = DECODE(B, 0, TO_NUMBER(A), NULL);

答案 2 :(得分:1)

您可以使用子查询来确信结果的正确性

select /*+NO_MERGE(T)*/ count(*)
from (
    select *
    from TAB
    where B = 0
) T
where TO_NUMBER(A) = 123

答案 3 :(得分:0)

在您的特定示例中,您可以比较varchars ,如下所示:

SELECT COUNT(*) FROM TAB WHERE B = 0 AND A = '123';

或者如果您信任oracle执行隐式转换,这应该几乎总是有效(我不知道在什么情况下它不起作用,但是很难调试,如果出现问题)

SELECT COUNT(*) FROM TAB WHERE B = 0 AND A = 123;

答案 4 :(得分:-1)

首先应该测试B = 0 虽然没有看到样本数据,但我不确定你的猜测是否正确。

SELECT *
FROM DUAL
WHERE 1=0 AND 1/0=0

您可以尝试添加1/0 = 0作为最后一个语句(如此查询) 查询以了解Oracle 短路逻辑运算符。

sqlfiddle here