如何在动态 sql 语句中使用 local-name(.)
How to use local-name(.) within dynamic sql statement
我有以下代码来创建 SQL 函数,该函数将解析 XML 字符串并创建 table 表示节点和值的键值对。这在我的用例中对我来说很好用。
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
我想做的是在我的主数据库中有一个存储过程,它将创建另一个具有所有适当 functions/procedures/etc 的数据库。所以在那个存储过程中我试图做这样的事情:
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
吗?如果没有,我怎样才能实现我的目标?谢谢。
问题不在于 local-name
函数。这完全是您将 @cmd
变量连接到 Dynamic 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 而不是部分一个字符串。
还有:
- 动态 SQL 末尾不需要
USE master
(所以我删除了它)。
- 您在第一个字符串文字前添加了
N
前缀,但在其他字符串文字中添加了 none(我为其他字符串添加了 N
,以便它们都具有该前缀)。
我有以下代码来创建 SQL 函数,该函数将解析 XML 字符串并创建 table 表示节点和值的键值对。这在我的用例中对我来说很好用。
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
我想做的是在我的主数据库中有一个存储过程,它将创建另一个具有所有适当 functions/procedures/etc 的数据库。所以在那个存储过程中我试图做这样的事情:
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
吗?如果没有,我怎样才能实现我的目标?谢谢。
问题不在于 local-name
函数。这完全是您将 @cmd
变量连接到 Dynamic 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 而不是部分一个字符串。
还有:
- 动态 SQL 末尾不需要
USE master
(所以我删除了它)。 - 您在第一个字符串文字前添加了
N
前缀,但在其他字符串文字中添加了 none(我为其他字符串添加了N
,以便它们都具有该前缀)。