【问题标题】:Replacing more than 1 period to 1 period in sql在sql中将超过1个句点替换为1个句点
【发布时间】:2020-08-14 17:57:53
【问题描述】:

我有以下代码可以将表格列中的多个句点转换为一个句点。

alter proc replace_characters_1
@COLUMN_NAME varchar(30),
@TABLE_NAME varchar(30)
as 
    declare @SQL varchar(MAX)
    while @COLUMN_NAME like '%..%'
    begin
    set @SQL= 'update [' +@TABLE_NAME+ '] set [' +@COLUMN_NAME+ '] = replace([' +@COLUMN_NAME+ '],''..'',''.'')';
    exec(@SQL)
end

我想一口气将Anna...Amal 更改为Anna.Amal,但循环不起作用。我该怎么办?`

【问题讨论】:

  • 请提供样本数据和期望的结果。
  • 您想用一个点替换未知数量的点吗?
  • 您的 while 条件是检查 COLUMN_NAME 是否存在“..”,而不是具有该列名的表的实际内容。
  • 我在存储过程的执行语句中给出了COLUMN_NAME。
  • 是的,我想将多个点替换为一个

标签: sql sql-server replace


【解决方案1】:

一种可能的方法是使用嵌套的REPLACE()s:

SET ColumnName = REPLACE(REPLACE(REPLACE(ColumnName, '.', '<>'), '><', ''), '<>', '.')

在第一个 REPLACE() 之后,文本中包含句点 (.) 的部分看起来像 &lt;&gt;&lt;&gt;&lt;&gt;。在第二个REPLACE() 之后,结果只有&lt;&gt;,最后一个REPLACE() 返回单个句点(.)。如果输入文本中存在&lt;&gt;这两个字符,您可以选择另一对字符。

表:

CREATE TABLE Data (Name varchar(100))
INSERT INTO Data (Name)
VALUES
   ('ANNA..Amal'),
   ('ANNA..Amal.'),
   ('ANNA.Amal.'),
   ('ANNA...........Amal.'),
   ('ANNA.....Amal')

程序:

CREATE PROC replace_characters_1
   @COLUMN_NAME sysname,
   @TABLE_NAME sysname
AS
BEGIN
    DECLARE @SQL nvarchar(MAX)
    DECLARE @RC int

    SET @SQL = 
       N'UPDATE ' + QUOTENAME(@TABLE_NAME) + N' ' +
       N'SET ' + QUOTENAME(@COLUMN_NAME) + N' = ' + 
            N'REPLACE(REPLACE(REPLACE(' + QUOTENAME(@COLUMN_NAME) + ', ''.'', ''<>''), ''><'', ''''), ''<>'', ''.'') ' +
       N'WHERE ' + QUOTENAME(@COLUMN_NAME) + N' LIKE ''%..%'''

    EXEC @RC = sp_executesql @SQL
    RETURN @RC
END 

结果:

EXEC replace_characters_1 N'Name', N'Data'
SELECT * FROM Data

Name
ANNA.Amal
ANNA.Amal.
ANNA.Amal.
ANNA.Amal.
ANNA.Amal

【讨论】:

  • 我在使用 时遇到过碰撞,这就是为什么我选择了一个极其罕见的‡†组合
【解决方案2】:

我正在使用 CHARINDEX 和 STUFF 导出结果集

DECLARE @sqlstring Varchar(max) = 'Anna...Amal'
-- Getting first index of .
DECLARE @firstidx INT = CHARINDEX('.',@sqlstring) 
-- Getting last index of .  
Declare @lastidx int = (LEN(@sqlstring) - CHARINDEX('.',REVERSE(@sqlstring))) + 1
-- Stuffing the gap with emptystring
SELECT STUFF(@sqlstring,@firstidx+1,(@lastidx-@firstidx),'') as result

结果

+-----------+
|  result   |
+-----------+
| Anna.Amal |
+-----------+

UPDATE:如果有多个逗号分隔值

    DECLARE @sqlstring Varchar(max) = 'Anna...Amal,Vimal...Mathew'

    SELECT STRING_agg(removedvalues,',') as values
    FROM
    (SELECT STUFF(value, CHARINDEX('.',value)+1
        ,(LEN(value) - CHARINDEX('.',REVERSE(value)) + 1) - CHARINDEX('.',value),'') AS removedvalues
    FROM string_split(@sqlstring,',') ) AS t
+------------------------+
|         Values         |
+------------------------+
| Anna.Amal,Vimal.Mathew |
+------------------------+

【讨论】:

  • 这是有道理的。让我试一试。谢谢:)
  • 如果有效,请将其标记为答案。以后会对其他人有所帮助。
  • 这适用于只有一个点的地方,如果你尝试使用值Anna...Amal...Mathews,它将返回Anna.Mathews
  • @EzLo 知道了。要求变了。我需要做出改变
【解决方案3】:

请检查 Zhorov 的答案,因为它避免了像这样的多个操作。


CREATE PROCEDURE replace_characters_1
    @COLUMN_NAME varchar(30),
    @TABLE_NAME varchar(30)
AS
BEGIN

    DECLARE @SQL NVARCHAR(MAX) = N'
        UPDATE T SET
            ' + QUOTENAME(@COLUMN_NAME) + N' = REPLACE(' + QUOTENAME(@COLUMN_NAME) + N',''..'',''.'')
        FROM
            ' + QUOTENAME(@TABLE_NAME) + N' AS T
        WHERE
            T.' + QUOTENAME(@COLUMN_NAME) + N' LIKE ''%..%'';

        SET @UpdatedRowsOut = @@ROWCOUNT;';

    DECLARE @UpdatedRows INT = 1;

    WHILE @UpdatedRows > 0
    BEGIN

        EXECUTE sp_executesql 
            @SQL,
            N'@UpdatedRowsOut INT OUTPUT',
            @UpdatedRowsOut = @UpdatedRows OUTPUT;

    END

END

Dynamic SQL 现在返回已更新的行数,因此只要该列有 .. 的值,它就会继续运行(请注意,有一个 WHERE 过滤器,你不想每次更新所有行!)。

SQL Server 不是正则表达式的最佳选择,如果您需要使用正则表达式执行不同类型的操作,也许您想考虑使用 CLR 函数。

【讨论】:

    【解决方案4】:

    这是一种减少重复字符的方法。

    示例

    Declare @YourTable Table ([SomeCol] varchar(50))
    Insert Into @YourTable Values 
     ('Anna...Amal')
    ,('Anna........Amal')
    ,('Anna.Amal')
    ,('Anna Amal') 
    
    Select * 
          ,NewVal = replace(replace(replace(SomeCol,'.','†‡'),'‡†',''),'†‡','.')
     from @YourTable
    

    返回

    SomeCol             NewVal
    Anna...Amal         Anna.Amal
    Anna........Amal    Anna.Amal
    Anna.Amal           Anna.Amal
    Anna Amal           Anna Amal
    

    【讨论】:

    • @JohnCappelletti 我认为嵌套的REPLACEs 是更好的选择,+1。
    猜你喜欢
    • 1970-01-01
    • 2017-01-23
    • 2012-04-03
    • 1970-01-01
    • 1970-01-01
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    相关资源
    最近更新 更多