更新或插入 SQL Server 时忽略错误行

Posted

技术标签:

【中文标题】更新或插入 SQL Server 时忽略错误行【英文标题】:Ignore error row when update or insert SQL Server 【发布时间】:2013-06-15 20:07:24 【问题描述】:

我的项目必须处理庞大的数据库。在最坏的情况下,它可能超过 8000 万行。

现在,我有 2 张桌子 T1T2。我必须将数据从表T1 复制到表T2

如果表T1中的一行已经存在于表T2中(相同的主键),则将T1中该行的其他列的数据更新为T2 否则将新行插入T2

首先,我使用 while 循环遍历 T1 中的 8000 万行,然后更新或插入到 T2。这非常非常非常慢,需要10多个小时才能完成。但是,如果任何行导致错误,我可以忽略它并捕获错误。

之后,我使用如下查询:

update Table2 
set T2.Column1 = T1.Column1,T2.Column2=T1.Column2 
from Table2 T2 JOIN Table1 T1 ON T1.ID=T2.ID

这要快得多,只需大约 1->2 小时即可完成。但是,如果任何一行有错误,查询就根本无法执行。

所以,我的问题是:

上面的查询有什么办法可以忽略错误行并继续执行有效行吗?

如果我没有办法做到这一点,我该怎么做才能比第一种方法运行得更快并且还可以捕获错误行?

p/s:我曾尝试将表格拆分为多个小部分,然后同时更新或插入所有小部分,但它并没有更快。

我已经用第二种方法解决了这个问题。我使用 TRY_CAST 来防止插入或更新行时出现异常。任何无效的数据都将为 NULL。完成后,我比较了 2 个表并找到不同的行。这些行是错误行。

【问题讨论】:

【参考方案1】:

您可以尝试从 T2 中删除现有行,然后从 T1 中批量插入所有行。这取决于现有行数,如果太大,则此方法不起作用。

【讨论】:

【参考方案2】:

至于您要求的功能,我建议如下:

MERGE INTO table2 target
USING
(
  SELECT id, column1, column2 FROM table1
) source ([id], [column1], [column2])
ON target.[Id] = source.[Id]
WHEN MATCHED THEN
    UPDATE SET 
        target.Colum1 = source.Column1,
                target.COlumn2 = source.Column2
WHEN NOT MATCHED BY SOURCE THEN
DELETE
WHEN NOT MATCHED BY TARGET THEN
    INSERT ([Id], [Column1], [Column2])
    VALUES([Id], [Column1], [Column2])
;

至于忽略错误 - 我认为这种方式是错误的。在这方面我会在数据验证上投入一些精力

【讨论】:

谢谢。运行这些错误:Msg 4104, Level 16, State 1, Line 7 The multi-part identifier "SOURCE.ID" could not be bound. 您能否检查一下您在“unsing”中的选择语句是否有效。它可能会发生,而不是重复相同的错误。如果它会 - 比你应该在你的 SELECT 中寻找问题 谢谢。我已经用第二种方法解决了这个问题。我使用 TRY_CAST 来防止插入或更新行时出现异常。任何无效的数据都将为 NULL。完成后,我比较了 2 个表并找到不同的行。这些行是错误行。【参考方案3】:

我已经用第二种方法解决了这个问题。我使用 TRY_CAST 来防止插入或更新行时出现异常。任何无效的数据都将为 NULL。完成后,我比较了 2 个表并找到不同的行。这些行是错误行。

【讨论】:

以上是关于更新或插入 SQL Server 时忽略错误行的主要内容,如果未能解决你的问题,请参考以下文章

sql:mysql:MySql 不存在则插入,存在则更新或忽略

sql:mysql:MySql 不存在则插入,存在则更新或忽略

MySql -- 不存在则插入,存在则更新或忽略

TypeORM 在批量保存时抛出重复错误,而不是忽略或更新现有值

SQL Server:忽略 AVG NULL 值

Oracle SQL 多次插入忽略重复行