将XML传递给存储过程时可以使用变量吗?我试图避免必须进行手动查询,然后将其粘贴到XML中以执行存储过程。
例如,下面可以为其中一条XML记录传递NEWID()
甚至SELECT
语句 - 即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>'
答案 0 :(得分:0)
SP的参数可以是您喜欢的任何数据类型,包括自定义数据类型(可以传递表参数的方式)。拥有带有xml参数的SP是完全可以接受的。
答案 1 :(得分:0)
看起来好像你想拥有一个通用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;
对我来说更重要的是关于
通用方法很好,但在部署时往往变得丑陋......
XML作为参数非常棒,因为您可以传递任何类型和数量的数据。但如果你不知道里面是什么,SP就会丢失。这个XML的结构不能改变(否则你需要版本控制 - 更糟糕的是!)
从XML读取可能还需要一些元数据,尤其是数据类型。好吧,可以依赖隐式转换,将所有内容读作字符串并将其传递到引号内的INSERT
。这在大多数情况下都有效(确保在ISO8601中使用日期时间,并且它不适用于base64编码的二进制文件......)。我可能会从DATA_TYPE
阅读INFORMATION_SCHEMA.column
。
为所有表生成CRUD过程并使用XML的工作负载作为参数在内部调用它们可能是个好主意。这将允许您实现业务规则,而不会使您的通用SP膨胀。
从你的评论中我得到了一个想法,你可能还需要别的东西:
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;