【问题标题】:The argument 1 of the XML data type method “value” must be a string literalXML 数据类型方法“value”的参数 1 必须是字符串文字
【发布时间】:2020-04-19 02:45:12
【问题描述】:

如果我传递@count 变量,我会收到此错误

以下是我的查询

DECLARE @Error_Description NVARCHAR(Max)
DECLARE @Count VARCHAR(20)
DECLARE @x NVARCHAR(Max)

SELECT @Error_Description = 'The external columns for Excel Source are out of synchronization with the data source columns. 
The column "szReferencceNumber" needs to be added to the external columns.
The column "SMSa" needs to be added to the external columns.
The column "as" needs to be added to the external columns.'

SELECT @Count = (LEN(@Error_Description) - LEN(REPLACE(@Error_Description, '"', ''))) / LEN('"')

SELECT @Count

SELECT COALESCE(LTRIM(CAST(('<X>' + REPLACE(@Error_Description, '"', '</X><X>') + '</X>') AS XML).value('(/X)[' + @Count + ']', 'varchar(128)')), '')

【问题讨论】:

  • 这里的错误很清楚。你的实际目标是什么?
  • @Larnu 我需要引号之间的字符串。如果我运行此查询,它工作正常。 SELECT COALESCE(LTRIM(CAST(('&lt;X&gt;'+REPLACE(@Error_Description,'"' ,'&lt;/X&gt;&lt;X&gt;')+'&lt;/X&gt;') AS XML).value('(/X)[2]', 'varchar(128)')), '')
  • 我将这个问题复制为@Larnu 您是否更喜欢将数据存储在表变量中。然后我们可以使用交叉申请。
  • 正如错误消息所说,第一个参数需要是字符串文字。不是 '(/X)[' + @Count + ']' 之类的表达式 - 因此您可以通过动态构造整个 SQL 字符串并在其中连接 @Count 来做到这一点 - 但如果您解释您尝试做的实际最终要求,可能会有更好的方法
  • 引号内有多个字符串 (") 尽管 @SubhashManikantaKumarMogili 。你没有解释你的真正目标是什么,所以我们很难帮助你。

标签: sql sql-server xml tsql


【解决方案1】:

value 的第一个参数必须是字符串文字。要选择具有动态索引的节点,您可以执行以下操作

SELECT 
n.value('.', 'varchar(128)') as Result
from (SELECT CAST(('<X>' + REPLACE(@Error_Description, '"', '</X><X>') + '</X>') AS XML)) ca(x)
CROSS APPLY x.nodes('(/X)') n(n)
WHERE n.value('for $l in . return count(../*[. << $l]) + 1', 'int') %2 = 0

这将返回每隔一个节点的值。这样就可以实现将值括在引号中的期望结果。

Result
---------------------
szReferencceNumber
SMSa
as

【讨论】:

    【解决方案2】:

    如果您使用的是 2012+,并且可以使用 nvarchar(4000)(而不是 MAX),则可以获取 DelimitedSplitN4K_LEAD 的副本并抓取 ItemNumber 的值为偶数的行:

    DECLARE @Error_Description nvarchar(4000);
    
    SELECT @Error_Description = N'The external columns for Excel Source are out of synchronization with the data source columns. 
    The column "szReferencceNumber" needs to be added to the external columns.
    The column "SMSa" needs to be added to the external columns.
    The column "as" needs to be added to the external columns.';
    
    SELECT DS.Item
    FROM dbo.DelimitedSplitN4K_LEAD(@Error_Description,'"') DS
    WHERE DS.ItemNumber % 2 = 0;
    

    如果您使用的是 SQL Server 2016+,那么您可以使用一些 JSON 操作(支持 MAX 值):

    SELECT OJ.value
    FROM (VALUES(@Error_Description))V(Error_Description)
         CROSS APPLY (VALUES('["' + REPLACE(REPLACE(REPLACE(V.Error_Description,'"','","'),NCHAR(13),''),NCHAR(10),'')+ '"]'))R(JSON)
         CROSS APPLY OPENJSON(R.JSON) OJ
    WHERE OJ.[Key] % 2 = 1;
    

    【讨论】:

      【解决方案3】:

      您可以在 XQuery 谓词中使用 @Count,但不能通过串联。有sql:variable()

      TheXml.value('(/X)[sql:variable("@Count") cast as xs:int?][1]', 'varchar(128)')
      

      将变量 @Count 声明为 INT 有助于避免 XQuery 强制转换。

      提示:您需要最后的 [1] 来强制执行单例 .value() 要求。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-07
        • 2018-11-18
        • 2022-08-21
        • 2023-02-14
        • 2021-06-02
        相关资源
        最近更新 更多