SQL Server 2008更新语句WHERE子句优先级

SQL Server 2008更新语句WHERE子句优先级,sql,sql-update,where-clause,operator-precedence,Sql,Sql Update,Where Clause,Operator Precedence,我编写了以下查询: UPDATE king_in SET IN_PNSN_ALL_TP_CNTRCT_CD = IN_PNSN_ALL_TP_CNTRCT_CD + '3' WHERE COALESCE(IN_PNSN_ALL_TP_CNTRCT_TX, '') <> '' AND CHARINDEX('3', IN_PNSN_ALL_TP_CNTRCT_CD) = 0 它检查一个字段中是否有值,如果有,则在相应的字段中放入一个3,如果其中没有3。当我运行它时,我得

我编写了以下查询:

UPDATE king_in
SET IN_PNSN_ALL_TP_CNTRCT_CD = IN_PNSN_ALL_TP_CNTRCT_CD + '3'
WHERE COALESCE(IN_PNSN_ALL_TP_CNTRCT_TX, '') <> ''
        AND CHARINDEX('3', IN_PNSN_ALL_TP_CNTRCT_CD) = 0
它检查一个字段中是否有值,如果有,则在相应的字段中放入一个3,如果其中没有3。当我运行它时,我得到一个字符串或二进制数据将被截断的错误。该字段是一个VARCHAR3,表中有些行已经包含3个字符,但实际上我正在通过WHERE过滤器进行更新的行的最大长度为2,因此我完全不明白为什么SQL Server会向我抛出截断错误。因此,我将更新语句更改为:

UPDATE king_in
SET IN_PNSN_ALL_TP_CNTRCT_CD = k.IN_PNSN_ALL_TP_CNTRCT_CD + '3'
FROM king_in k
        INNER JOIN
                     (
                        SELECT ki.row_key,
                                in_sqnc_nb
                        FROM king_in ki
                                INNER JOIN King_Ma km
                                    ON ki.Row_Key = km.Row_Key
                                INNER JOIN King_Recs kr
                                    ON km.doc_loc_nb = kr.ACK_ID
                        WHERE CHARINDEX('3', IN_PNSN_ALL_TP_CNTRCT_CD) = 0
                                AND COALESCE(IN_PNSN_ALL_TP_CNTRCT_TX, '') <> ''
                      ) a
            ON k.Row_Key = a.Row_Key 
                AND k.in_sqnc_nb = a.insr_sqnc_nb
它工作正常,没有错误

因此,基于此,当执行不带FROM子句的UPDATE语句时,SQL Server会在内部遍历并运行SET语句,然后再根据WHERE子句过滤记录。这就是我得到截断错误的原因,因为即使我要更新的记录少于3个字符,表中的某些行在该字段中有3个字符,当它无法将“3”添加到其中一行的末尾时,它抛出了错误

所以在所有这些之后,我有几个问题

1为什么?SQL Server在应用set语句之前不过滤结果集是否有特定的DBMS原因

2这是我在学习SQL的过程中从未学过的一件已知的事情吗

3 SQL Server中是否有更改此行为的设置

提前感谢。

1-可能是因为您的标准不可搜索-也就是说,它们不能使用索引。如果查询优化器确定执行表扫描更快,它将继续并在所有行上运行。当您像这里一样过滤应用于字段的函数时,这种情况尤其可能发生

2-是的。优化器将做它认为最好的事情。您可以通过使用括号强制WHERE子句的求值顺序来解决这个问题,但在您的示例中,我认为这不会有帮助,因为它强制执行表扫描

3-不,您需要更改数据或逻辑以允许使用索引。如果您真的需要对字段中某个字符的存在进行过滤,它可能应该是它自己的列,并且/或者您应该更好地规范化该特定的数据位

您的特定实例的一个解决方法是添加一个WHERE LENIN_PNSN_ALL_TP_CNTRCT_CD<3。

1-可能是因为您的标准不可搜索-也就是说,它们不能使用索引。如果查询优化器确定执行表扫描更快,它将继续并在所有行上运行。当您像这里一样过滤应用于字段的函数时,这种情况尤其可能发生

2-是的。优化器将做它认为最好的事情。您可以通过使用括号强制WHERE子句的求值顺序来解决这个问题,但在您的示例中,我认为这不会有帮助,因为它强制执行表扫描

3-不,您需要更改数据或逻辑以允许使用索引。如果您真的需要对字段中某个字符的存在进行过滤,它可能应该是它自己的列,并且/或者您应该更好地规范化该特定的数据位


对于您的特定实例,一个解决方法是添加一个WHERE LENIN_PNSN_ALL_TP_CNTRCT_CD<3。

@tom-很乐意提供帮助。当您希望SQL按照您的要求而不是它认为最好的方式来执行时,这样的内容有时会很有挑战性:@tom-很乐意帮忙。当您希望SQL按照您的要求而不是它认为最好的方式来执行时,这类内容有时会很有挑战性: