在sql核心中case条件的oracle执行顺序

zaqlnxep  于 2023-04-05  发布在  Oracle
关注(0)|答案(3)|浏览(215)

为什么下面的代码不能在SQL中工作?在pl/sql中,它可以正常工作(在轻微的代码编辑之后)。根据正确的代码,它应该在检查oopname = 'PAY_OPERDATE'时停止,而不是继续转换为数字到_number(substr(paramvalue,4,2))〈=12。在oracle上测试到19 c。

with data as(
select null oopname, 'fgdfhdfhdf' paramvalue from dual
)
select 
  case 
    when  oopname = 'PAY_OPERDATE' 
      and length(paramvalue)=10 
      and to_number(substr(paramvalue,4,2))<=12 
    then paramvalue 
  end
from data

在PostgreSQL中,代码可以正常工作

select case when oopname = 'PAY_OPERDATE'  and length(paramvalue)=10 
and TO_NUMBER(substr(paramvalue,4,2),'99') <= 12
then paramvalue end aa
from (
select ''::text oopname, '02.hh.2022y'::text paramvalue 
) a

我想得到一个技术上的解释。文档没有说CONDITION是如何执行的。非常类似于一个bug。

dba5bblo

dba5bblo1#

在Oracle 12中,可以使用DEFAULT NULL ON CONVERSION ERROR

SELECT CASE 
       WHEN oopname = 'PAY_OPERDATE' 
       AND  length(paramvalue)=10 
       AND  to_number(substr(paramvalue,4,2) DEFAULT NULL ON CONVERSION ERROR)<=12 
       THEN paramvalue 
       END AS paramvalue
FROM   data

fiddle
为什么下面的代码在SQL中不起作用?
您已经:

CASE WHEN simple_expression THEN result END

其中simple_expression的形式为expr1 AND expr2 AND expr3。问题不在于CASE表达式,而在于嵌套在其中的子表达式的求值。SQL引擎可以以任何顺序求值expr1expr2expr3,并且如果它基于统计/基于成本的优化器决定,则可以选择首先求值最后一个表达式。这样做是最有利的。你写表达式的顺序不被考虑在内。
相反,如果您有:

CASE
WHEN expr1 THEN result1
WHEN expr2 THEN result2
WHEN expr3 THEN result3
END

然后,Oracle的SQL引擎将按顺序评估案例,并且如果为较早的案例找到匹配,则不会评估稍后的表达式(或结果)。

watbbzwu

watbbzwu2#

将CASE WHEN拆分为两个或多个

with data as(
select null oopname, 'fgdfhdfhdf' paramvalue from dual
)
select 
  case 
    when  oopname = 'PAY_OPERDATE'  then
  
      CASE WHEN length(paramvalue)=10 
      and to_number(substr(paramvalue,4,2))<=12 
    then paramvalue 
  ELSE NULL END 
  ELSE NULL
  end
from data
CASEWHENOOPNAME='PAY_OPERDATE'THENCASEWHENLENGTH(PARAMVALUE)=10ANDTO_NUMBER(SUBSTR(PARAMVALUE,4,2))〈=12THENPARAMVALUEELSENULLENDELSENULLEND
* 无效 *

fiddle

yws3nbqq

yws3nbqq3#

简而言之,这是一个半bug。
所有这一切都是因为opname = 'PAY_OPERDATE'。示例中的oopname为NULL,第一次比较返回NULL,并且错误(特点)是oracle不停止检查,虽然已经知道NULL不等于TRUE.但由于NULL不等于FALSE,所以检查第二个条件等等.但最后,所有检查之后,如果不满足FALSE它将理解NULL AND TRUE AND TRUE不是TRUE,因此不会执行THEN块

with data as(
select null oopname, 'fgdfhdfhdf' paramvalue from dual
)
select 
  case 
    when  decode(oopname,'PAY_OPERDATE',1,0) = 1
      and length(paramvalue)=10 
      and to_number(substr(paramvalue,4,2))<=12 
    then paramvalue 
  end
from data

相关问题