SQL 查询在 SQL Server 2012 中运行良好,但在 SQL Server 2008 R2 中无法执行

标签 sql sql-server tsql sql-server-2008-r2 sql-server-2012

我有一个名为 MyTextstable (myTextsTable_id INT, myTextsTable_text VARCHAR(MAX)) 的表。该表有大约 400 万条记录,我正在尝试删除以下范围内的 ASCII 字符的任何实例 VARCHAR(MAX)myTextsTable_text

  • 00 - 08
  • 11 - 12
  • 14 - 31
  • 127

我编写了以下 SQL 查询,它在 SQL Server 2012 上花费了不到 10 分钟,但即使在两个小时后也无法在 SQL Server 2008 R2 上执行(所以我停止了执行)。请注意,我已经在 SQL Server 2012 上恢复了 SQL Server 2008 R2 数据库的备份(即数据完全相同)。

BEGIN TRANSACTION [Tran1]

BEGIN TRY
    UPDATE myTextsTable
    SET myTextsTable_text = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(myTextsTable_text, CHAR(0), ''), CHAR(1), ''), CHAR(2), ''), CHAR(3), ''), CHAR(4), ''), CHAR(5), ''), CHAR(6), ''), CHAR(7), ''), CHAR(8), ''), CHAR(11), ''), CHAR(12), ''), CHAR(14), ''), CHAR(15), ''), CHAR(16), ''), CHAR(17), ''), CHAR(18), ''), CHAR(19), ''), CHAR(20), ''), CHAR(21), ''), CHAR(22), ''), CHAR(23), ''), CHAR(24), ''), CHAR(25), ''), CHAR(26), ''), CHAR(27), ''), CHAR(28), ''), CHAR(29), ''), CHAR(30), ''), CHAR(31), ''), CHAR(127), '')
    WHERE myTextsTable_text LIKE '%[' + CHAR(0) + CHAR(1) + CHAR(2) + CHAR(3) + CHAR(4) + CHAR(5) + CHAR(6) + CHAR(7) + CHAR(8) + CHAR(11) + CHAR(12) + CHAR(14) + CHAR(15) + CHAR(16) + CHAR(17) + CHAR(18) + CHAR(19) + CHAR(20) + CHAR(21) + CHAR(22) + CHAR(23) + CHAR(24) + CHAR(25) + CHAR(26) + CHAR(27) + CHAR(28) + CHAR(29) + CHAR(30) + CHAR(31) + CHAR(127) + ']%';
    COMMIT TRANSACTION [Tran1];
END TRY

BEGIN CATCH
    ROLLBACK TRANSACTION [Tran1];
    --PRINT ERROR_MESSAGE();
END CATCH;

只有 135 条记录受到影响。由于单个 UPDATE 查询在 SQL Server 2008 中不起作用,我尝试了使用临时表的以下方法。

BEGIN TRANSACTION [Tran1]

BEGIN TRY
    IF OBJECT_ID('tempdb..#myTextsTable') IS NOT NULL DROP TABLE #myTextsTable;
    SELECT myTextsTable_id, myTextsTable_text
    INTO #myTextsTable
    FROM myTextsTable
    WHERE myTextsTable_text LIKE '%[' + CHAR(0) + CHAR(1) + CHAR(2) + CHAR(3) + CHAR(4) + CHAR(5) + CHAR(6) + CHAR(7) + CHAR(8) + CHAR(11) + CHAR(12) + CHAR(14) + CHAR(15) + CHAR(16) + CHAR(17) + CHAR(18) + CHAR(19) + CHAR(20) + CHAR(21) + CHAR(22) + CHAR(23) + CHAR(24) + CHAR(25) + CHAR(26) + CHAR(27) + CHAR(28) + CHAR(29) + CHAR(30) + CHAR(31) + CHAR(127) + ']%';

    UPDATE #myTextsTable
    SET myTextsTable_text = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(myTextsTable_text, CHAR(0), ''), CHAR(1), ''), CHAR(2), ''), CHAR(3), ''), CHAR(4), ''), CHAR(5), ''), CHAR(6), ''), CHAR(7), ''), CHAR(8), ''), CHAR(11), ''), CHAR(12), ''), CHAR(14), ''), CHAR(15), ''), CHAR(16), ''), CHAR(17), ''), CHAR(18), ''), CHAR(19), ''), CHAR(20), ''), CHAR(21), ''), CHAR(22), ''), CHAR(23), ''), CHAR(24), ''), CHAR(25), ''), CHAR(26), ''), CHAR(27), ''), CHAR(28), ''), CHAR(29), ''), CHAR(30), ''), CHAR(31), ''), CHAR(127), '')

    UPDATE myTextsTable
    SET myTextsTable_text = new.myTextsTable_text
    FROM myTextsTable
    INNER JOIN #myTextsTable new ON new.myTextsTable_id=myTextsTable.myTextsTable_id

    DROP TABLE #myTextsTable;

    COMMIT TRANSACTION [Tran1];
END TRY

BEGIN CATCH
    ROLLBACK TRANSACTION [Tran1];
    --PRINT ERROR_MESSAGE();
END CATCH;

但是,结果是一样的。在 SQL Server 2012 中运行良好,但在 SQL Server 2008 R2 中运行不佳。我发现 UPDATE 查询即使在两个小时后仍在执行(记录在几分钟内保存到临时表(#myTextsTable)中,我稍后检查了这个确保哪个部分花费的时间更长)。

由于上述两种方法不起作用,我尝试使用 TABLE 变量来检查它是否有任何区别,但结果是相同的(即在 SQL Server 2012 中工作正常但不在 SQL Server 2008 R2 中)

BEGIN TRANSACTION [Tran1]

BEGIN TRY
    DECLARE @myTextsTable TABLE (myTextsTable_id INT, myTextsTable_text VARCHAR(MAX))
    INSERT INTO @myTextsTable(myTextsTable_id, myTextsTable_text)
    SELECT myTextsTable_id, myTextsTable_text
    FROM myTextsTable
    WHERE myTextsTable_text LIKE '%[' + CHAR(0) + CHAR(1) + CHAR(2) + CHAR(3) + CHAR(4) + CHAR(5) + CHAR(6) + CHAR(7) + CHAR(8) + CHAR(11) + CHAR(12) + CHAR(14) + CHAR(15) + CHAR(16) + CHAR(17) + CHAR(18) + CHAR(19) + CHAR(20) + CHAR(21) + CHAR(22) + CHAR(23) + CHAR(24) + CHAR(25) + CHAR(26) + CHAR(27) + CHAR(28) + CHAR(29) + CHAR(30) + CHAR(31) + CHAR(127) + ']%';

    UPDATE @myTextsTable
    SET myTextsTable_text = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(myTextsTable_text, CHAR(0), ''), CHAR(1), ''), CHAR(2), ''), CHAR(3), ''), CHAR(4), ''), CHAR(5), ''), CHAR(6), ''), CHAR(7), ''), CHAR(8), ''), CHAR(11), ''), CHAR(12), ''), CHAR(14), ''), CHAR(15), ''), CHAR(16), ''), CHAR(17), ''), CHAR(18), ''), CHAR(19), ''), CHAR(20), ''), CHAR(21), ''), CHAR(22), ''), CHAR(23), ''), CHAR(24), ''), CHAR(25), ''), CHAR(26), ''), CHAR(27), ''), CHAR(28), ''), CHAR(29), ''), CHAR(30), ''), CHAR(31), ''), CHAR(127), '')

    UPDATE myTextsTable
    SET myTextsTable_updated = GETDATE()
        ,myTextsTable_updatedby = 'As per V87058'
        ,myTextsTable_text = new.myTextsTable_text
    FROM myTextsTable
    INNER JOIN @myTextsTable new ON new.myTextsTable_id=myTextsTable.myTextsTable_id

    COMMIT TRANSACTION [Tran1];
END TRY

BEGIN CATCH
    ROLLBACK TRANSACTION [Tran1];
    --PRINT ERROR_MESSAGE();
END CATCH;

谁能解释为什么会这样?如何使这个 SQL 查询在 SQL Server 2008 R2 中工作?

注意:我知道数据库服务器/层的字符串操作并不理想,建议在应用层进行字符串操作,然后将其保存在数据库中。但是,我试图理解为什么这在一个版本中会成为问题,而在另一个版本中却不会。

SQL Server 2012
Microsoft SQL Server 2012 - 11.0.5058.0 (X64)
Standard Edition (64-bit) on Windows NT 6.3 (Build 9600: ) (Hypervisor)

SQL Server 2008 R2
Microsoft SQL Server 2012 - 11.0.5058.0 (X64)
Standard Edition (64-bit) on Windows NT 6.3 (Build 9600: ) (Hypervisor)

最佳答案

这是一个 known issue在具有 LOB 数据类型和某些排序规则的 SQL Server 2008 上。

容易复制

/*Hangs on 2008*/

DECLARE @VcMax varchar(max)= char(0) + 'a'

SELECT REPLACE(@VcMax COLLATE Latin1_General_CS_AS, char(0), '')

虽然挂起,但它受 CPU 限制,并且似乎在这些函数中处于无限循环中。

enter image description here

修复也很简单。要么使用非 MAX 数据类型...

...或二进制排序规则

/*Doesn't Hang*/
DECLARE @VcMax varchar(max)= char(0) + 'a'

SELECT REPLACE(@VcMax COLLATE Latin1_General_100_BIN2, char(0), '')

关于SQL 查询在 SQL Server 2012 中运行良好,但在 SQL Server 2008 R2 中无法执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28884135/

相关文章:

sql - 使用 SQL 在列中查找缺失的订单

sql-server - “字符串或二进制数据将被截断”

sql - Select min 返回空行

sql - 我可以避免在这里使用游标吗?

mysql - 连接表性能的 ORDER BY 列

mysql - 如何将这两个左连接合并为一个?

sql - SQL Server 如何处理非聚集索引中的包含列?

sql - 基于条件的数量

mysql - 执行 120mb 的插入语句

sql - 有没有办法让 SQL 语句从以整数为键的映射中返回字符串值?