0

我将从显示我的表结构开始:

数字表:

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>
-----------------------------------------------------------------------------

标签表:

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

这是更新Numbers.Labels列的存储过程,由我正忙于编写的外部应用程序运行。XML 结构由该外部应用程序生成,具体取决于Labels.Label表中读取的行

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

这里的问题是,如果 2 个人使用自己的会话登录同一个帐户,并且用户 1 尝试运行此更新存储过程,但就在按下按钮进行此更新之前,用户 2 删除了其中的 1 个标签包含在用户 1 的更新会话中的Labels.label表,它将导致 XML 包含“已删除”行,并且当我尝试再次查询数字时可能会出现问题(当我显示标签后的数字时会查询 RGB 列在 jQuery 中标记为具有十六进制彩色背景)

我的想法是在提交更新之前检查构建的 XML 中包含的行是否存在。如何在 TSQL 中实现这一点?或者有什么更好的方法可以推荐吗?

编辑

我们的表结构是有意非规范化的,没有外键约束。

编辑 2

好吧,看来我的问题有点难,或者我脑子太用力了,变得愚蠢:)。我会尽量简化。

  • 在 中的Labels列中Numbers,每个<lbl>元素都必须存在于Labels表中
  • 更新 中的Labels列时Numbers,如果在 XML 中找到表中不存在的 Label,则Labels必须引发错误。
  • XML 是在我的应用程序中预先形成的,这意味着每次运行更新时,Labels列中的旧 XMLNumbers将被我的应用程序生成的新 XML 替换
  • Labels这是我需要检查表中不再存在的 XML 中是否存在标签节点的地方
4

1 回答 1

0

在尝试任何操作之前,我会检查您的 xml 中是否有不在真实表(在数据库中)中的行。如果您发现了什么,请尽早退出。

这是一个罗斯文的例子。

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
于 2013-04-15T13:26:44.957 回答