我有以下代码来创建一个SQL函数,它将解析XML字符串并创建一个表示节点和值的键值对表。在我的用例中,这对我来说很好。
CREATE FUNCTION XmlToKeyValue
(
@rootName AS varchar(256),
@xml AS Xml
)
RETURNS @keyval TABLE ([key] varchar(max), [value] varchar(max))
AS
BEGIN
DECLARE @input TABLE (XmlData XML NOT NULL)
INSERT INTO @input VALUES(@xml)
INSERT @keyval ([key], [value])
SELECT
XC.value('local-name(.)', 'varchar(max)') AS [key],
XC.value('(.)[1]', 'varchar(max)') AS [value]
FROM
@input
CROSS APPLY
XmlData.nodes('/*[local-name()=sql:variable("@rootName")]/*') AS XT(XC)
RETURN
END
我要做的是在我的主数据库中有一个存储过程,它将创建另一个包含所有相应函数/过程/等的数据库。所以在那个存储过程中,我试图做这样的事情:
SET @cmd = '
CREATE FUNCTION XmlToKeyValue
(
@rootName AS varchar(256),
@xml AS Xml
)
RETURNS @keyval TABLE ([key] varchar(max), [value] varchar(max))
AS
BEGIN
DECLARE @input TABLE (XmlData XML NOT NULL)
INSERT INTO @input VALUES(@xml)
INSERT @keyval ([key], [value])
SELECT
XC.value(''local-name(.)'', ''varchar(max)'') AS [key],
XC.value(''(.)[1]'', ''varchar(max)'') AS [value]
FROM
@input
CROSS APPLY
XmlData.nodes(''/*[local-name()=sql:variable("@rootName")]/*'') AS XT(XC)
RETURN
END
'
BEGIN TRY
EXEC(N'USE '+@dbName+'; EXEC sp_executesql N''' + @cmd + '''; USE master')
END TRY
BEGIN CATCH
PRINT 'Error creating XmlToKeyValue'
Print Error_Message();
RETURN
END CATCH
但是,我收到以下错误,我无法弄清楚如何解决。
Error creating XmlToKeyValue
Incorrect syntax near 'local'.
我可以在动态sql语句中使用local-name
吗?如果没有,我怎样才能实现目标?谢谢。
答案 0 :(得分:1)
问题不在于local-name
功能。事实上,您将@cmd
变量连接到动态SQL中,而没有正确地转义嵌入的单引号。
这一行:
EXEC(N'USE '+@dbName+'; EXEC sp_executesql N''' + @cmd + '''; USE master')
应该是:
SET @cmd = REPLACE(@cmd, N'''', N'''''');
EXEC(N'USE ' + @dbName + N'; EXEC sp_executesql N''' + @cmd + N''';');
否则你要嵌入:
XC.value(''local-name(
进入字符串,但使用相同数量的转义序列,因此XC.value(
现在成为字符串的结尾,而local-name(.)
在技术上是未转义的SQL而不是字符串的一部分。
此外:
USE master
(所以我删除了它)。N
作为前缀,但没有其他字符串(我为其他字符添加了N
,以便它们都具有该前缀)。