相关疑难解决方法(0)

SQL Server CASE 语句是评估所有条件还是在第一个 TRUE 条件时退出?

SQL Server(特别是 2008 或 2012)CASE语句是评估所有WHEN条件还是在找到WHEN评估为真的子句后退出?如果它确实通过了整个条件集,这是否意味着最后一个条件评估为 true 会覆盖第一个评估为 true 的条件所做的事情?例如:

SELECT
    CASE
        WHEN 1+1 = 2 THEN'YES'
        WHEN 1+1 = 3 THEN 'NO'
        WHEN 1+1 = 2 THEN 'NO' 
    END
Run Code Online (Sandbox Code Playgroud)

结果是“YES”,即使最后一个 when 条件应该使它评估为“NO”。一旦找到第一个 TRUE 条件,它似乎就退出了。有人可以确认是否是这种情况

sql-server t-sql case

53
推荐指数
3
解决办法
11万
查看次数

条件中的逻辑运算符 OR AND 和 WHERE 中的条件顺序

让我们检查这两个语句:

IF (CONDITION 1) OR (CONDITION 2)
...

IF (CONDITION 3) AND (CONDITION 4)
...
Run Code Online (Sandbox Code Playgroud)

如果CONDITION 1TRUE,会CONDITION 2被检查吗?
如果CONDITION 3FALSE,会CONDITION 4被检查吗?

条件如何WHERE:SQL Server 引擎是否优化WHERE子句中的所有条件?程序员是否应该以正确的顺序放置条件以确保 SQL Server 优化器以正确的方式解析它?

添加:

感谢 Jack 提供链接,来自 t-sql 代码的惊喜:

IF  1/0 = 1 OR 1 = 1
      SELECT 'True' AS result
ELSE
      SELECT 'False' AS result


IF  1/0 = 1 AND 1 = 0
      SELECT 'True' …
Run Code Online (Sandbox Code Playgroud)

sql-server-2008 sql-server optimization t-sql condition

38
推荐指数
2
解决办法
14万
查看次数

添加选择时超出自引用标量函数嵌套级别

目的

在尝试创建自引用函数的测试示例时,一个版本失败而另一个版本成功。

唯一的区别是添加SELECT到函数体导致两者的执行计划不同。


起作用的功能

CREATE FUNCTION dbo.test5(@i int)
RETURNS INT
AS 
BEGIN
RETURN(
SELECT TOP 1
CASE 
WHEN @i = 1 THEN 1
WHEN @i = 2 THEN 2
WHEN @i = 3 THEN  dbo.test5(1) + dbo.test5(2)
END
)
END;
Run Code Online (Sandbox Code Playgroud)

调用函数

SELECT dbo.test5(3);
Run Code Online (Sandbox Code Playgroud)

退货

(No column name)
3
Run Code Online (Sandbox Code Playgroud)

不起作用的功能

CREATE FUNCTION dbo.test6(@i int)
RETURNS INT
AS 
BEGIN
RETURN(
SELECT TOP 1
CASE 
WHEN @i = 1 THEN 1
WHEN @i = 2 THEN 2
WHEN @i = 3 …
Run Code Online (Sandbox Code Playgroud)

sql-server functions sql-server-2017

31
推荐指数
1
解决办法
853
查看次数

为什么以不允许在大多数子句中使用列别名的方式解析查询?

在尝试编写查询时,我发现(困难的方法)SQL Server 在执行查询时解析 SELECT 之前很久就解析了查询中的 WHERE。

MSDN文档说,一般逻辑解析顺序是这样的:SELECT被解析几乎最后(因此导致“没有这样的对象[别名]”试图使用在其他条款列别名时误差)。甚至有人建议允许在任何地方使用别名,但被微软团队驳回,理由是 ANSI 标准合规性问题(这表明这种行为是 ANSI 标准的一部分)。

作为一名程序员(不是 DBA),我发现这种行为有些令人困惑,因为在我看来它在很大程度上违背了拥有列别名的目的(或者,至少,如果列别名是在查询执行中更早地解析),因为您可以实际使用别名的唯一地方是在 ORDER BY 中。作为一名程序员,它似乎错过了使查询更强大、更方便和 DRY 的巨大机会。

看起来这是一个如此明显的问题,它有理由认为,除了 SELECT 和 ORDER BY 之外,还有其他原因决定不允许列别名,但这些原因是什么?

sql-server alias

16
推荐指数
2
解决办法
3293
查看次数

意外的 CASE 评估逻辑

我一直都明白,该CASE语句遵循“短路”原则,因为如果先前步骤被评估为真,则不会对后续步骤进行评估。(此答案是否 SQL Server CASE 语句评估所有条件或在第一个 TRUE 条件时退出?相关但似乎并未涵盖这种情况并且与 SQL Server 相关)。

在以下示例中,我希望MAX(amount)根据开始日期和支付日期之间的月份数计算不同月份之间的月份范围。

(这显然是一个构建的示例,但该逻辑在我看到问题的实际代码中具有有效的业务推理)。

如果开始日期和支付日期之间的时间小于 5 个月,则将使用表达式 1,否则将使用表达式 2

这会导致错误“ORA-01428:参数‘-1’超出范围”,因为 1 条记录的数据条件无效,导致 ORDER BY 的 BETWEEN 子句的开头为负值。

查询 1

SELECT ref_no,
       CASE WHEN MONTHS_BETWEEN(paid_date, start_date) < 5 THEN
-- Expression 1
          MAX(amount)
             OVER (PARTITION BY ref_no ORDER BY paid_date ASC 
             ROWS BETWEEN MONTHS_BETWEEN(paid_date, start_date) PRECEDING
             AND CURRENT ROW)
       ELSE
-- Expression 2
           MAX(amount)
             OVER (PARTITION BY ref_no ORDER BY paid_date ASC 
             ROWS …
Run Code Online (Sandbox Code Playgroud)

oracle

8
推荐指数
1
解决办法
858
查看次数

CTE 错误(nvarchar 到数字)

我正在使用 CTE 将 SSRS 存储的 proc 转换为 BO 存储的 proc,因为显然我不能将临时表与 Business Objects 一起使用。

我有这个查询:

;WITH cte1
AS
( 
    SELECT  cv.issue  
          , cv.customfield  
          , CAST(STRINGVALUE AS NUMERIC) AS priority_num  
    --INTO    #temp_priority_val  
    FROM    proddb1.customfieldvalue cv WITH (NOLOCK)  
            INNER JOIN proddb1.customfield e WITH (NOLOCK)
                 ON  cv.CUSTOMFIELD = e.id 
                 AND e.cfname = 'Issue Priority')  

,cte2
AS
( 
    SELECT  a.ISSUE  
          , f.customvalue priority_num  
    --INTO    #temp_priority  
    FROM    cte1 a 
            INNER JOIN proddb1.customfieldoption f WITH (NOLOCK)
                 ON  a.CUSTOMFIELD = f.CUSTOMFIELD        
                 AND CAST(a.priority_num AS NUMERIC) = f.id) 

SELECT …
Run Code Online (Sandbox Code Playgroud)

sql-server cte

5
推荐指数
1
解决办法
4578
查看次数

UPDATE语句处理WHERE子句应该消除的记录

我收到一个非常奇怪的错误。考虑下表:

CREATE TABLE #MyTable (
    Key1 INT , Key2 INT ,
    x SMALLINT , y INT , z INT ,
    a FLOAT , b FLOAT , c SMALLINT , s FLOAT
)

-- insert many records

CREATE UNIQUE CLUSTERED INDEX CI ON #MyTable ( Key1 , Key2 )
Run Code Online (Sandbox Code Playgroud)

出于某种原因,以下更新语句尝试除以零。这只能在c=0或 时发生c=1。该WHERE条款明确规定c>1

-- this fails with divide-by-zero error
UPDATE  #MyTable
SET s = CASE
        WHEN a - SQUARE ( b ) / c <= …
Run Code Online (Sandbox Code Playgroud)

sql-server-2008 sql-server update errors

3
推荐指数
1
解决办法
207
查看次数