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
输出:
╔════╦═════════════════════╦═════════════════════════════════════════════╗
║ ID ║ Create_date ║ message ║
╠════╬═════════════════════╬═════════════════════════════════════════════╣
║ 1 ║ 2015-12-26 11:04:12 ║ Conversion failed when converting the ║
║ ║ ║ nvarchar value '3A' to data type int. ║
╚════╩═════════════════════╩═════════════════════════════════════════════╝
我想知道当我们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
输出:
╔════╦═════════════════════╦═════════════════════════════════════════════╗
║ ID ║ Create_date ║ message ║
╠════╬═════════════════════╬═════════════════════════════════════════════╣
║ 1 ║ 2015-12-26 11:04:12 ║ Conversion failed when converting the ║
║ ║ ║ nvarchar value '3A' to data type int. ║
╚════╩═════════════════════╩═════════════════════════════════════════════╝