TL; DR - 我试图转换一个编码为varbinary的XML字符串,将其作为跟踪的一部分保存到NTEXT字段中,返回到XML,以便我可以查看它。
背景: 我在我们的一个接收XML包的服务器上运行了一个跟踪。它的调用方式如下:
exec sp_executesql N'EXEC dbo.myproc @MSG',N'@MSG varbinary(max) ',@MSG=0xFFFE3...
示例repro:
DECLARE @msg XML = '<A>
<B>
<C>1</C>
</B>
</A>'
SELECT CONVERT(VARBINARY(max),@msg)
--0xFFFE3C0041003E003C0042003E003C0043003E0031003C002F0043003E003C002F0042003E003C002F0041003E00
USE tempdb
GO
CREATE TABLE faketrace (id int identity, textdata NTEXT)
CREATE TABLE finished_trace (id int identity, data_value XML)
GO
INSERT INTO faketrace
(textdata)
VALUES ('exec sp_executesql N''EXEC dbo.myproc @MSG'',N''@MSG varbinary(max)'',@MSG=0xFFFE3C0041003E003C0042003E003C0043003E0031003C002F0043003E003C002F0042003E003C002F0041003E00' ) -- textdata - ntext
所以现在我需要提取@MSG并查看XML。
SELECT STUFF(CAST(textdata AS NVARCHAR(max)),1,71,'') FROM faketrace
这给了我0xFFFE ......
但是如何将字段转换回XML?
我有一种有效的作弊方式,但很难看,一次只能做一行。我毫不怀疑有一种方法,但我尝试过的每一个基于版本的版本都会被扼杀。
DECLARE @min int, @max INT, @sql NVARCHAR(MAX)
SELECT @min = MIN(id) , @max = MAX(id) FROM faketrace
WHILE @min <= @max
BEGIN
SET @sql = NULL
SELECT @sql = 'declare @msg varbinary(max)
set @msg = ' + CAST(STUFF(CONVERT(NVARCHAR(MAX),TextData),1,71,'') AS NVARCHAR(MAX))
+ '
select convert(xml, @msg)' FROM faketrace WHERE id = @min
INSERT INTO finished_trace (data_value)
EXEC (@sql)
SET @min = @min + 1
END
答案 0 :(得分:1)
SELECT
textdata,
CAST(textdata AS NVARCHAR(max)),
-- use SUBSTRING instead of STUFF, but LEN won't take an NTEXT, so cast to NVARCHAR
SUBSTRING(textdata, 72, LEN(CAST(textdata AS NVARCHAR(max))) - 71),
-- you can use CONVERT with the third argument of 1
CONVERT(VARBINARY(MAX), SUBSTRING(textdata, 72, LEN(CAST(textdata AS NVARCHAR(max))) - 71), 1),
-- now that you have a valid VARBINARY, you can directly cast to XML
CAST(CONVERT(VARBINARY(MAX), SUBSTRING(textdata, 72, LEN(CAST(textdata AS NVARCHAR(max))) - 71), 1) AS XML)
FROM faketrace