問題描述
我將首先顯示我的表結構:
數字表:
Id AccountId MobileNr FirstName LastName AttributeKeyValues 標簽--- ---------- ----------- ---------- ----------- -------------------- -------490 2000046 2XXXXXXXXXX Eon du Plessis <attrs/><lbs><lbl>Meep11e</lbl><lbl>43210</lbl><lbl>1234</lbl><lbl>標簽5</lbl><lbl>標簽 6(編輯)</lbl></lbs>-----------------------------------------------------------------------------
標簽表:
Id AccountId Label RGB LastAssigned LastMessage----------- ----------- ----------------- ------ ----------------------- -----------91 2000046 Meep11e 000000 2013-04-15 13:42:06.660 NULL-----------------------------------------------------------------------
這是問題
每個數字都可以分配多個標簽,并存儲為無類型 XML.在 Numbers.Labels
//lbls/lbl/text()
中,您會注意到那里的文本將與 Labels.Label
<中的文本匹配/p>
這是更新 Numbers.Labels
列的存儲過程,由我正在編寫的外部應用程序運行.XML 結構由此外部應用程序生成,具體取決于在 Labels.Label
表
創建程序 [dbo].[UpdateLabels]@Id INT,@Labels XML作為開始更新數字放標簽 = @標簽在哪里Id = @Id更新標簽放最后分配 = GETDATE()在哪里標簽在(SELECT @Labels.value('(//lbls/lbl)[1]', 'VARCHAR(100)'))結尾
這里的問題是,如果 2 個人使用他們自己的會話登錄同一個帳戶,并且用戶 1 嘗試運行此更新存儲過程,但就在按下按鈕進行此更新之前,用戶 2 刪除了其中的 1 個用戶 1 的更新會話中包含的 Labels.label
表中的標簽,它會導致 XML 包含已刪除"行,并且當我再次嘗試查詢數字時可能會出現問題(RGB 列在我顯示數字時被查詢,因為標簽在 jQuery 中被標記為具有十六進制彩色背景)
我的想法是在提交更新之前檢查構建的 XML 中包含的行是否存在.我怎樣才能在 TSQL 中實現這一點?或者有什么更好的方法可以推薦?
編輯
我們的表結構是故意非規范化的,沒有外鍵約束.
編輯 2
好吧,看來我的問題有點難,或者我腦子太硬了而變得愚蠢:).我會盡量簡化.
- 在
Numbers
的Labels
列中,每個
元素都必須存在于Labels
表中 - 更新
Numbers
中的Labels
列時,如果發現XML中的Label在Labels
表中不存在,必須引發錯誤. - XML 是在我的應用程序中預先形成的,這意味著每次運行更新時,
Numbers
中Labels
列中的舊 XML 將被替換為我的應用程序生成的新 XML - 這是我需要檢查我的 XML 中是否存在
Labels
表中不再存在的標簽節點
在嘗試任何操作之前,我會檢查您的 xml 中是否有不在真實表(在數據庫中)中的行.如果你發現了什么,早點退出.
這是一個 Northwind 的例子.
使用北風走聲明@data XML;設置@數據=N'<根><訂單><OrderId>10248</OrderId><CustomerId>VINET</CustomerId></訂單><訂單><OrderId>-9999</OrderId><CustomerId>CHOPS</CustomerId></訂單>';/* 從 dbo.Orders 中選擇 * */聲明@Holder 表( OrderId int, CustomerId nchar(5) )插入到@Holder (OrderId , CustomerId )選擇T.myAlias.value('(./OrderId)[1]', 'int') AS OrderId, T.myAlias.value('(./CustomerId)[1]', 'nchar(5)') AS CustomerId從@data.nodes('//root/Order') AS T(myAlias);如果存在(從不存在的@Holder h 中選擇空值(從 dbo.Orders realTable 中選擇空值,其中 realTable.OrderID = h.OrderId ))開始打印 '你的 xml 中有不在真實表中的行.在這里引發錯誤'結尾別的開始打印使用數據"更新 dbo.Orders 設置 CustomerID = h.CustomerId來自 dbo.Orders o ,@Holder h其中 o.OrderID = h.OrderId結尾
I am going to start off by displaying my table structures:
Numbers Table:
Id AccountId MobileNr FirstName LastName AttributeKeyValues Labels
--- ---------- ----------- ---------- ----------- ------------------- -------
490 2000046 2XXXXXXXXXX Eon du Plessis <attrs /> <lbls>
<lbl>Meep11e</lbl>
<lbl>43210</lbl>
<lbl>1234</lbl>
<lbl>Label 5</lbl>
<lbl>Label 6 (edit)</lbl>
</lbls>
-----------------------------------------------------------------------------
Labels Table:
Id AccountId Label RGB LastAssigned LastMessage
----------- ----------- ----------------- ------ ----------------------- ------------
91 2000046 Meep11e 000000 2013-04-15 13:42:06.660 NULL
-------------------------------------------------------------------------------------
This is the issue
Every number can have multiple labels assigned to it and is stored as untyped XML. In Numbers.Labels
//lbls/lbl/text()
you will notice that the text there will match the text in Labels.Label
This is the stored procedure which updates the Numbers.Labels
column, and is run by an external application I am busy writing. The XML structure is generated by this external application, depending on which rows are read in the Labels.Label
table
CREATE PROCEDURE [dbo].[UpdateLabels]
@Id INT,
@Labels XML
AS
BEGIN
UPDATE
Numbers
SET
Labels = @Labels
WHERE
Id = @Id
UPDATE
Labels
SET
LastAssigned = GETDATE()
WHERE
label
IN
(SELECT @Labels.value('(//lbls/lbl)[1]', 'VARCHAR(100)'))
END
The issue here is if 2 people log onto the same account, both with their own session, and User 1 tries to run this update stored procedure, but just before the button is pressed to do this update, user 2 deletes 1 of the labels in the Labels.label
table which was included in User 1's update session, it will cause the XML to include the "Deleted" row, and can be problematic when I try to query the numbers again (The RGB column gets queried when I display the number since the label is marked up in jQuery to have a hexidecimal colored background)
My thought approach went to checking if the rows included in the built up XML exists before committing the update. How can I achieve this in TSQL? Or can any better way be recommended?
EDIT
Our table structure is intentionally denormalized, there are no foreign key constraints.
EDIT 2
Ok, it would seem my question is a bit hard, or that I brained too hard and got the dumb :). I will try and simplify.
- In the
Labels
column inNumbers
, every<lbl>
element must exist within theLabels
table - When updating the
Labels
column inNumbers
, if a Label in the XML is found which does not exist in theLabels
table, an error must be raised. - The XML is pre-formed in my application, meaning, every time the update is run, the old XML in the
Labels
column inNumbers
will be REPLACED with the new XML generated by my application - This is where I need to check whether there are label nodes in my XML which no longer exists within the
Labels
table
I would check to see if there are rows in your xml that are not in the real table (in the database) before trying anything. And if you find something, exit out early.
Here is a Northwind example.
Use Northwind
GO
DECLARE @data XML;
SET @data =
N'
<root>
<Order>
<OrderId>10248</OrderId>
<CustomerId>VINET</CustomerId>
</Order>
<Order>
<OrderId>-9999</OrderId>
<CustomerId>CHOPS</CustomerId>
</Order>
</root>';
/* select * from dbo.Orders */
declare @Holder table ( OrderId int, CustomerId nchar(5) )
Insert Into @Holder (OrderId , CustomerId )
SELECT
T.myAlias.value('(./OrderId)[1]', 'int') AS OrderId
, T.myAlias.value('(./CustomerId)[1]', 'nchar(5)') AS CustomerId
FROM
@data.nodes('//root/Order') AS T(myAlias);
if exists (select null from @Holder h where not exists (select null from dbo.Orders realTable where realTable.OrderID = h.OrderId ))
BEGIN
print 'you have rows in your xml that are not in the real table. raise an error here'
END
Else
BEGIN
print 'Using the data'
Update dbo.Orders Set CustomerID = h.CustomerId
From dbo.Orders o , @Holder h
Where o.OrderID = h.OrderId
END
這篇關于TSQL 中無類型 XML 的參照完整性問題的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!