sql-server - 批量插入 - 捕获所有约束错误

标签 sql-server validation tsql bulkinsert

我正在尝试使用 BULK INSERT 收集文件中包含的所有格式和约束错误。我想要文件中每个错误的确切行和错误描述。

目前,我正在使用 ERRORFILE 选项来收集文件中包含的所有格式错误。这给了我我需要的东西,但仅限于格式错误。

我想对约束错误做同样的事情。如果我使用 CHECK_CONSTRAINTS 选项,我可以捕捉到错误,但批量插入会终止。在检测到约束违规后,是否有任何方法可以让批量插入继续插入行,以便我可以收集所有约束错误?

我可以对插入行的临时表进行约束检查(在批量插入完成后),但我不想遵循这种方法,因为:

  1. 我无法在文件中找到约束所在的确切行 发现违规行为并
  2. 由于文件的性能原因 可能包含数百万行

更新

输入文件是一个制表符分隔的文本文件,包含 3 列:ID、名称、描述

下面是我用来读取/验证文件的代码:

create table #MyTable (ID int not null, Name varchar(20) not null, Description varchar(60) not null)

alter table #MyTable add check (ID != 1)

begin try
  execute sp_executesql 'bulk insert #MyTable from ''' + @FilePath + ''' with (maxerrors = 1000,check_constraints,errorfile='''+@ErrorFilePath+''')'
end try
begin catch
-- Here I am logging the constraint validation error
end catch

所需的输出是一个表格,其中包含在文件中找到的所有格式和约束错误。目前,我在指定的 errorfile 中收到所有格式错误,我批量插入 errorfile 以在具有结构的表中获取错误

RowNumber int, ErrorDescription nvarchar(max) not null

除了格式错误之外,我还希望此表包含所有约束错误。目前,查询在出现第一个约束错误时终止(由于 CHECK_CONSTRAINTS 行为)。

最佳答案

最近我不得不导入数十万个 XML 文件,每个文件只包含一行。我的方法是首先将所有文件放入数据库,然后检查文本长度、约束、值范围、转换问题……当采用这种方法时,您需要将所有列的数据类型声明为 nvarchar(max)允许所有数据保存在临时表中。你永远不会知道你会得到什么。该表包含您进行检查、识别错误记录、转换并将转换后的数据写入目标表所需的所有信息,只需一条 SQL 语句。

CREATE TABLE #MyTable1 ([ID] varchar(max), [NAME] varchar(max), [DESCRIPTION] varchar(max));
CREATE TABLE #MyTable2 ([ID] int not null, [NAME] varchar(20) not null, [DESCRIPTION] varchar(60) not null);

EXEC sp_executesql 'bulk insert #MyTable from ''' + @FilePath + ''''
--> I'm not so familiar wit the right syntax. I hope it is right. The point is, don't do any checks here.

SELECT 
    TRY_CONVERT([ID])
   ,[NAME]
   ,[DESCRIPTION]
   --,CASE WHEN TRY_CONVERT([ID]) IS NULL AND [ID] IS NOT NULL        THEN 1 ELSE 0 END AS [CONVERSION_ERROR_ID]
   --,CASE WHEN [NAME] IS NOT NULL AND LEN([NAME]) > 20               THEN 1 ELSE 0 END AS [CONVERSION_NAME]
   --,CASE WHEN [DESCRIPTION] IS NOT NULL AND LEN([DESCRIPTION]) > 60 THEN 1 ELSE 0 END AS [CONVERSION_DESCRIPTION]
FROM 
   #MyTable1
WHERE
      CASE WHEN TRY_CONVERT([ID]) IS NULL AND [ID] IS NOT NULL        THEN 1 ELSE 0 END = 1 --
   OR CASE WHEN [NAME] IS NOT NULL AND LEN([NAME]) > 20               THEN 1 ELSE 0 END = 1 -- --> show only erroneous rows
   OR CASE WHEN [DESCRIPTION] IS NOT NULL AND LEN([DESCRIPTION]) > 60 THEN 1 ELSE 0 END = 1 --
   -- Insert additional checks concerning the not null settings  


INSERT #MyTable2 ([ID], [NAME], [DESCRIPTION])
SELECT 
    [ID]
   ,[NAME]
   ,[DESCRIPTION]
FROM 
   #MyTable1
WHERE
       CASE WHEN TRY_CONVERT([ID]) IS NULL AND [ID] IS NOT NULL        THEN 1 ELSE 0 END = 0 --
   AND CASE WHEN [NAME] IS NOT NULL AND LEN([NAME]) > 20               THEN 1 ELSE 0 END = 0 -- --> Write only those rows to #MyTable2 where no issues can be found
   AND CASE WHEN [DESCRIPTION] IS NOT NULL AND LEN([DESCRIPTION]) > 60 THEN 1 ELSE 0 END = 0 --
   -- Insert additional checks concerning the not null settings  

-- Please note, that I have not tested these statements

关于sql-server - 批量插入 - 捕获所有约束错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38740391/

相关文章:

sql-server - 如果记录不存在,插入记录的最佳做法是什么?

javascript - 我正在尝试使用 Node 和 hapi.js 连接到我的 SQL Server 数据库

java - 如何使用枚举中的字符串值作为输入来输出 Java 中该枚举项的其余数据?

sql-server - 查询备份文件系统中其他位置的数据库

javascript - 如何限制用户在文本框中输入数字和特殊字符?

JavaScript 验证不会停止提交到 php 脚本

tsql - 这是什么 TSQL ".."

sql - 我想在第一行相同的SQL服务器中订购,但后来不同了

sql-server - 如何使用 TSQL 截断数据库中的所有表?

sql - 复杂的 SQL 选择查询