我有一个数据库(无论出于何种原因)有一个包含管道分隔数据的列。
我想快速解析这些数据,所以我想通过用XML属性替换管道并将其放入其他地方的XML数据类型列中,将此列(nvarchar)转换为XML。
它有效,除非该列具有需要编码的字符,例如'<'字符。
我发现我可以使用FOR XML子句对XML进行编码,但是,它似乎会在数据周围注入一些XML标记。
例如:(这会给不良角色带来错误)
SELECT CAST('<f>' + replace(value,'|','</f><f>') + '</f>' AS XML)
FROM TABLE
这给出了xml编码值,但将其包装在“&lt; value&gt;&lt; / value&gt;”中标签
SELECT value
FROM table
FOR XML PATH('')
关于如何在没有添加额外标记的情况下获取XML编码值的任何想法,所以我可以在完成后将管道格式转换为XML(最好是一次性)?
编辑:因为人们在问,这是5个潜在的数据行可能是什么样的
foo
foo|bar
foo|bar|1
foo||
baz|
结果将是
Col1, Col2, Col3
foo,null,null
foo,bar,null
foo,bar,1
foo,null,null
baz,null,null
我通过在子查询中使用生成的XML类型来实现这一点,例如:(在任何给定的行中最多可以有4列pr 3个管道)
SELECT
*,
x.query('f[1]').value('.','nVarChar(2048)') Col1
,x.query('f[2]').value('.','nVarChar(2048)') Col2
,x.query('f[3]').value('.','nvarchar(2048)') Col3
,x.query('f[4]').value('.','nvarchar(2048)') Col4
FROM
(
SELECT *,
CAST('<f>' + REPLACE(Value,'|','</f><f>') + '</f>' AS XML) as x
FROM table
) y
@srutzky提出了一个很好的观点。不,我根本不需要在这里做XML。如果我能找到一个快速的&amp;在基于集合的操作中解析管道的干净方法,我会这样做。将查看SQL#文档...
答案 0 :(得分:1)
SELECT CAST('<values><f>' +
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(value,'&','&')
,'"','"')
,'<','<')
,'>','>')
,'|','</f><f>') + '</f></values>' AS XML)
FROM TABLE;
答案 1 :(得分:1)
您可以尝试以下方法但是您需要确保内容是“xml safe”,换句话说,内容不包含xml将拒绝的值(查看xml元素内容解析)。 尝试以下...它是测试脚本,看它是否符合您的要求..
UPDATE:
好吧,如果我一直读完这个问题可能会有所帮助... 2步......拆分管道然后xml所有拆分项......试试这个:
创建以下功能:
CREATE FUNCTION [dbo].[udf_SPLIT]
(
@s nvarchar(max),
@trimPieces bit,
@returnEmptyStrings bit,
@delimiter nvarchar(10)
)
RETURNS @t TABLE (val nvarchar(max))
AS
BEGIN
DECLARE @i int, @j int
SELECT @i = 0, @j = (LEN(@s) - LEN(REPLACE(@s,@delimiter,'')))
;WITH cte AS
(
SELECT i = @i + 1,
s = @s,
n = substring(@s, 0, charindex(@delimiter, @s)),
m = substring(@s, charindex(@delimiter, @s)+1, len(@s) - charindex(@delimiter, @s))
UNION ALL
SELECT i = cte.i + 1,
s = cte.m,
n = substring(cte.m, 0, charindex(@delimiter, cte.m)),
m = substring(cte.m, charindex(@delimiter, cte.m) + 1, len(cte.m)-charindex(@delimiter, cte.m))
FROM cte
WHERE i <= @j
)
INSERT INTO @t (val)
SELECT [pieces]
FROM (
SELECT CASE
WHEN @trimPieces = 1 THEN LTRIM(RTRIM(CASE WHEN i <= @j THEN n ELSE m END))
ELSE CASE WHEN i <= @j THEN n ELSE m END
END AS [pieces]
FROM cte
) t
WHERE (@returnEmptyStrings = 0 AND LEN(pieces) > 0)
OR (@returnEmptyStrings = 1)
OPTION (maxrecursion 0)
RETURN
END
接下来尝试以下测试...
DECLARE @str nvarchar(500) = 'test|<html>this</html>|boogie woogie| SDGDSFG| game<br /> on |working| this|'
SELECT REPLACE(
REPLACE(
REPLACE(
REPLACE([val],'&','&')
,'"','"')
,'<','<')
,'>','>')
AS [f]
FROM [dbo].[udf_SPLIT](@str,1,0,'|')
FOR XML PATH('')
如果不完全正确,希望能让你走上正确的道路......
HTH
戴夫
答案 2 :(得分:1)
您的想法绝对正常:通过从字符串中生成XML,XML引擎将正确转换所有特殊字符。拆分后,XML应该是正确的。
如果您的字符串存储在列中,您可以通过执行某种计算(类似'' + YourColumn
)来避免自动给定的名称,或者为列添加别名{{1 }}:
试试这样:
AS [*]