STRING_AGG() Error. Conversion failed when converting the varchar value to data type int

huangapple go评论54阅读模式
英文:

STRING_AGG() Error. Conversion failed when converting the varchar value to data type int

问题

以下是翻译的部分内容:

我需要将一个表格插入/更新触发器转换为Service Broker任务。

INSERTED表被使用,但作为XML变量从触发器传递给存储过程,然后在Broker服务下异步执行。再次强调,这不是问题,因为我已经让触发器/存储过程/代理正常工作,像将数据记录到日志表一样。

以下是一段成功在存储过程中执行并将数据记录到日志表中的代码块。

INSERT INTO [dbo].[MapLocationLog](
    [lo_location]
	, [lo_Location_Code]
)
SELECT
    inserted.[lo_location]
	, inserted.lo_location_Code 
FROM (
	SELECT
		X.query('.').value('(row/lo_Location)[1]', 'int') AS lo_location
		, X.query('.').value('(row/lo_Location_Code)[1]', 'nvarchar(100)') AS lo_location_Code
	FROM @inserted.nodes('inserted/row') AS T(X)
) AS inserted 

这是一个修改,使用STRING_AGG()创建带分隔符的整数数组,也成功记录到表中。请注意,在X.query中的"lo_Location"的类型从INT更改为NVARCHAR(10)。

INSERT INTO [dbo].[MapLocationLog]([lo_Location_Code])
(
    SELECT String_agg(inserted.lo_location, ',')
    FROM (
        SELECT
		    X.query('.').value('(row/lo_Location)[1]', 'nvarchar(10)') AS lo_location
		FROM @inserted.nodes('inserted/row') AS T(X)
	) AS inserted
)

我尝试的是获取逗号分隔的ID列表,并将其用于后续查询过滤。

这是问题出现的地方。

DECLARE @ids NVARCHAR(max) 
SET @ids = (
    SELECT STRING_AGG(inserted.lo_location, ',')
	FROM (
        SELECT
			X.query('.').value('(row/lo_Location)[1]', 'nvarchar(10)') AS lo_location
		FROM @inserted.nodes('inserted/row') AS T(X)
	) AS inserted
)

这是错误:

转换失败,将nvarchar值 '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20' 转换为数据类型int。

错误行在这里:SET @ids = (SELECT STRING_AGG(inserted.lo_location), ',')

我已经检查了很多次,但找不到问题所在。我尝试过

  • 强制转换
    • CAST(inserted.lo_location, NVARCHAR(10))
    • 整个SELECT语句

我唯一关注的是STRING_AGG明确是NVARCHAR/VARCHAR,而XPath值有隐式类型,暗示"1"隐式类型为INT。我不是XPath专家,但这是我的理解。
令人困惑的是,代码认为我试图转换为INT,因为没有INT声明。

感谢任何见解。

英文:

I needed to convert a table insert/update trigger to a Service Broker task.

The INSERTED table is used but is passed from the Trigger as XML variable to the SP and executed asynchronously under the Broker Service. Again this is not the issue as I have the Trigger/SP/Broker working for mundane task like logging data to a log table.

Below is a block of code that was successfully executing within a Stored procedure and logging data to a log table.

INSERT INTO [dbo].[MapLocationLog](
    [lo_location]
	, [lo_Location_Code]
)
SELECT
    inserted.[lo_location]
	, inserted.lo_location_Code 
FROM (
	SELECT
		X.query('.').value('(row/lo_Location)[1]', 'int') AS lo_location
		, X.query('.').value('(row/lo_Location_Code)[1]', 'nvarchar(100)') AS lo_location_Code
	FROM @inserted.nodes('inserted/row') AS T(X)
) AS inserted 

This is a modification that uses STRING_AGG() to create a delimited array of integers. Also logging successfully to a table. Note the change in type in the X.query for "lo_Location" changing from INT to NVARCHAR(10).

INSERT INTO [dbo].[MapLocationLog]([lo_Location_Code])
(
    SELECT String_agg(inserted.lo_location, ',')
    FROM (
        SELECT
		    X.query('.').value('(row/lo_Location)[1]', 'nvarchar(10)') AS lo_location
		FROM @inserted.nodes('inserted/row') AS T(X)
	) AS inserted
)

What I'm trying to do is get a comma delimited list of IDs and use these for subsequent query filtering.

This is where things go wrong.

DECLARE @ids NVARCHAR(max) 
SET @ids = (
    SELECT STRING_AGG(inserted.lo_location), ',')
	FROM (
        SELECT
			X.query('.').value('(row/lo_Location)[1]', 'nvarchar(10)') AS lo_location
		FROM @inserted.nodes('inserted/row') AS T(X)
	) AS inserted
)

This is the error

> Conversion failed when converting the nvarchar value '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20' to data type int.

The error line is on this
SET @ids = (SELECT STRING_AGG(inserted.lo_location), ',')

I have been over this so many times and I cannot find where I'm going wrong. I've tried

  • CASTING
    • CAST(inserted.lo_location, NVARCHAR(10))
    • The whole Select statement

The only thing I can centre on is the STRING_AGG is explicitly NVARCHAR/VARCHAR and the Xpath value has implicit typing suggesting "1" is implicitly type as INT. I'm no expert on Xpath but that's my reading.
What is confusing is where the code thinks I'm trying to convert to INT as there is no INT declarations.

Grateful for any insight.

答案1

得分: 1

根据您的示例,我创建了一个XML并简化了您的查询。
如果您可以提供原始的XML - 那将非常有帮助。

DECLARE @xml XML = '<inserted><row><lo_Location>123</lo_Location></row>' +
                    '<row><lo_Location>222</lo_Location></row>' +
                    '<row><lo_Location>123456789123456</lo_Location></row>' +
                    '<row><lo_Location></lo_Location></row>' +
                    '<row><lo_Location>aaa</lo_Location></row>' +
                    '<row><lo_Location>aaafgnhjfgy</lo_Location></row>' +
                    '<row></row>' +
                    '</inserted>';
DECLARE @out VARCHAR(100)

SELECT @out = STRING_AGG(i.lo_location, ',')
   FROM (
        SELECT
            X.query('.').value('(row/lo_Location)[1]', 'nvarchar(10)') AS lo_location
        FROM @xml.nodes('inserted/row') AS T(X)
   ) i

SELECT @out

结果: 123,222,1234567891,,aaa,aaafgnhjfg

注意:在您的第一个查询中,您使用了整数作为位置,在其他查询中,您使用了nvarchar(10),它应该"接受一切"...
我会假设在表MapLocationLog中,列lo_Location_Code不是整数。
另外,请尽量避免使用保留字,比如inserted/deleted等。

英文:

base on your example I created an xml and simplified your query
if you can provide an original XML - that would be helpful

DECLARE @xml XML = &#39;&lt;inserted&gt;&lt;row&gt;&lt;lo_Location&gt;123&lt;/lo_Location&gt;&lt;/row&gt;&#39;+
					&#39;&lt;row&gt;&lt;lo_Location&gt;222&lt;/lo_Location&gt;&lt;/row&gt;&#39;+
					&#39;&lt;row&gt;&lt;lo_Location&gt;123456789123456&lt;/lo_Location&gt;&lt;/row&gt;&#39;+
					&#39;&lt;row&gt;&lt;lo_Location&gt;&lt;/lo_Location&gt;&lt;/row&gt;&#39;+
					&#39;&lt;row&gt;&lt;lo_Location&gt;aaa&lt;/lo_Location&gt;&lt;/row&gt;&#39;+
					&#39;&lt;row&gt;&lt;lo_Location&gt;aaafgnhjfgy&lt;/lo_Location&gt;&lt;/row&gt;&#39;+
					&#39;&lt;row&gt;&lt;/row&gt;&#39;+
					&#39;&lt;/inserted&gt;&#39;
DECLARE @out VARCHAR(100)

SELECT @out = STRING_AGG(i.lo_location, &#39;,&#39;)
   FROM (
        SELECT
            X.query(&#39;.&#39;).value(&#39;(row/lo_Location)[1]&#39;, &#39;nvarchar(10)&#39;) AS lo_location
        FROM @xml.nodes(&#39;inserted/row&#39;) AS T(X)
   ) i

SELECT @out

result: 123,222,1234567891,,aaa,aaafgnhjfg

NOTE: in your first query you are using location as integer, in other queries you have nvarchar(10), which should "eat everything"...
i would assume in table MapLocationLog column lo_Location_Code is NOT integer.
In addition, TRY TO AVOID USING RESERVED WORDS. such as inserted/deleted, etc..

huangapple
  • 本文由 发表于 2023年5月25日 14:32:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76329483.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定