【问题标题】:Replace string without fixed length替换没有固定长度的字符串
【发布时间】:2021-03-03 04:17:45
【问题描述】:

我正在查看一些数据,这些数据的文本格式存储在 NTEXT 字段中。 使用 SQL 替换来删除已知长度和格式的数据已经很满意了,但是有些字段看起来像颜色格式,我正在尝试找到一种方法来删除这些。

以下数据示例,但是(如果可能)我希望能够删除数据中颜色后面的任何数字,但看不到如何将通配符引入 替换 声明。 根据 Excel,'\red***\green\***\blue***' 之类的东西,但这在 Sql Server 中不起作用。

declare @str varchar(1500) = '\red3\green73\blue125;Jimmy Jazz\red31\green73\blue125;'
select @str,
replace(@str,'\red31\green73\blue125;','')

任何指点将不胜感激,在此先感谢。

【问题讨论】:

  • ntext 已过时,将从 SQL Server 中删除。我建议您修复数据库以使用nvarchar(max)
  • 没错,但是它是第三方学校系统,并且计划在下次更新时进行更改。

标签: sql sql-server


【解决方案1】:

根据您的示例数据,您似乎只需要删除字符串中的数字即可使用patreplace8k 或使用patextract8K。请注意以下示例数据和示例:

-- Sample data
DECLARE @strings TABLE(stringId INT IDENTITY, string VARCHAR(100));
INSERT @strings VALUES('DeepPurple1978\yellow2\red009;pink\black3322'),
('red202\yellow5\red009;hotpink2'),('purple999\gray65\violet;blue\yellow381');

--==== Solution #1 Patreplace8k
SELECT
  s.stringId,
  pr.newString
FROM        @strings AS s
CROSS APPLY samd.patReplace8K(s.string,'[0-9]','') AS pr;

--==== Solution #2 PatExtract8k + STRING_AGG (SQL 2017+)
SELECT
  s.stringId,
  NewString = STRING_AGG(pe.Item,'') WITHIN GROUP (ORDER BY pe.ItemNumber)
FROM        @strings AS s
CROSS APPLY samd.patExtract8K(s.string,'[0-9]') AS pe
GROUP BY    s.stringId;

--==== Solution #3 PatExtract8k + XML Concatination (Pre SQL 2017\)
SELECT 
  s.stringId,
  NewString = 
(
  SELECT      pe.item+''
  FROM        @strings AS s2
  CROSS APPLY samd.patExtract8K(s2.string,'[0-9]') AS pe
  WHERE       s.stringId = s2.stringid
  ORDER BY    pe.itemNumber
  FOR XML PATH('')
) 
FROM        @strings AS s
GROUP BY    s.stringId;

这些解决方案中的每一个都返回:

stringId    NewString
----------- -------------------------------------
1           DeepPurple\yellow\red;pink\black
2           red\yellow\red;hotpink
3           purple\gray\violet;blue\yellow

第二个和第三个利用串联,第二个与 SQL Server 2017+ 兼容,第三个适用于早期版本(您没有包括您使用的版本。)

要仅去除一种或多种预定义颜色后面的数字,您可以使用patternsplitCM。请注意使用带有您正在寻找的一组颜色的表格;在现实世界中,我会使用真实的桌子。

-- Colors
DECLARE @colors TABLE(color VARCHAR(20) PRIMARY KEY);
INSERT  @colors VALUES('red'),('green'),('blue'),('yellow'),('purple'),('grey');

-- Sample data
DECLARE @strings TABLE(stringId INT IDENTITY, string VARCHAR(100));
INSERT @strings VALUES('Burger1978\yellow2\red009;pink\86thisfool'),
('red202\yellow5\red009;Freddy99'),('green999\grey65\violet;blue\yellow381');


SELECT 
  s.stringId, s.string, NewString = 
(
  SELECT
  (
    SELECT SUBSTRING(f.Item, IIF(f.M=0 AND EXISTS (SELECT c.Color FROM @colors AS c
                   WHERE c.Color = f.L),NULLIF(PATINDEX('%[^0-9]',f.item),0),1),8000)
    FROM
    (
      SELECT ps.ItemNumber, ps.Item, ps.[Matched],
             LAG(ps.Item,1,ps.Item) OVER (ORDER BY ps.ItemNumber)
      FROM   dbo.PatternSplitCM(s.string,'[^0-9\ ;]') AS ps
    ) AS f(ItemNumber,Item,M,L)
    ORDER BY f.ItemNumber
    FOR XML PATH(''), TYPE
  ).value('(text())[1]','varchar(8000)')
)
FROM @strings AS s;

返回:

stringId    string                                        NewString
----------- --------------------------------------------- ----------------------------------------
1           Burger1978\yellow2\red009;pink\86thisfool     Burger1978\yellow\red;pink\86thisfool
2           red202\yellow5\red009;Freddy99                red\yellow\red;Freddy99
3           green999\grey65\violet;blue\yellow381         green\grey\violet;blue\yellow

【讨论】:

  • 谢谢艾伦,这看起来很有用。我真正想做的是替换颜色和数字,但由于颜色值范围从 1 到 255,我需要 1,2 或 3 个通配符。不过,我会试试你的解决方案 - 可能只需要删除数字,然后是颜色?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多