【问题标题】:How to use local-name(.) within dynamic sql statement如何在动态 sql 语句中使用 local-name(.)
【发布时间】:2015-06-02 17:43:52
【问题描述】:

我有以下代码来创建一个 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吗?如果没有,我怎样才能实现我的目标?谢谢。

【问题讨论】:

  • 如果你PRINT@cmd,看起来正确吗?
  • @RickS 是的,当我打印它时,它与没有动态 sql 的代码块相同。
  • 你可以把打印出来的东西用短信执行吗?
  • @RickS 是的。这些是我在发布之前检查的内容。
  • 作为一个测试,尝试去掉本地名称中的破折号,这样你就有了localname。也许破折号给你带来了麻烦。

标签: sql-server stored-procedures dynamic-sql sqlxml sql-function


【解决方案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,而不是字符串的一部分。

还有:

  1. 您不需要动态 SQL 末尾的 USE master(因此我将其删除)。
  2. 您为第一个字符串文字添加了 N 前缀,但其他都没有(我在其他字符串中添加了 N,以便它们都具有该前缀)。

【讨论】:

    猜你喜欢
    • 2011-06-05
    • 2021-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-01
    • 1970-01-01
    相关资源
    最近更新 更多