为什么下面的代码不能在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。
3条答案
按热度按时间dba5bblo1#
在Oracle 12中,可以使用
DEFAULT NULL ON CONVERSION ERROR
:fiddle
为什么下面的代码在SQL中不起作用?
您已经:
其中
simple_expression
的形式为expr1 AND expr2 AND expr3
。问题不在于CASE
表达式,而在于嵌套在其中的子表达式的求值。SQL引擎可以以任何顺序求值expr1
、expr2
和expr3
,并且如果它基于统计/基于成本的优化器决定,则可以选择首先求值最后一个表达式。这样做是最有利的。你写表达式的顺序不被考虑在内。相反,如果您有:
然后,Oracle的SQL引擎将按顺序评估案例,并且如果为较早的案例找到匹配,则不会评估稍后的表达式(或结果)。
watbbzwu2#
将CASE WHEN拆分为两个或多个
fiddle
yws3nbqq3#
简而言之,这是一个半bug。
所有这一切都是因为opname = 'PAY_OPERDATE'。示例中的oopname为NULL,第一次比较返回NULL,并且错误(特点)是oracle不停止检查,虽然已经知道NULL不等于TRUE.但由于NULL不等于FALSE,所以检查第二个条件等等.但最后,所有检查之后,如果不满足FALSE它将理解NULL AND TRUE AND TRUE不是TRUE,因此不会执行THEN块