【问题标题】:SQL Server : manipulating complex xml into tablesSQL Server:将复杂的 xml 操作到表中
【发布时间】:2013-05-11 14:30:24
【问题描述】:

我有一些 XML 需要插入到两个数据库表中。第二个表 (TblSales) 必须包含第一个表 (TblDetails.Id) 的 PK。

我可以使用 XQuery 将数据插入到这些表中,但我想不出一种将 TblDetails 的 PK 转换为 TblSales 的 FK (DetailsId) 的好方法?

我使用的是 SQL Server 2005。

DECLARE @xml XML
SET @xml = 
N'<Details>
    <Detail>
        <Sub>SubjectName 1</Sub>
        <Data>DataName 1</Data>
        <Sales>
            <Sale>
                <Name>Name 1</Name>
            </Sale>
            <Sale>
                <Name>Name 11</Name>
            </Sale>
            <Sale>
                <Name>Name 111</Name>
            </Sale>
        </Sales>
    </Detail>
    <Detail>
        <Sub>SubjectName 2</Sub>
        <Data>DataName 2</Data>
        <Sales>
            <Sale>
                <Name>Name 2</Name>
            </Sale>
            <Sale>
                <Name>Name 22</Name>
            </Sale>
            <Sale>
                <Name>Name 222</Name>
            </Sale>
        </Sales>
    </Detail>
</Details>'

-- Details

IF object_id('TblDetails') is not null
    drop table TblDetails

create table TblDetails ( 
    Id int identity not null primary key, 
    Sub nvarchar(max),
    Data nvarchar(max)) 

INSERT INTO TblDetails (
    Sub, 
    Data
)
SELECT
    ParamValues.Detail.value('(Sub)[1]','NVARCHAR(MAX)') AS [Sub],
    ParamValues.Detail.value('(Data)[1]','NVARCHAR(MAX)') AS [Data]
FROM 
    @xml.nodes('/Details/Detail') AS ParamValues(Detail)


-- Sales

IF object_id('TblSales') is not null
    drop table TblSales

create table TblSales ( 
    Id int identity not null primary key, 
    Name nvarchar(max),
    DetailsId int) -- FK to TblDetails.Id PK

INSERT INTO TblSales (
    Name, 
    DetailsId
)
SELECT
    ParamValues.Sale.value('(Name)[1]','NVARCHAR(MAX)') AS [Name],
    1 --Need to get the PK of the newly added row in TblDetails
FROM 
    @xml.nodes('/Details/Detail/Sales/Sale') AS ParamValues(Sale)



select * from TblDetails
select * from TblSales

【问题讨论】:

    标签: sql xml sql-server-2005 xquery


    【解决方案1】:

    嗯,你可以试试这样的:

    -- first insert your rows into "TblDetails"
    INSERT INTO dbo.TblDetails(Sub, Data)
       SELECT
          ParamValues.Detail.value('(Sub)[1]','VARCHAR(50)') AS [Sub],
          ParamValues.Detail.value('(Data)[1]','VARCHAR(50)') AS [Data]
       FROM 
          @xml.nodes('/Details/Detail') AS ParamValues(Detail)
    
    -- now, in a second step, use a CTE (Common Table Expression) to get the
    -- inserted data and the new data for TblSales
    ;WITH CTE AS 
    (
        SELECT
            ParamValues.Detail.value('(Sub)[1]','VARCHAR(50)') AS [Sub],
            ParamValues.Detail.value('(Data)[1]','VARCHAR(50)') AS [Data],
            XTbl.Sale.value('(Name)[1]', 'VARCHAR(50)') AS [Name]
        FROM 
            @xml.nodes('/Details/Detail') AS ParamValues(Detail)
        CROSS APPLY
            ParamValues.Detail.nodes('Sales/Sale') AS XTbl(Sale)
    )
    INSERT INTO dbo.TblSales(Name, DetailsId)
       SELECT 
          Name,
          (SELECT TOP  1 ID    -- fetch the ID from the TblDetails based on "Sub" and "Data"
           FROM TblDetails d 
           WHERE d.Sub = CTE.Sub AND d.Data = CTE.DATA)     
       FROM CTE
    

    当然,只有当您的 (Sub, Data) 组合在 TblDetails 中是唯一的时,这种方法才真正有效。也许你需要稍微调整一下——但我希望这应该是一个很好的起点!

    【讨论】:

    • 谢谢,很遗憾,TblDetails 中的数据不能保证是唯一的。这是用于执行此类程序的常用技术吗?另一种选择是向表“TblSales”添加一个附加列,该列将存储“SalesXml”数据。然后,当“TblDetails”上的“插入”发生时,我可以将“插入的 TblDetails.Id”和“插入的 TblDetails.SalesXml”“输出”到临时表中。但这是向表中添加仅此过程所需的额外数据。
    • @DanielBillingham:如果您的 (Sub,Data) 不能是唯一的 - 那么您必须在源 XML 中有其他内容,您可以通过这些内容唯一标识 &lt;Detail&gt; 节点- 否则这将永远无法工作......
    猜你喜欢
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多