這取決於什麼是錯誤?
這可能是
- 無效的XML(僅當您在XML作爲字符串傳遞,並在內部將其丟)
- 無效的內部藥結構(節點/屬性丟失,損壞嵌套...)
在石膏
- 錯誤的值(應該是
INT
,但並不)
- 遭破壞的商業規則(例如值不能爲1,如果其他值爲0)
無論如何:一個聲明是一個步驟。它將全部工作,否則將失敗。達到你想要什麼
一種方法是一行一行地辦法(CURSOR
),第二個是用一個臨時表一組爲基礎的方法:
作爲一個例子,我認爲這是錯誤的值,但總的方法應該是完全一樣的其他問題:
第二個數據節點具有無效valueInt
DECLARE @passedIn XML=
'<root>
<data rowID="1">
<valueInt>111</valueInt>
<valueString>hello1</valueString>
</data>
<data rowID="2">
<valueInt>222xyz</valueInt>
<valueString>hello2</valueString>
</data>
<data rowID="3">
<valueInt>333</valueInt>
<valueString>hello3</valueString>
</data>
</root>';
這是CURSOR
方法
DECLARE @target TABLE(RowID INT,valueInt INT,valueString NVARCHAR(MAX));
DECLARE @errors TABLE(rowID INT,DataNode XML);
DECLARE @rowID INT;
DECLARE @vInt NVARCHAR(MAX); --type is NVARCHAR!!!
DECLARE @vString NVARCHAR(MAX);
DECLARE @DataNode XML;
DECLARE cur CURSOR FOR
(
SELECT data.value('@rowID','int') AS RowID
,data.value('valueInt[1]','nvarchar(max)') AS ValueInt --type is NVARCHAR!!!
,data.value('valueString[1]','nvarchar(max)') AS ValueString
,data.query('.') AS DataNode
FROM @passedIn.nodes('/root/data') AS A(data)
);
OPEN cur;
FETCH NEXT FROM cur INTO @rowID,@vInt,@vString,@DataNode;
WHILE @@FETCH_STATUS=0
BEGIN
BEGIN TRY
INSERT INTO @target VALUES(@rowID,@vInt,@vString);
END TRY
BEGIN CATCH
INSERT INTO @errors VALUES(@rowID,@DataNode);
END CATCH
FETCH NEXT FROM cur INTO @rowID,@vInt,@vString,@DataNode;
END
CLOSE cur;
DEALLOCATE cur;
--This is the result
SELECT * FROM @target;
SELECT * FROM @errors;
清理並重新開始通過臨時表
DELETE FROM @target;
DELETE FROM @errors;
SELECT data.value('@rowID','int') AS RowID
,data.value('valueInt[1]','nvarchar(max)') AS ValueInt --type is NVARCHAR!!!
,data.value('valueString[1]','nvarchar(max)') AS ValueString
,data.query('.') AS DataNode
INTO #stagingTable
FROM @passedIn.nodes('/root/data') AS A(data);
INSERT INTO @target
SELECT RowID,ValueInt,ValueString
FROM #stagingTable
WHERE ISNUMERIC(ValueInt)=1;
INSERT INTO @errors
SELECT RowID,DataNode
FROM #stagingTable
WHERE ISNUMERIC(ValueInt)=0;
SELECT * FROM @target;
SELECT * FROM @errors;
GO
DROP TABLE #stagingTable;
嗨基於集合的方法,這是仍處於打開狀態?你需要進一步的幫助嗎?如果這個問題得到解決,那麼在最佳答案的投票櫃檯下面勾選驗收將會很好。這將1)標記這個問題已解決2)使追隨者更容易找到最佳的解決方案3)支付點給回答者和4)支付點給你。一旦你自己超過了15分的邊界,你又被要求對貢獻進行投票。這是SO的方式來說聲謝謝。快樂編碼! – Shnugo