解析字符串SQL

解析字符串SQL,sql,sql-server,tsql,Sql,Sql Server,Tsql,我在MSSQL中有一个很长的字符串,我需要I值 我代表发票, A代表金额, D代表日期 I=940;A=29.5;D=20090901 | I=941;A=62.54;D=20090910 | I=942;A=58.99;D=20091005 | I=954;A=93.45;D=20091201 | I=944;A=96.76;D=20091101 | I=946;A=52.5;D=20091101 | I=943;A=28.32;D=20091101 | I=945;A=52.5;D=2009

我在MSSQL中有一个很长的字符串,我需要I值

我代表发票, A代表金额, D代表日期

I=940;A=29.5;D=20090901 | I=941;A=62.54;D=20090910 | I=942;A=58.99;D=20091005 | I=954;A=93.45;D=20091201 | I=944;A=96.76;D=20091101 | I=946;A=52.5;D=20091101 | I=943;A=28.32;D=20091101 | I=945;A=52.5;D=20091101 | I=955;A=79.81;D=20091201 | I=950;A=25.2;D=20091124 | I=948;A=31.86;D=20091110 | I=949;A=28.32;D=20091120 | I=947;A=25.2;D=20091109 | I=951;A=242.54;D=20091124 | I=952;A=28.32;D=20091129 | I=956;A=38.94;D=20091210 | I=957;A=107.39;D=20091215 | I=958;A=32.55;D=20091228 | I=959;A=27.3;D=20091228 | I=960;A=24.79;D=20091230 | I=1117;A=28.32;D=20100131 | I=1115;A=272.58;D=20100131 | I=1116;A=159.6;D=20100209

这是最可怕的案例之一


每一个都是发票编号,具有相关值,我将使用这些值链接到另一个交易。如果有人能在不制作应用程序的情况下尽可能地向我解释这一过程的最佳方式,我将不胜感激。我不知道这是否会对您有所帮助,但这里有一个与sql server兼容的字符串解析器函数。。。 可以这样称呼:

Select * From dbo.ParseTextString([Your long text string here],  '|') 
功能是:

Create FUNCTION [dbo].[ParseTextString] (@S Text, @delim VarChar(5))
Returns @tOut Table 
(ValNum Integer Identity Primary Key, 
 sVal VarChar(8000))
As
Begin 
Declare @dLLen TinyInt      -- Length of delimiter
Declare @sWin  VarChar(8000)-- Will Contain Window into text string
Declare @wLen  Integer      -- Length of Window
Declare @wLast TinyInt      -- Boolean to indicate processing Last Window
Declare @wPos  Integer      -- Start Position of Window within Text String
Declare @sVal  VarChar(8000)-- String Data to insert into output Table
Declare @BtchSiz Integer    -- Maximum Size of Window
Set @BtchSiz = 7900     -- (Reset to smaller values to test routine)
Declare @dPos Integer       -- Position within Window of next Delimiter
Declare @Strt Integer       -- Start Position of each data value within Window
-- -------------------------------------------------------------------------

-- ---------------------------
If @delim is Null Set @delim = '|'
If DataLength(@S) = 0 Or
    Substring(@S, 1, @BtchSiz) = @delim Return
-- ---------------------------
Select @dLLen = Len(@delim),
    @Strt = 1, @wPos = 1,
    @sWin = Substring(@S, 1, @BtchSiz)
Select @wLen = Len(@sWin),
      @wLast = Case When Len(@sWin) = @BtchSiz
                Then 0 Else 1 End,
      @dPos = CharIndex(@delim, @sWin, @Strt)
-- ----------------------------
While @Strt <= @wLen
    Begin
    If @dPos = 0 Begin    -- No More delimiters in window
        If @wLast = 1 Set @dPos = @wLen + 1 
        Else Begin
        Set @wPos = @wPos + @Strt - 1
        Set @sWin = Substring(@S, @wPos, @BtchSiz)
        -- ----------------------------------------
        Select @wLen = Len(@sWin), @Strt = 1,
               @wLast = Case When Len(@sWin) = @BtchSiz
                    Then 0 Else 1 End,
               @dPos = CharIndex(@delim, @sWin, 1)
                If @dPos = 0 Set @dPos = @wLen + 1 
             End
         End
         -- -------------------------------
         Set @sVal = LTrim(Substring(@sWin, @Strt, @dPos - @Strt))
         Insert @tOut (sVal) Values (@sVal)
         -- -------------------------------
         -- Move @Strt to char after last delimiter
         Set @Strt = @dPos + @dLLen 
         Set @dPos = CharIndex(@delim, @sWin, @Strt)
    End
  Return
  End
创建函数[dbo].[ParseTextString](@S Text,@delim VarChar(5))
返回@tOut表
(ValNum整数标识主键,
sVal VarChar(8000))
作为
开始
Declare@dLLen TinyInt—分隔符的长度
声明@swinvarchar(8000)--将窗口包含为文本字符串
声明@wLen整数——窗口的长度
声明@wLast TinyInt——布尔值以指示处理最后一个窗口
Declare@wPos Integer——文本字符串中窗口的起始位置
Declare@sVal VarChar(8000)——要插入到输出表中的字符串数据
声明@BtchSiz Integer——窗口的最大大小
设置@BtchSiz=7900--(重置为较小值以测试例程)
Declare@dPos Integer——下一个分隔符窗口内的位置
Declare@Strt Integer——窗口中每个数据值的起始位置
-- -------------------------------------------------------------------------
-- ---------------------------
如果@delim为空,则设置@delim='|'
如果数据长度(@S)=0或
子字符串(@S,1,@BtchSiz)=@delim Return
-- ---------------------------
选择@dLLen=Len(@delim),
@Strt=1,@wPos=1,
@swn=子字符串(@S,1,@BtchSiz)
选择@wLen=Len(@sWin),
@wLast=Len(@sWin)=@BtchSiz时的情况
然后0或1结束,
@dPos=CharIndex(@delim、@sWin、@Strt)
-- ----------------------------

虽然@Strt我使用SQL中的函数分割字符串,但这可能是您的出发点:

CREATE Function [dbo].[CsvToVarchar] ( @Array varchar(4000)) 
returns @IntTable table 
    (CharsValue VARCHAR(40))
AS
begin

    declare @separator varchar(5)
    set @separator = ','

    declare @separator_position int 
    declare @array_value varchar(4000) 

    set @array = @array + @separator

    while patindex('%'+@separator+'%' , @array) <> 0 
    begin

      select @separator_position =  patindex('%'+@separator+'%' , @array)
      select @array_value = left(@array, @separator_position - 1)

        Insert @IntTable
        Values (@array_value)

      select @array = stuff(@array, 1, @separator_position, '')
    end

    return
end
创建函数[dbo].[CsvToVarchar](@Array varchar(4000))
返回@IntTable表
(CharsValue VARCHAR(40))
作为
开始
声明@separator varchar(5)
设置@separator=','
声明@separator\u位置int
声明@array_value varchar(4000)
设置@array=@array+@分隔符
而patindex('%'+@separator+'%',@array)0
开始
选择@separator_position=patindex('%'+@separator+'%',@array)
选择@array\u value=left(@array,@separator\u位置-1)
插入@IntTable
值(@array_值)
选择@array=stuff(@array,1,@separator\u position,“”)
结束
返回
结束
对于SQL Server 2005,您需要使用日期时间而不是日期

select N.value('substring(value[1],3)', 'int') as Invoice,
       N.value('substring(value[2],3)', 'money') as Amount,
       N.value('substring(value[3],3)', 'datetime') as [Date]
from @xml.nodes('item') as T(N)
要阅读表格,你需要这样做

declare @s varchar(max) = 'I=940;A=29.5;D=20090901|I=941;A=62.54;D=20090910|I=942;A=58.99;D=20091005|I=954;A=93.45;D=20091201|I=944;A=96.76;D=20091101|I=946;A=52.5;D=20091101|I=943;A=28.32;D=20091101|I=945;A=52.5;D=20091101|I=955;A=79.81;D=20091201|I=950;A=25.2;D=20091124|I=948;A=31.86;D=20091110|I=949;A=28.32;D=20091120|I=947;A=25.2;D=20091109|I=951;A=242.54;D=20091124|I=952;A=28.32;D=20091129|I=956;A=38.94;D=20091210|I=957;A=107.39;D=20091215|I=958;A=32.55;D=20091228|I=959;A=27.3;D=20091228|I=960;A=24.79;D=20091230|I=1117;A=28.32;D=20100131|I=1115;A=272.58;D=20100131|I=1116;A=159.6;D=20100209'

declare @YourTable table(ID int, s varchar(max))
insert into @YourTable values
(1, @s),
(2, @s)

select Y.ID,
       T.N.value('substring(value[1],3)', 'int') as Invoice,
       T.N.value('substring(value[2],3)', 'money') as Amount,
       T.N.value('substring(value[3],3)', 'date') as [Date]
from @YourTable as Y
  cross apply (select cast('<item><value>'+replace(replace(Y.s, ';','</value><value>'), '|','</value></item><item><value>')+'</value></item>' as xml)) as X(XMLCol)
  cross apply X.XMLCol.nodes('item') as T(N)
声明@s varchar(max)='I=940;A=29.5;D=20090901 | I=941;A=62.54;D=20090910 | I=942;A=58.99;D=20091005 | I=954;A=93.45;D=20091201 | I=944;A=96.76;D=20091101 | I=946;A=52.5;D=20091101 | I=943;A=28.32;D=20091101 | I=945;A=52.5;D=20091101 | I=955;A=79.81;D=20091201 | I=950;A=25.2;D=20091124 | I=948;A=31.86;D=20091110 | I=949;A=28.32;D=20091120 | I=947;A=25.2;D=20091109 | I=951;A=242.54;D=20091124 | I=952;A=28.32;D=20091129 | I=956;A=38.94;D=20091210 | I=957;A=107.39;D=20091215 | I=958;A=32.55;D=20091228 | I=959;A=27.3;D=20091228 | I=960;A=24.79;D=20091230 | I=1117;A=28.32;D=20100131 | I=1115;A=272.58;D=20100131 | I=1116;A=159.6;D=20100209'
声明@YourTable表(ID int,s varchar(max))
在@YourTable值中插入
(1,@s),
(2,@s)
选择Y.ID,
T.N.value(‘子字符串(值[1],3)’,‘int’)作为发票,
T.N.value(“子字符串(值[2],3)”,“货币”)作为金额,
T.N.value(‘子字符串(值[3],3)’‘日期’)作为[日期]
从@YourTable作为Y
交叉应用(选择cast(“”+replace(替换(Y.s,“;”,“”),“|,”)+xml)作为X(XMLCol)
交叉应用X.XMLCol.nodes('item')作为T(N)

如果可能的话,在应用程序中对此进行解析,并将数据传递给SQL。我不太清楚您在问什么。这个字符串是变量中的一个值,并且您希望从中提取某些值吗?对于给定的示例输入,您能给出一个您希望生成的示例吗?如前所述,这是mssql中的一个字段,由sage pastel evolution生成,与支付有关,我再次需要每个i值,我希望这会澄清问题。您想要的是明确的,为什么要采用困难的方式并使用SQL,不是。我不知道你在做什么项目,但让我说我很高兴我没有在做:D!Thx只需将其链接到字段,然后dbo.PostAP.cAllocs,它就可以正常工作了?@Enzero–不知道。什么是dbo.PostAP.cAllocs?是否要将输出保存在那里?@Enzero–添加了一个从表中读取的版本。只需将
@YourTable
替换为
dbo.PostAP.cAllocs
,并添加所需的列,也许还有一个where子句。我做了以下“declare@s varchar(max)=(Select cAllocs from dbo.PostAP where AutoIdx=@index)”以及“insert into@YourTable values(1,@s),(2,@s)的作用是什么“@Enzero这是我用来创建一个样本表来测试的。您应该只使用查询。无需将数据提取到变量。
select N.value('substring(value[1],3)', 'int') as Invoice,
       N.value('substring(value[2],3)', 'money') as Amount,
       N.value('substring(value[3],3)', 'datetime') as [Date]
from @xml.nodes('item') as T(N)
declare @s varchar(max) = 'I=940;A=29.5;D=20090901|I=941;A=62.54;D=20090910|I=942;A=58.99;D=20091005|I=954;A=93.45;D=20091201|I=944;A=96.76;D=20091101|I=946;A=52.5;D=20091101|I=943;A=28.32;D=20091101|I=945;A=52.5;D=20091101|I=955;A=79.81;D=20091201|I=950;A=25.2;D=20091124|I=948;A=31.86;D=20091110|I=949;A=28.32;D=20091120|I=947;A=25.2;D=20091109|I=951;A=242.54;D=20091124|I=952;A=28.32;D=20091129|I=956;A=38.94;D=20091210|I=957;A=107.39;D=20091215|I=958;A=32.55;D=20091228|I=959;A=27.3;D=20091228|I=960;A=24.79;D=20091230|I=1117;A=28.32;D=20100131|I=1115;A=272.58;D=20100131|I=1116;A=159.6;D=20100209'

declare @YourTable table(ID int, s varchar(max))
insert into @YourTable values
(1, @s),
(2, @s)

select Y.ID,
       T.N.value('substring(value[1],3)', 'int') as Invoice,
       T.N.value('substring(value[2],3)', 'money') as Amount,
       T.N.value('substring(value[3],3)', 'date') as [Date]
from @YourTable as Y
  cross apply (select cast('<item><value>'+replace(replace(Y.s, ';','</value><value>'), '|','</value></item><item><value>')+'</value></item>' as xml)) as X(XMLCol)
  cross apply X.XMLCol.nodes('item') as T(N)