SQL Query用于选择两个已知字符串之间的值

时间:2018-01-15 20:13:28

标签: sql sql-server

我需要一个SQL查询来获取text列中两个已知字符串之间的值。 列名称为 d_info ,表格名称为详细信息

文本XML片段,但存储为text值。 我需要的是获取书挡<nettoeinkommen></nettoeinkommen>之间的值,在此示例中为718。 我还需要将输出保存在名为income的新列中,数据类型为float(8)

land>DE</land></wohnanschrift><taetigkeit>rentner</taetigkeit><dkbkundenstatus><bestandskunde>false</bestandskunde></dkbkundenstatus><haushaltsangaben><einnahmen><einkommen><nettoeinkommen>718</nettoeinkommen></einkommen><kindergeld>0</kindergeld><vermietungverpachtungnetto>0</vermietungverpachtungnetto><elterngeld>0</elterngeld><rentenunbefristet>0</rentenunbefristet><unselbststaendigetaetigkeit>740</unselbststaendigetaetigkeit><geringfuegigebeschaeftigung>0</geringfuegigebeschaeftigung></einnahmen><ausgaben><warmmiete>550</warmmiete><ratenimmobilienfinanzierung>0</ratenimmobilienfinanzierung>

我试过这段代码:

SELECT cast(SUBSTRING(d_info, CHARINDEX('<nettoeinkommen>', d_info) , CHARINDEX('</nettoeinkommen>', d_info) - CHARINDEX('<nettoeinkommen>', d_info)) as float(8)) as income from dbo.Details

但它正在返回Error converting data type varchar to real.

当我删除cast函数时,脚本可以正常工作,但它返回的是<nettoeinkommen>718而不是718

感谢。

3 个答案:

答案 0 :(得分:2)

它从标签的开头而不是它的结尾开始。

 SELECT cast(
   SUBSTRING(
     d_info, 
     CHARINDEX('<nettoeinkommen>', d_info) + len('<nettoeinkommen>'),
     CHARINDEX('</nettoeinkommen>', d_info) - (CHARINDEX('<nettoeinkommen>', d_info) + len('<nettoeinkommen>'))
   ) as float(8)) as income
 from dbo.Details

你甚至可能在变量中定义了这些:

 SELECT cast(
   SUBSTRING(
     d_info, 
     CHARINDEX(@startTag, d_info) + len(@startTag),
     CHARINDEX(@endTag, d_info) - (CHARINDEX(@startTag,d_info)+ len(@startTag))
   ) as float(8)) as income
 from dbo.Details

我认为使用变量更容易理解代码。

答案 1 :(得分:1)

您需要从起始索引添加开始标记的长度,并从子字符串语句的长度中减去:

SUBSTRING(d_info, CHARINDEX('<nettoeinkommen>', d_info)+16,  
CHARINDEX('</nettoeinkommen>', d_info) - CHARINDEX('<nettoeinkommen>', d_info)-16)

答案 2 :(得分:1)

看起来,你正在查询普通的xml数据,为此目的,sql-server提供了xquery功能:

SELECT CAST(r.d_info AS XML).value('(/haushaltsangaben/einnahmen/einkommen/nettoeinkommen)[1]', 'decimal(19,2)')
FROM
(
    SELECT '<taetigkeit>rentner</taetigkeit>
<dkbkundenstatus>
    <bestandskunde>false</bestandskunde>
</dkbkundenstatus>
<haushaltsangaben>
    <einnahmen>
        <einkommen>
            <nettoeinkommen>718</nettoeinkommen>
        </einkommen>
    </einnahmen>
</haushaltsangaben>' AS d_info
) AS r

如果您打算从源查询更多信息,最终会得到一堆堆叠子字符串,patindex函数甚至您自己定义的函数。这应该更具可读性和可持续性。

使用XQuery:https://docs.microsoft.com/en-us/sql/t-sql/xml/query-method-xml-data-type

关于您的初始问题SQL中的SUBSTRING函数返回从给定索引开始的特定长度的字符串的子集。例如SELECT SUBSTRING('whatever',5,4)返回&#39;永远&#39;。 在CHARINDEX的情况下,它给出了字符串中给定模式的第一个匹配的索引。示例SELECT CHARINDEX('ever','whatever')应返回5,因为&#39;永远&#39;无论是什么&#39;都从第五个位置开始。

现在,在您的情况下,您需要将'<nettoeinkommen>'的长度添加到起始charindex并从子字符串的长度中减去'</nettoeinkommen>'的长度:

如果需要精确计算,还可以考虑使用十进制或数字类型而不是浮点数:https://technet.microsoft.com/en-us/library/ms187912(v=sql.105).aspx