我有一个带有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)。我的猜测是否正确?
答案 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。