【问题标题】:Adding variables to a SQL Server stored procedure that takes XML as a param将变量添加到将 XML 作为参数的 SQL Server 存储过程
【发布时间】:2017-11-22 21:48:43
【问题描述】:

在将 XML 传递给存储过程时可以使用变量吗?我试图避免手动查询,然后将其粘贴到 XML 中以执行存储过程。

例如下面的例子可以传递NEWID() 甚至SELECT 语句来获取其中一个XML 记录——即ID?

exec spChangeRecordXML '<SP_ChangeRecordXML><Details><TableName>table1</TableName><ModificationType>Insert</ModificationType><Field><Name>ID</Name><Value>9b99e3ce-a675-44b9-9c6e-cedc1a1c2834</Value></Field><Field><Name>strtName</Name><Value>TEST2</Value></Field><Field><Name>strName</Name><Value>TEST2</Value></Field><Field><Name>DeptID</Name><Value>5894f6cc-7236-482a-af0f-08d0d15e6d5c</Value></Field></SP_ChangeRecordXML>'

【问题讨论】:

    标签: sql-server xml stored-procedures


    【解决方案1】:

    SP 的参数可以是您喜欢的任何数据类型,包括自定义数据类型(这是您可以传递表参数的方式)。拥有一个带有 xml 参数的 SP 是完全可以接受的。

    【讨论】:

    • 但是我可以动态生成该 XML 的一部分,例如一个新的 GUID,如果可以,如何通过?
    • @user3543017 谁将成为调用者(=XML 的发送者)?数据库中的外部应用程序或其他代码?
    • 我自己手动拨打电话。 SP 已经写好了,我基本上是在试图绕过位于它前面的 GUI。虽然我可以通过执行 SP 并手动生成一些必要的标识符来做到这一点,但我正在尝试动态地这样做,以避免在调用 SP 之前运行一些选择语句。
    【解决方案2】:

    看起来,好像你想要一个通用的 SP 来进行任何类型的数据操作。您发送 嘿,将以下字段插入我的表“table1”! 并且 SP 形成适当的语句并针对数据库执行此语句。对吗?

    关于您的问题:

    拥有一个带有 XML 参数的 SP 是完全可以的:

    CREATE PROCEDURE dbo.TestWithXML(@SomeXML XML)
    AS
    BEGIN
        --Do something with the XML
        SELECT fld.value(N'(Name/text())[1]',N'nvarchar(max)')
              ,fld.value(N'(Value/text())[1]',N'nvarchar(max)')
        FROM @SomeXml.nodes(N'//Field') AS A(fld)
    END
    GO
    

    --现在我用各种方式称呼这个SP:

    --fill a variable with a given XML
    DECLARE @xml XML=
    N'<SP_ChangeRecordXML>
      <Details>
        <TableName>table1</TableName>
        <ModificationType>Insert</ModificationType>
        <Field>
          <Name>ID</Name>
          <Value>9b99e3ce-a675-44b9-9c6e-cedc1a1c2834</Value>
        </Field>
        <Field>
          <Name>strtName</Name>
          <Value>TEST2</Value>
        </Field>
        <Field>
          <Name>strName</Name>
          <Value>TEST2</Value>
        </Field>
        <Field>
          <Name>DeptID</Name>
          <Value>5894f6cc-7236-482a-af0f-08d0d15e6d5c</Value>
        </Field>
      </Details>
    </SP_ChangeRecordXML>'
    
    --call the SP with an XML variable
    EXEC dbo.TestWithXML @SomeXML=@xml;
    
    --call the SP with an XML on string base
    EXEC dbo.TestWithXML @SomeXML='<root><Field><Name>SomeName</Name><Value>SomeValue</Value></Field></root>';
    
    --Set the variable from above to an XML "on the fly"
    SET @xml=(SELECT 'testName' AS [Name], 'testValue' AS [Value] FOR XML PATH('Field'),ROOT('root'),TYPE);
    --and call the SP with this
    EXEC dbo.TestWithXML @SomeXML=@xml;
    
    --Clean up
    GO
    DROP PROCEDURE dbo.TestWithXML;
    

    对我来说更重要的是关于代码这个SP中的问题。

    通用方法很好,但部署后往往会变得丑陋...

    XML 作为参数非常棒,因为您可以传递任何种类和数量的数据。但是SP丢失了,如果你不知道里面是什么。此 XML 的结构不得更改(否则您需要版本控制 - 更糟!)

    从 XML 读取可能还需要一些元数据,尤其是数据类型。好吧,可以依靠隐式转换,将所有内容读取为字符串并将其传递到引号内的INSERT。这在大多数情况下都有效(确保您在 ISO8601 中使用 datetime 并且它不适用于 base64 编码的二进制文件......)。我可能会从INFORMATION_SCHEMA.column 阅读DATA_TYPE

    最好为所有表生成 CRUD 过程并在内部调用它们,使用 XML 的工作负载作为参数。这将允许您实施业务规则,而不会使您的通用 SP 膨胀。

    UPDATE 修改 XML

    从您的评论中我知道您可能需要其他东西:

    DECLARE @xml XML=
    N'<SP_ChangeRecordXML>
      <Details>
        <TableName>table1</TableName>
        <ModificationType>Insert</ModificationType>
        <Field>
          <Name>ID</Name>
          <Value>9b99e3ce-a675-44b9-9c6e-cedc1a1c2834</Value>
        </Field>
        <Field>
          <Name>strtName</Name>
          <Value>TEST2</Value>
        </Field>
        <Field>
          <Name>strName</Name>
          <Value>TEST2</Value>
        </Field>
        <Field>
          <Name>DeptID</Name>
          <Value>5894f6cc-7236-482a-af0f-08d0d15e6d5c</Value>
        </Field>
      </Details>
    </SP_ChangeRecordXML>';
    

    --声明一个变量持有然后新的值

    DECLARE @ReplaceID UNIQUEIDENTIFIER=NEWID();
    SELECT @ReplaceID;
    

    --在XQuery/XPathsql:variable()中使用这个变量

    SET @xml.modify(N'replace value of (//Field[Name="ID"]/Value/text())[1] with sql:variable("@ReplaceID")');
    SELECT @xml;
    

    【讨论】:

    • 我会尝试这样的事情:为 NEWID() 声明一个变量并将其传递给字段“ID”的 xml。
    • @user3543017 它认为您正在寻找.modify()。查看我的更新。
    猜你喜欢
    • 2014-07-30
    • 1970-01-01
    • 2015-12-20
    • 1970-01-01
    • 2023-03-20
    • 2016-09-25
    • 2019-03-17
    • 2012-07-11
    • 1970-01-01
    相关资源
    最近更新 更多