INSERT INTO SELECT错误处理

时间:2016-02-11 11:34:16

标签: sql sql-server stored-procedures

我正在编写一个T-SQL存储过程,使用语句

插入表中
INSERT INTO [tableName]
.....
SELECT * FROM [tableName]

有时输入表(SELECT)可能包含错误的值:插入期望小数的表,而select返回NVarChar值,这将导致转换错误。 现在因为语句执行了“批量插入”,我不知道插入的最后一条记录是什么,或者包含错误数据的记录是什么。 SQL只说“转换错误.....” 有没有办法“记录”最后插入的记录,以便至少我知道什么行包含错误的值? (不使用游标)

5 个答案:

答案 0 :(得分:5)

观察此查询的结果

SELECT 
    v.id,
    v.val,
    x=TRY_CAST(v.val AS DECIMAL(28,2))
FROM 
    (VALUES(1,'1.26'),(2,'A.13')) AS v(id,val) 
WHERE
    TRY_CAST(v.val AS DECIMAL(28,2)) IS NULL

结果:

+----+------+------+
| id | val  |  x   |
+----+------+------+
|  2 | A.13 | NULL |
+----+------+------+

它使用TRY_CAST,如果NULL失败,则返回CAST。您可以使用它来确定失败的记录,或缩小您插入目标表的集合。

答案 1 :(得分:2)

没有上一个错误。

根据基本的数据库ACID条件,语句是ATOMIC - 它完全可以工作或完全失败。还没有在内部处理行的已定义顺序 - 这可能因服务器和数据特征而异。

通常在将数据复制到目标表之前清理数据。

答案 2 :(得分:1)

您可以尝试使用 OUTPUT 子句输出插入的行,直到遇到错误为止。您还可以使用 ORDER BY ,以便更快地确定哪个是插入失败的下一行。然后,知道失败的行,应该更容易确定问题的字段。

MSDN Link

  

具有OUTPUT子句的UPDATE,INSERT或DELETE语句   即使语句遇到错误,也会将行返回给客户端   回滚。如果发生任何错误,则不应使用该结果   你运行声明。

答案 3 :(得分:1)

您可以在下面的语句中使用哪个列进行转换问题。

SELECT SQL_VARIANT_PROPERTY(col1, 'BaseType') from Table1

过滤问题

SELECT * from Table1 WHERE QL_VARIANT_PROPERTY(col1, 'BaseType') not  like 'decimal%'

答案 4 :(得分:1)

我曾经在表中导入了1500万行时遇到过这个问题。我们最终决定采用以下方法在SSIS中做得最好:

  1. 创建让n个数据任务跟随另一个" ON ERROR"仅
  2. 在第一个数据任务中将COMMIT批量设置为100K。如果出错,请转到我们命名为10K的下一个
  3. 在这个任务中,whcih是10K,我们将COMMIT批量设置为10K和" ON ERROR"我们去1K等等。
  4. 我们最终在1条记录COMMIT BATCH数据任务" ON ERROR"上,将数据移动到一个表(调用ERROR RECORD表)中,该表具有足够的列(所有VARCHAR / NVARCHAR)以保持传入data +一个额外的列,用于保存该行的SSIS错误消息。
  5. 稍后当SSIS完成时,我们将分析所有失败的记录。这样我们就可以说你在1500万只中只有5条错误记录,我们会在隔离表中成功地插入1499995条记录和5条记录。

    谢谢并希望这种方法有所帮助