SQL case-when-else 语句效率

Posted

技术标签:

【中文标题】SQL case-when-else 语句效率【英文标题】:SQL case-when-else statement efficiency 【发布时间】:2016-06-13 08:33:15 【问题描述】:

当我使用这个语句时;

UPDATE TABLE
   SET FIELD = CASE
               WHEN NAME = 'a' THEN (SELECT NO FROM TABLE_TWO WHERE NAME = 'a')
               ELSE 'x' END
 WHERE FIELD_TWO = 1

如果TABLE.NAME != 'a' 会执行select SQL 吗? 此外,还有一点额外的问题,您认为在任何给定产品的 SQL 代码中都有这样的逻辑是否合适?我认为在 SQL 中包含任何逻辑都会使其覆盖变得非常困难,并且难以维护,您怎么看?

edit:select语句只返回单个值,忽略可以返回多个值的情况,这种情况不在本题讨论范围内。

【问题讨论】:

您使用的是哪个 DBMS?一般来说: CASE 语句没有“快捷方式”,因此很可能会为where 子句选择的每一行执行嵌套选择。但这确实取决于所使用的 DBMS。 目前我使用的是Oracle 12g 【参考方案1】:

The Oracle manual 声称它进行短路评估:

Oracle 数据库使用短路评估。对于一个简单的CASE 表达式,数据库仅在将每个comparison_expr 值与expr 进行比较之前评估它,而不是在将它们中的任何一个值与expr 进行比较之前评估所有compare_expr 值

在您的情况下,comparison_exprWHEN NAME = 'a' 部分,如果手册正确,如果 name 具有不同的值,数据库将不会运行 select

【讨论】:

【参考方案2】:

我认为,当您将其拆分为两个这样的 UPDATE 语句时,它会更易于阅读和维护:

UPDATE TABLE SET FIELD = (SELECT TOP 1 NO FROM TABLE_TWO WHERE NAME = 'a')
            WHERE FIELD_TWO = 1
              AND NAME='a'
UPDATE TABLE SET FIELD = 'x' 
            WHERE FIELD_TWO = 1
            AND NAME != 'a'

它可以让您轻松添加更多案例,如果案例更多,您可以概括案例,例如:

UPDATE TABLE SET FIELD = (SELECT TOP 1 NO FROM TABLE_TWO WHERE NAME = TABLE.FIELD)
            WHERE FIELD_TWO = 1
              AND NAME IN ('a','b','c')

【讨论】:

我喜欢这个,因为它大大提高了可读性,但即使第一条语句的条件为假,它仍然会执行内部选择,对吧?【参考方案3】:

如果我是你,我会使用一个变量,这样这种情况就不会每次都计算一个标量值。类似于以下内容:

DECLARE @myVar VARCHAR(10);

SELECT TOP 1 @myVar = NO FROM TABLE_TWO WHERE NAME = 'a';

UPDATE TABLE
   SET FIELD = CASE
               WHEN NAME = 'a' THEN @myVar
               ELSE 'x' END
 WHERE FIELD_TWO = 1

【讨论】:

问题是无论case语句中的条件如何,都会执行select SQL吗?看起来是这样的。

以上是关于SQL case-when-else 语句效率的主要内容,如果未能解决你的问题,请参考以下文章

java 多表联查sql语句效率问题

MySQL查看SQL语句执行效率

oracle如何查出历史记录中执行效率低的SQL语句

Mysql 定位执行效率低的sql 语句

sql语句中条件查询里in、like、及=三个的效率怎么样?

项目中优化sql语句执行效率的方法是啥?