【问题标题】:Why are rows affected after executing and committing the same transaction more than once?为什么在多次执行和提交同一事务后行会受到影响?
【发布时间】:2021-04-01 21:12:02
【问题描述】:

我有一个充满更新的事务,如下所示:

BEGIN TRANSACTION updateCompanyNames;

UPDATE Companies 
SET name = 'abc Inc.' 
WHERE name = 'abc inc';
...
COMMIT TRANSACTION updateCompanyNames

我提交了事务,但是当我重新执行它时,一些行没有像预期的那样受到影响,但其他行仍然有相同数量的行受到影响,无论我执行多少次事务并提交。

【问题讨论】:

    标签: sql-server transactions


    【解决方案1】:

    您似乎使用了不区分大小写的排序规则,因此每次运行查询时,相同的行都符合条件。 UPDATE 后面的行数反映了符合条件的行数,即使当前列值没有更改。但是,SQL Server 实际上并没有将未更改的行更新为优化。

    使用COLLATE 子句可用于强制区分大小写比较。指定当前列排序规则的区分大小写的版本。例如,使用Latin1_General_CI_AS 列排序规则,指定Latin1_General_CS_AS

    UPDATE Companies 
    SET name = 'abc Inc.' 
    WHERE 
        name = 'abc inc' COLLATE Latin1_General_CS_AS;
    

    上述查询的缺点是表达式不是 sargable,因此即使列上存在索引也需要进行扫描。也可以通过包含不区分大小写的标准来提高性能和并发性。不区分大小写的谓词有助于索引查找以定位可能需要更新的行,而区分大小写的谓词将行限制为大小写不同的行。

    UPDATE Companies 
    SET name = 'abc Inc.' 
    WHERE 
        name = 'abc inc'
        AND name = 'abc inc' COLLATE Latin1_General_CS_AS;
    

    【讨论】:

    • 这是怎么解决的? SELECT SERVERPROPERTY('collation') 然后添加到UPDATE..SET...WHERE foo COLLATE (collation) = 'abc inc' ?
    • @CharlesLeblanc,您可以指定 WHERE foo = 'abc inc' COLLATE (collation),其中 collat​​ion 是您的列排序规则的区分大小写版本。请注意,即使列已编入索引,这也可能导致完全扫描。
    • 全面扫描的含义是什么?
    • @CharlesLeblanc,我将其添加到我的答案中以及一个查询以避免扫描。
    • @CharlesLeblanc 这回答了你的问题吗?如果是,请考虑接受。
    猜你喜欢
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    相关资源
    最近更新 更多