【问题标题】:How to replace all numbers of exactly 8 characters in length eg 12345678如何替换长度正好为 8 个字符的所有数字,例如 12345678
【发布时间】:2015-03-17 19:16:30
【问题描述】:

我已经做了很多搜索,所以不要责备我。

我有一列包含显示节目名称的字符串值。

例如:

[Titles]
World Cup 2014
Family Guy
UFC Fight Night
9pm News and Weather
2014 Media Awards
Homeland 25242324
Simpsons 25242314
Shameless
Soccer Night 45342324 International
Rugby Live 45342324 HTML5

我希望使用 select 语句去除数字长度正好为 8 个字符的数字。

我只有读取权限,因此无法创建函数,而且我使用的是 SQL Server 2005。

【问题讨论】:

  • 只是为了确保您尝试在数据库本身上使用 SQL 来执行此操作?您可以考虑在客户端使用正则表达式来去除不需要的字符串部分。
  • 你试过什么?顺便说一句,在您发布的示例中,没有数字序列为 8 的值。最长的是 7。;)
  • 如果你把它保存在 SQL 中,你最终会创建一个标量函数,它会逐个字符地解析字符串。
  • 我更新了答案。
  • 抱歉,我现在已经修改了示例以包含 8 位数字,呵呵。 :)

标签: sql sql-server sql-server-2005 replace numbers


【解决方案1】:
create table #tmp(myString varchar(255))
insert into #tmp
values('Soccer Night 45342327 International'),('9pm News and Weather')



    Select newstring = case when  patindex('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%',mystring) > 0 then
        left(mystring, patindex('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%',mystring) - 1) 
        + substring(mystring,patindex('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%',mystring) + 8,9999)
        else mystring end
        from #tmp
    drop table #tmp

【讨论】:

  • 这工作正常,直到有 2 组数字需要删除。
  • 我不能以我的菜鸟的身份投票,但这看起来不错,所以给小伙子点赞吧;)。我的数据集不包含有两组数字的实例。
【解决方案2】:

互联网上有许多拆分功能。我个人的偏好是由 Jeff Moden 创建并在过去几年中由社区增强的。你可以在这里找到他的文章,http://www.sqlservercentral.com/articles/Tally+Table/72993/。确保您查看 cmets ......在此发布时有几百个。这是该拆分器的代码。

CREATE FUNCTION [dbo].[DelimitedSplit8K]
--===== Define I/O parameters
        (@pString VARCHAR(8000), @pDelimiter CHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN
--===== "Inline" CTE Driven "Tally Table" produces values from 0 up to 10,000...
     -- enough to cover VARCHAR(8000)
  WITH E1(N) AS (
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
                ),                          --10E+1 or 10 rows
       E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
       E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
 cteTally(N) AS (--==== This provides the "zero base" and limits the number of rows right up front
                     -- for both a performance gain and prevention of accidental "overruns"
                 SELECT 0 UNION ALL
                 SELECT TOP (DATALENGTH(ISNULL(@pString,1))) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
                ),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
                 SELECT t.N+1
                   FROM cteTally t
                  WHERE (SUBSTRING(@pString,t.N,1) = @pDelimiter OR t.N = 0) 
                )
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
 SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY s.N1),
        Item       = SUBSTRING(@pString,s.N1,ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000))
   FROM cteStart s
;

无论您使用哪种拆分器(只要它是表值函数),它都可以像这样工作。

if OBJECT_ID('tempdb..#Something') is not null
    drop table #Something;

create table #Something
(
    SomeValue varchar(100)
);

insert #Something
select 'World Cup 2014' union all
select 'Family Guy' union all
select 'UFC Fight Night' union all
select '9pm News and Weather' union all
select '2014 Media Awards' union all
select 'Homeland 2524232' union all
select 'Simpsons 2524231' union all
select 'Shameless' union all
select 'Soccer Night 4534232 International' union all
select 'Rugby Live 4534232 HTML5';

with ParsedData as
(
    select * 
    from #Something s
    cross apply dbo.DelimitedSplit8K(s.SomeValue, ' ')
    where Item not like '[0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
)

select distinct
    Stuff((SELECT ' ' + Item
              FROM ParsedData p2
              WHERE  p1.SomeValue = p2.SomeValue
              ORDER  BY p1.ItemNumber --The split function keeps track of the order for us already
              FOR XML PATH('')), 1, 1, ' ') as Details
from ParsedData p1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多