簡體   English   中英

SQL 從存儲為 nvarchar 的 XML 列查詢

[英]SQL query from XML Column stored as nvarchar

我需要 sql 查詢方面的幫助。 我有一個帶有列的表,其中 xml 存儲為 nvarchar。

Xml曲線
<?xml version="1.0" encoding="Windows-1252"?>

所有 XML 看起來像:

   <?xml version="1.0" encoding="Windows-1252"?>
<Curve xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Anchor>Begin</Anchor>
  <LoadOnlyNOKCurves>false</LoadOnlyNOKCurves>
  <Teachmode>false</Teachmode>
  <ActualCurve>
    <FloatPoints>0;4.965425|0.01004791;5.438642|0.01076508;5.50529|0.01112366;5.485298</FloatPoints>
  </ActualCurve>
  <AbsOffset>
    <X>88.21842</X>
    <Y>0</Y>
  </AbsOffset>
  <UpperLimit>
    <FloatPoints>9.456265E-05;5.023251|0.008893617;5.502031</FloatPoints>
  </UpperLimit>
  <LowerLimit>
    <FloatPoints>0.0008510638;4.906321|0.01408511;5.495711</FloatPoints>
  </LowerLimit>
  <ULViolationCurveIdx>-1</ULViolationCurveIdx>
  <ULViolationULIdx>-1</ULViolationULIdx>
  <LLViolationCurveIdx>-1</LLViolationCurveIdx>
  <LLViolationLLIdx>-1</LLViolationLLIdx>
  <SIO_X>
    <Id>1</Id>
    <Alias>Position</Alias>
    <Unit>mm</Unit>
  </SIO_X>
  <SIO_Y>
    <Id>2</Id>
    <Alias>Force</Alias>
    <Unit>kN</Unit>
  </SIO_Y>
</Curve>

And i need built SQL query, which select data in first tag FloatPoints: <FloatPoints>0;4.965425|0.01004791;5.438642|0.01076508;5.50529|0.01112366;5.485298</Floatpoint>

解釋:

<FloatPoints>x1;y1|x2;y2|x3;y3|x4;y4</FloatPoints>

因此,我想要這個結果:

x1 y1 x2 y2 x3 y3 x4 y4
0 4.965425 0.01004791 5.438642 0.01076508 5.50529 0.01112366 5.485298

如果可能的話。

這個答案有幾個假設:

  • XML 始終是有效的xml值。
  • 總是有 4 個 xy 坐標
  • x & y 值的長度不能超過 127 個字符。
  • 在節點ActualCurve中想要的值
  • 您正在使用支持TRANSLATE的版本(如果沒有,請使用嵌套的REPLACE s)

有了這個假設,您可以執行以下操作:

  1. nvarchar轉換為有效的xml
  2. 提取Curve/ActualCurve/FloatPoints的值
  3. 替換字符以創建一個值,該值可以使用PARSENAME將單獨的部分分隔為
  4. 使用CHARINDEX獲取字符串的正確左/右部分
  5. CONVERTfloat
DECLARE @XMLLikeString nvarchar(MAX) = '<?xml version="1.0" encoding="Windows-1252"?>
<Curve xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Anchor>Begin</Anchor>
  <LoadOnlyNOKCurves>false</LoadOnlyNOKCurves>
  <Teachmode>false</Teachmode>
  <ActualCurve>
    <FloatPoints>0;4.965425|0.01004791;5.438642|0.01076508;5.50529|0.01112366;5.485298</FloatPoints>
  </ActualCurve>
  <AbsOffset>
    <X>88.21842</X>
    <Y>0</Y>
  </AbsOffset>
  <UpperLimit>
    <FloatPoints>9.456265E-05;5.023251|0.008893617;5.502031</FloatPoints>
  </UpperLimit>
  <LowerLimit>
    <FloatPoints>0.0008510638;4.906321|0.01408511;5.495711</FloatPoints>
  </LowerLimit>
  <ULViolationCurveIdx>-1</ULViolationCurveIdx>
  <ULViolationULIdx>-1</ULViolationULIdx>
  <LLViolationCurveIdx>-1</LLViolationCurveIdx>
  <LLViolationLLIdx>-1</LLViolationLLIdx>
  <SIO_X>
    <Id>1</Id>
    <Alias>Position</Alias>
    <Unit>mm</Unit>
  </SIO_X>
  <SIO_Y>
    <Id>2</Id>
    <Alias>Force</Alias>
    <Unit>kN</Unit>
  </SIO_Y>
</Curve>';

SELECT CONVERT(float,LEFT(xy1,CHARINDEX(';',xy1)-1)) AS x1, 
       CONVERT(float,STUFF(xy1,1,CHARINDEX(';',xy1),'')) AS y1,
       CONVERT(float,LEFT(xy2,CHARINDEX(';',xy2)-1)) AS x2, 
       CONVERT(float,STUFF(xy2,1,CHARINDEX(';',xy2),'')) AS y2,
       CONVERT(float,LEFT(xy3,CHARINDEX(';',xy3)-1)) AS x3, 
       CONVERT(float,STUFF(xy3,1,CHARINDEX(';',xy3),'')) AS y3,
       CONVERT(float,LEFT(xy4,CHARINDEX(';',xy4)-1)) AS x4, 
       CONVERT(float,STUFF(xy4,1,CHARINDEX(';',xy4),'')) AS y4
FROM (VALUES(@XMLLikeString))V(XMLLikeString)
     CROSS APPLY (VALUES(TRY_CONVERT(xml,CONVERT(varchar(MAX),V.XMLLikeString))))TC(XML)
     CROSS APPLY (VALUES(TC.XML.value('(Curve/ActualCurve/FloatPoints/text())[1]','varchar(4000)')))AC(FloatPoints)
     CROSS APPLY (VALUES(TRANSLATE(AC.FloatPoints,'.|',',.')))T(FloatPoints)
     CROSS APPLY (VALUES(REPLACE(PARSENAME(T.FloatPoints,4),',','.'),REPLACE(PARSENAME(T.FloatPoints,3),',','.'),REPLACE(PARSENAME(T.FloatPoints,2),',','.'),REPLACE(PARSENAME(T.FloatPoints,1),',','.')))PN(xy1,xy2,xy3,xy4);

db<>小提琴

撇開編碼不談,問題是在解析 FloatPoints 標記時保留項目位置。 不幸的是, string_split不能保證保留項目位置,因此您可能需要一個自定義拆分器(此處為DelimitedSplit8K_LEAD ),它也返回項目 position。

select id,
   Max(case t2.itemnumber*100 + t3.itemnumber when 101 then cast(t3.Item as decimal(10,6)) end) x1,
   Max(case t2.itemnumber*100 + t3.itemnumber when 102 then cast(t3.Item as decimal(10,6)) end) y1,
   Max(case t2.itemnumber*100 + t3.itemnumber when 201 then cast(t3.Item as decimal(10,6)) end) x2,
   Max(case t2.itemnumber*100 + t3.itemnumber when 202 then cast(t3.Item as decimal(10,6)) end) y2
...
from (select id, cast(txn_message as xml) x
      from tbl) a
cross apply a.x.nodes('Curve/ActualCurve/FloatPoints') t(n)
cross apply DelimitedSplit8K_LEAD(t.n.value('.[1]', 'varchar(200)') , '|') t2
cross apply DelimitedSplit8K_LEAD(t2.Item, ';') t3
group by id;

db<>小提琴

包括DelimitedSplit8K_LEAD

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM