【问题标题】:USE RIGHT with CHARINDEX using string with multiple characters fails使用具有多个字符的字符串的 CHARINDEX 使用 RIGHT 失败
【发布时间】:2018-03-15 00:33:53
【问题描述】:

我有一个文本文件,我需要从左边获取字符串的一部分。

select top 100 Description, right(Description, 
charindex('</span>', reverse(Description))-1) 
as CleanedDesc 
from MyDB.dbo.MyTable_output

如果出现以下错误,则执行查询时:

传递给 RIGHT 函数的长度参数无效。

这实际上是正确的,因为我指定了charindex('&lt;/span&gt;'

这是不对的,它必须是单个字符,但不幸的是,文本值“分隔符恰好是. .

以下是可用于测试的字符串数据示例:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  <html>  <head>  <title></title>  </head>  <body>  <span class="added">Added: <input type="hidden" name="dnf_class_values[procurement_notice][description][0][added_on]" value="2017-06-19 10:32:17">Jun 19, 2017 10:32 am</span> This solicitation will contain NSN 1d2323, OIL. A Request for Proposal (RFP) will be issued for award .....ed item and must be acquired from an approved manufacturer. The approved sources are:<br>  SEYER INDUSTRIES, INC. 19494 P/N 74A150625-1006<br>

【问题讨论】:

  • 它失败了,因为您正在寻找 /span 标签,但您正在反转描述字符串。您不会在反向字符串中找到它。你为什么要反转字符串?您的预期输出是什么?

标签: sql-server string replace right-to-left charindex


【解决方案1】:

我找到了解决方法。那就是用我确定在描述列中不存在的字符替换使用 CTE 的 ''。我用这段代码扫描了我的桌子

 select * from  MyDB.dbo.MyTable_output where Description like '%~%'. 

但我确实有一些记录确实具有此值“~”。所以这不是一个选择。

但即使我找不到任何从长远来看似乎不是切实可行的解决方案

;with cte as (
select top 100 RowNo, replace(Description, '</span>','~') as ReplacedDesc from InputTemp.dbo.SearchFBO_output 
) 
select 
RowNo = ROW_NUMBER() OVER (ORDER BY EntityPKID),
Project,
[Title],

RIGHT(cte.ReplacedDesc, charindex('~', reverse(cte.ReplacedDesc))-1) as Description,

FROM
 MyDB.dbo.MyTable_output o
INNER JOIN cte ON cte.RowNo = o.RowNo

【讨论】:

    【解决方案2】:

    不是 100% 确定这是否是您要查找的内容,但您可以使用分隔符。

    如果对表值函数开放,请考虑以下事项:

    厌倦了提取数据...left,right,charindex,reverse,...我修改了一个解析函数来接受两个不相似的分隔符(最多100个字符而不是一个)。

    示例or dbFiddle

    Declare @YourTable table ([ID] int,[Description] varchar(max))
    Insert Into @YourTable values 
    (1,'<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  <html>  <head>  <title></title>  </head>  <body>  <span class="added">Added: <input type="hidden" name="dnf_class_values[procurement_notice][description][0][added_on]" value="2017-06-19 10:32:17">Jun 19, 2017 10:32 am</span> This solicitation will contain NSN 1d2323, OIL. A Request for Proposal (RFP) will be issued for award .....ed item and must be acquired from an approved manufacturer. The approved sources are:<br>  SEYER INDUSTRIES, INC. 19494 P/N 74A150625-1006<br>')
    
    
    Select A.ID
          ,B.*
     From  @YourTable A
     Cross Apply [dbo].[tvf-Str-Extract]([Description],'>','</span') B
     Where RetVal>''
    

    退货

    ID  RetSeq  RetPos  RetVal
    1   1       262     Jun 19, 2017 10:32 am
    

    现在,如果分隔符是 >,将返回以下内容

    ID  RetSeq  RetPos  RetVal
    1   7   136 Added: 
    1   8   262 Jun 19, 2017 10:32 am
    1   9   290  This solicitation will contain NSN 1d2323, OIL. A Request for Proposal (RFP) will be issued for award .....ed item and must be acquired from an approved manufacturer. The approved sources are:
    1   10  487   SEYER INDUSTRIES, INC. 19494 P/N 74A150625-1006
    

    有兴趣的 UDF

    CREATE FUNCTION [dbo].[tvf-Str-Extract] (@String varchar(max),@Delimiter1 varchar(100),@Delimiter2 varchar(100))
    Returns Table 
    As
    Return (  
    
    with   cte1(N)   As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
           cte2(N)   As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 N1,cte1 N2,cte1 N3,cte1 N4,cte1 N5,cte1 N6) A ),
           cte3(N)   As (Select 1 Union All Select t.N+DataLength(@Delimiter1) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter1)) = @Delimiter1),
           cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter1,@String,s.N),0)-S.N,8000) From cte3 S)
    
    Select RetSeq = Row_Number() over (Order By N)
          ,RetPos = N
          ,RetVal = left(RetVal,charindex(@Delimiter2,RetVal)-1) 
     From  (
            Select *,RetVal = Substring(@String, N, L) 
             From  cte4
           ) A
     Where charindex(@Delimiter2,RetVal)>1 
    
    )
    /*
    Max Length of String 1MM characters
    
    Declare @String varchar(max) = 'Dear [[FirstName]] [[LastName]], ...'
    Select * From [dbo].[tvf-Str-Extract] (@String,'[[',']]')
    */
    

    编辑 - 关于评论

    您可能会注意到我添加了一个愚蠢的结尾分隔符 |||

    Select A.ID
          ,B.*
     From  @YourTable A
     Cross Apply [dbo].[tvf-Str-Extract]([Description]+'|||','</span>','|||') B
     Where RetVal>''
    

    【讨论】:

    • 嗨,约翰,我只需要返回,只需返回我所谓的分隔符“”之后的所有内容
    • @enigma6205 这种方法对于您的要求可能有点过头了。把它放在你的后兜里,也许有一天它会有所帮助
    猜你喜欢
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多