通过存储过程使用 XML 更新 table 详细信息

Update table details using XML Through Stored Procedures

首先,我已经完成了关于这个主题的相关问题,但是 none 解决了我的问题,因为我的 xml 有一些不同的结构。这就是为什么我在这里问一个关于这个问题的问题。

<Root>
    <MyData>
    <Data>
    <EID>1</EID>
    <PID>246</PID>
    <SID>1</SID>
    </Data>

    <UpdateData>
    <TemplateID>42</TemplateID>
    <UserID>12</UserID>
    </UpdateData>

    <UpdateData>
    <TemplateID>55</TemplateID>
    <UserID>2</UserID>
    </UpdateData>

    <UpdateData>
    <TemplateID>61</TemplateID>
    <UserID>2</UserID>
    </UpdateData>

    <UpdateData>
    <TemplateID>66</TemplateID>
    <UserID>2</UserID>
    </UpdateData>

    <UpdateData>
    <TemplateID>76</TemplateID>
    <UserID>2</UserID>
    </UpdateData>

    <UpdateData>
    <TemplateID>79</TemplateID>
    <UserID>2</UserID>
    </UpdateData>

    </MyData>
    </Root>

我有一个像上面那样的 xml,我想使用特定条件从我的数据库 table 中的那个 XML 更新每个 UserId

我在下面包含了我的 table 结构

Table 姓名:UpdateDetails

列:EID, PID, SID, TemplateID, UserID 所有列都是 int 数据类型

正常查询会像下面这样

update UpdateDetails  
set UserID = @UserID 
where EID = @EID 
  and PID = @PID 
  and SID = @SID 
  and TemplateID = @TemplateID;

但我不知道如何获取 xml 中的所有值并进行更新。

我曾尝试过类似下面的方法,但它不起作用。

CREATE PROCEDURE Details
@xml text 
AS
BEGIN
      SET NOCOUNT ON;
Declare @intPointer int;
declare @PId int;
declare @EId int;
declare @SId int;



set @PId =(SELECT data.item.value('PID', 'int') AS PId
    FROM @xml.nodes('/Root/MyData/Data') data(item));

set @EId =(SELECT data.item.value('EID', 'int') AS EId
    FROM @xml.nodes('/Root/MyData/Data') Delegatedata(item));

set @SId =(SELECT data.item.value('SID', 'int') AS SId
    FROM @xml.nodes('/Root/MyData/Data') data(item));


exec sp_xml_preparedocument @intPointer output, @xml 


      update UpdateDetails set UserID=

 (Select      * 
      from OpenXml(@intPointer,'/Root/MyData/Data',3)
    With (UserID int 'UserID'))

where PID=@PID and SID=@SID and EID=@EID and TemplateID=(Select      * 
      from OpenXml(@intPointer,'/Root/MyData/Data',3)
    With (TemplateID int 'TemplateID'))


END

请帮我解决这个问题。任何帮助将不胜感激。

使用标准的本机 XQuery,您可以相当轻松地解析 XML:

DECLARE @input XML = '.... your XML .....' 

SELECT
    EID = XC.value('(EID)[1]', 'int'),
    PID = XC.value('(PID)[1]', 'int'),
    SID = XC.value('(SID)[1]', 'int'),
    TemplateID = XUC.value('(TemplateID)[1]', 'int'),
    UserID = XUC.value('(UserID)[1]', 'int')
FROM 
    @input.nodes('/Root/MyData/Data') AS XT(XC)
CROSS APPLY
    @input.nodes('/Root/MyData/UpdateData') AS XUT(XUC)

这给你一个输出:

EID PID SID TemplateID  UserID
------------------------------
 1  246  1     42         12
 1  246  1     55          2
 1  246  1     61          2
 1  246  1     66          2
 1  246  1     79          2

基于此,您应该能够制定一个 UPDATE 语句来完成您需要它做的事情。

:不要再使用TEXT数据类型了!它已被弃用 - 因为这确实是 XML - 使用 XML 数据类型!

所以试试存储过程:

CREATE PROCEDURE Details
     @input XML
AS
BEGIN
    WITH XmlCte AS 
    (
        SELECT
            EID = XC.value('(EID)[1]', 'int'),
            PID = XC.value('(PID)[1]', 'int'),
            SID = XC.value('(SID)[1]', 'int'),
            TemplateID = XUC.value('(TemplateID)[1]', 'int'),
            UserID = XUC.value('(UserID)[1]', 'int')
        FROM 
            @input.nodes('/Root/MyData/Data') AS XT(XC)
        CROSS APPLY
            @input.nodes('/Root/MyData/UpdateData') AS XUT(XUC)
    )
    UPDATE ud
    SET UserID = x.UserID
    FROM dbo.UpdateDetails ud
    INNER JOIN XmlCte x ON ud.EID = x.EID 
                        AND ud.PID = x.PID 
                        AND ud.SID = x.SID 
                        AND ud.TemplateID = x.TemplateID
END

XmlCte CTE(通用 Table 表达式)基本上将 @Input XML 解析为关系 table,然后应用 UPDATE 语句使用这些行作为值来更新您的 table with.

将列表传递给此方法以获取数据表

private DataTable GetSupplementaryLessonDataTable(List<SupplementaryLesson> supplementaryLessons)
{
        DataTable dtsupplementaryLessons = new DataTable("supplementaryLessons");
        dtsupplementaryLessons.Columns.Add(new DataColumn("LessonId",
                     Type.GetType("System.Int32")));

        dtsupplementaryLessons.Columns.Add(new DataColumn("IsSmartSyllabus",
                     Type.GetType("System.Int32")));

        foreach (var item in supplementaryLessons)
        {
            DataRow drRow = dtsupplementaryLessons.NewRow();  
            drRow["LessonId"] = item.Id;
            drRow["IsSmartSyllabus"] = Convert.ToInt32(item.Value);
            dtsupplementaryLessons.Rows.Add(drRow);
        }

        return dtsupplementaryLessons;
}

然后转换为 xml 并将其作为 SQL 参数传递

using (StringWriter swStringWriter = new StringWriter())
{
    supplementaryLessonsDataTable.WriteXml(swStringWriter);
    string strsupplementaryLessonsDataTable = swStringWriter.ToString();

    Parameter[] lstParams = new Parameter[]
                 {
                     new Parameter("@supplementaryLessons",strsupplementaryLessonsDataTable,ParameterDirection.Input,DbType.Xml)
                 };

    int intRetValue = DataBaseHelper.ExecuteNonQuery("Admin_UpdateBulkSupplementaryLesson", lstParams);
}

存储过程:

ALTER PROCEDURE Admin_UpdateBulkSupplementaryLesson
    @EmpDetails xml
AS
BEGIN
    WITH XmlCte AS 
    (
        SELECT
            CAST(colx.query('data(LessonId)') AS varchar) AS LessonId,
            CAST(colx.query('data(IsSmartSyllabus)') AS varchar) AS IsSmartSyllabus
        FROM
            @EmpDetails.nodes('DocumentElement/supplementaryLessons') AS TABX(COLX)
    )    
    UPDATE L
    SET L.IsSmartSyllabus = x.IsSmartSyllabus
    FROM Lesson L
    INNER JOIN XmlCte x ON L.LessonId = x.LessonId 
END