看起来,好像你想要一个通用的 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/XPath和sql:variable()中使用这个变量
SET @xml.modify(N'replace value of (//Field[Name="ID"]/Value/text())[1] with sql:variable("@ReplaceID")');
SELECT @xml;