insert/update 批量 xml 数据使用合并语句时如何捕获错误

How to capture error when insert/update bulk xml data using merge statement

我想知道当我们insert/update批量数据使用合并语句时,如果记录数据有问题,如何捕获错误。

查看示例 xml:

<?xml version = "1.0" encoding="UTF-8" standalone="yes"?>
<document>
  <employee>
  <id>1</id>
  <name>test1</name>
  <salary>2000</salary>
  </employee>
  <employee>
  <id>2</id>
  <name>test2</name>
  <salary>4000</salary>
  </employee>
  <employee>
  <id>3A</id>
  <name>test3</name>
  <salary>8000</salary>
  </employee>
</document>

这是错误 3A id 是 int 类型,我们正在插入字母数字值,因此无法插入。我想以这样的方式编写一个存储过程,它应该详细保存错误日志。所以稍后当我们看到错误日志时,就可以很容易地理解问题是什么或问题出在哪里。

请看下面的例子:

CREATE TABLE [employee]
(
    [id]        INT,
    [name]      NVARCHAR(100),
    [salary]    INT,
)
GO

DECLARE @XML XML ='<?xml version = "1.0" encoding="UTF-8" standalone="yes"?>
<document>
  <employee>
  <id>1</id>
  <name>test1</name>
  <salary>2000</salary>
  </employee>
  <employee>
  <id>2</id>
  <name>test2</name>
  <salary>4000</salary>
  </employee>
  <employee>
  <id>3</id>
  <name>test3</name>
  <salary>8000</salary>
  </employee>
</document>'
MERGE employee AS [target]
USING   
(
    SELECT   
         tab.col.value('id[1]','int') as id
        ,tab.col.value('name[1]','nvarchar(100)') as name
        ,tab.col.value('salary[1]','int') as salary              
    FROM @xml.nodes('//employee') AS tab(col) 
) 
 AS [source] (id,name,salary) ON ([target].[id] = [source].[id])
        WHEN MATCHED THEN 
        UPDATE 
        SET 
            [target].[name]     = [source].[name],
            [target].[salary]   = [source].[salary]              
        WHEN NOT MATCHED THEN       
            INSERT (id,name,salary) 
                VALUES ([source].id,[source].name,[source].salary);

请详细指导。谢谢

一种方法是用 TRY/CATCH 块包装您的代码并将数据记录到 error_table:

结构:

CREATE TABLE #employee
(
    [id]        INT,
    [name]      NVARCHAR(100),
    [salary]    INT,
);

CREATE TABLE #error_log(ID INT IDENTITY(1,1),
                        create_date DATETIME NOT NULL DEFAULT GETDATE(),
                        message NVARCHAR(1000));


DECLARE @XML XML ='<?xml version = "1.0" encoding="UTF-8" standalone="yes"?>
<document>
  <employee>
  <id>1</id>
  <name>test1</name>
  <salary>2000</salary>
  </employee>
  <employee>
  <id>2</id>
  <name>test2</name>
  <salary>4000</salary>
  </employee>
  <employee>
  <id>3A</id>
  <name>test3</name>
  <salary>8000</salary>
  </employee>
</document>';

代码:

BEGIN TRY

  MERGE #employee AS [target]
  USING   
  (
    SELECT   
         tab.col.value('id[1]','int') as id
        ,tab.col.value('name[1]','nvarchar(100)') as name
        ,tab.col.value('salary[1]','int') as salary              
    FROM @xml.nodes('//employee') AS tab(col) 
  ) 
   AS [source] (id,name,salary) ON ([target].[id] = [source].[id])
        WHEN MATCHED THEN 
        UPDATE 
        SET 
            [target].[name]     = [source].[name],
            [target].[salary]   = [source].[salary]              
        WHEN NOT MATCHED THEN       
            INSERT (id,name,salary) 
                VALUES ([source].id,[source].name,[source].salary);
END TRY
BEGIN CATCH
  INSERT INTO #error_log(message)
  VALUES (ERROR_MESSAGE());
END CATCH

SELECT *
FROM #error_log

SELECT *
FROM #employee

LiveDemo

输出:

╔════╦═════════════════════╦═════════════════════════════════════════════╗
║ ID ║     Create_date     ║                   message                   ║
╠════╬═════════════════════╬═════════════════════════════════════════════╣
║  1 ║ 2015-12-26 11:04:12 ║ Conversion failed when converting the       ║
║    ║                     ║ nvarchar value '3A' to data type int.       ║
╚════╩═════════════════════╩═════════════════════════════════════════════╝