【问题标题】:How to remove accents and all chars <> a..z in sql-server?如何在 sql-server 中删除重音符号和所有字符 <> a..z?
【发布时间】:2011-04-30 18:12:55
【问题描述】:

我需要对 varchar(20) 字段进行以下修改:

  1. 用普通字母替换重音符号(如 è 到 e)
  2. 在 (1) 之后删除所有不在 a..z 中的字符

例如

'aèàç=.32s df' 

必须变成

'aeacsdf'

是否有特殊的存储函数可以轻松实现这一点?

更新:请提供 T-SQL 而非 CLR 解决方案。这是我暂时使用的解决方法,因为它暂时适合我的需求,无论如何使用更优雅的方法会更好。

CREATE FUNCTION sf_RemoveExtraChars (@NAME nvarchar(50))
RETURNS nvarchar(50)
AS
BEGIN
  declare @TempString nvarchar(100)
  set @TempString = @NAME 
  set @TempString = LOWER(@TempString)
  set @TempString =  replace(@TempString,' ', '')
  set @TempString =  replace(@TempString,'à', 'a')
  set @TempString =  replace(@TempString,'è', 'e')
  set @TempString =  replace(@TempString,'é', 'e')
  set @TempString =  replace(@TempString,'ì', 'i')
  set @TempString =  replace(@TempString,'ò', 'o')
  set @TempString =  replace(@TempString,'ù', 'u')
  set @TempString =  replace(@TempString,'ç', 'c')
  set @TempString =  replace(@TempString,'''', '')
  set @TempString =  replace(@TempString,'`', '')
  set @TempString =  replace(@TempString,'-', '')
  return @TempString
END
GO

【问题讨论】:

  • 仅供参考,您不需要使用 nvarchar 来为您的角色添加重音。除非你绝对需要它,否则我建议转换为 varchar
  • NVARCHAR 用于保存 Unicode 字符。重音字符不一定是 Unicode(很可能不是)。
  • 是的,我知道,但是我正在处理的数据库是针对所有 nvarchar 的政策(奇怪的政策)

标签: sql-server sql-server-2005 tsql


【解决方案1】:

实现这一点的最佳方法非常简单高效:

SELECT 'àéêöhello!' Collate SQL_Latin1_General_CP1253_CI_AI

输出'aeeohello!'

字符串不能是 unicode。如果您有一个 nvarchar,只需在使用整理之前将其转换为 varchar。

这是一个满足 OP 需求的函数:

create function [dbo].[RemoveExtraChars] ( @p_OriginalString varchar(50) )
returns varchar(50) as
begin

  declare @i int = 1;  -- must start from 1, as SubString is 1-based
  declare @OriginalString varchar(100) = @p_OriginalString Collate SQL_Latin1_General_CP1253_CI_AI;
  declare @ModifiedString varchar(100) = '';

  while @i <= Len(@OriginalString)
  begin
    if SubString(@OriginalString, @i, 1) like '[a-Z]'
    begin
      set @ModifiedString = @ModifiedString + SubString(@OriginalString, @i, 1);
    end
    set @i = @i + 1;
  end

  return @ModifiedString

end

然后,命令:

select dbo.RemoveExtraChars('aèàç=.32s df')

输出

aeacsdf

【讨论】:

  • 感谢您的支持 ;-) 我真的很想知道为什么没有人使用这种方法,当我在法国环境中工作时,它为我节省了无数次。
  • 这真的很棒。为我节省了很多时间。应该有更多的人对此表示支持。实际上,这应该是公认的答案,因为它直接用一段有效的代码回答了这个问题。
  • @paracycle 我没有投票,因为它没有完全回答 OP 的问题。要求的第 2 部分是去除 a..z 范围之外的任何字符。建议的解决方案SELECT 'aèàç=.32s df' COLLATE SQL_Latin1_General_CP1253_CI_AI; 输出aeac=.32s df=.32&lt;space&gt; 是无效字符。
  • while @i 必须是:while @i 否则它将跳过字符串中的最后一个字母。不过感谢您的解决方案!
  • 关于转换为varchar的部分不够突出,特别是因为这个答案没有被选中,但在我看来是最好的。 select family_name,CONVERT(VARCHAR(99),family_name) 整理 SQL_Latin1_General_Cp1251_CS_AS FROM people
【解决方案2】:
    SELECT 'áéíóú' COLLATE Cyrillic_General_CI_AI

这将替换所有重音字符...

结果:aeiou

希望对您有所帮助!

【讨论】:

  • 有趣,效果很好!我尝试替换一些其他字符,例如“º”(用于度数表示),但效果不佳。
【解决方案3】:

让我先澄清一点:您显示的重音字符实际上不是 Unicode(正如一个答案所暗示的那样);这些是 8 位 ASCII 字符。要记住的一件事:您看到像 è 和 à 这样的字符仅仅是因为这是您的代码页(您的操作系统和/或 SQL Server 使用的代码页 [我不确定是哪一个])显示它们的方式。在不同的代码页中,这些字符将由完全不同的符号表示(例如,如果您使用西里尔文或土耳其语代码页)。

无论如何,假设您想将这些 8 位字符替换为与默认代码页等效的最接近的美国/拉丁字符 [我假设这些字符来自拉丁字符集的某些变体]。这就是我处理类似问题的方式(免责声明:这不是一个非常优雅的解决方案,但我当时想不出更好的方法):

创建一个 UDF 以将 8 位 ASCII 字符转换为 7 位可打印 ASCII 等价物,例如:

CREATE FUNCTION dbo.fnCharToAscii
(
  @Char AS VARCHAR
)
RETURNS
  VARCHAR   
AS
BEGIN
IF (@Char IS NULL)
  RETURN ''

-- Process control and DEL chars.
IF (ASCII(@Char) < 32) OR (ASCII(@Char) = 127)
    RETURN ''

-- Return printable 7-bit ASCII chars as is.
-- UPDATE TO DELETE NON-ALPHA CHARS.
IF (ASCII(@Char) >= 32) AND (ASCII(@Char) < 127)
    RETURN @Char

-- Process 8-bit ASCII chars.
RETURN
  CASE ASCII(@Char)
    WHEN 128 THEN 'E'
    WHEN 129 THEN '?'
    WHEN 130 THEN ','
    WHEN 131 THEN 'f'
    WHEN 132 THEN ','
    WHEN 133 THEN '.'
    WHEN 134 THEN '+'
    WHEN 135 THEN '+'
    WHEN 136 THEN '^'
    WHEN 137 THEN '%'
    WHEN 138 THEN 'S'
    WHEN 139 THEN '<'
    WHEN 140 THEN 'C'
    WHEN 141 THEN '?'
    WHEN 142 THEN 'Z'
    WHEN 143 THEN '?'
    WHEN 144 THEN '?'
    WHEN 145 THEN ''''
    WHEN 146 THEN ''''
    WHEN 147 THEN '"'
    WHEN 148 THEN '"'
    WHEN 149 THEN '-'
    WHEN 150 THEN '-'
    WHEN 151 THEN '-'
    WHEN 152 THEN '~'
    WHEN 153 THEN '?'
    WHEN 154 THEN 's'
    WHEN 155 THEN '>'
    WHEN 156 THEN 'o'
    WHEN 157 THEN '?'
    WHEN 158 THEN 'z'
    WHEN 159 THEN 'Y'
    WHEN 160 THEN ' '
    WHEN 161 THEN 'i'
    WHEN 162 THEN 'c'
    WHEN 163 THEN 'L'
    WHEN 164 THEN '?'
    WHEN 165 THEN 'Y'
    WHEN 166 THEN '|'
    WHEN 167 THEN '$'
    WHEN 168 THEN '^'
    WHEN 169 THEN 'c'
    WHEN 170 THEN 'a'
    WHEN 171 THEN '<'
    WHEN 172 THEN '-'
    WHEN 173 THEN '-'
    WHEN 174 THEN 'R'
    WHEN 175 THEN '-'
    WHEN 176 THEN 'o'
    WHEN 177 THEN '+'
    WHEN 178 THEN '2'
    WHEN 179 THEN '3'
    WHEN 180 THEN ''''
    WHEN 181 THEN 'm'
    WHEN 182 THEN 'P'
    WHEN 183 THEN '-'
    WHEN 184 THEN ','
    WHEN 185 THEN '1'
    WHEN 186 THEN '0'
    WHEN 187 THEN '>'
    WHEN 188 THEN '?'
    WHEN 189 THEN '?'
    WHEN 190 THEN '?'
    WHEN 191 THEN '?'
    WHEN 192 THEN 'A'
    WHEN 193 THEN 'A'
    WHEN 194 THEN 'A'
    WHEN 195 THEN 'A'
    WHEN 196 THEN 'A'
    WHEN 197 THEN 'A'
    WHEN 198 THEN 'A'
    WHEN 199 THEN 'C'
    WHEN 200 THEN 'E'
    WHEN 201 THEN 'E'
    WHEN 202 THEN 'E'
    WHEN 203 THEN 'E'
    WHEN 204 THEN 'I'
    WHEN 205 THEN 'I'
    WHEN 206 THEN 'I'
    WHEN 207 THEN 'I'
    WHEN 208 THEN 'D'
    WHEN 209 THEN 'N'
    WHEN 210 THEN 'O'
    WHEN 211 THEN 'O'
    WHEN 212 THEN 'O'
    WHEN 213 THEN 'O'
    WHEN 214 THEN 'O'
    WHEN 215 THEN 'x'
    WHEN 216 THEN 'O'
    WHEN 217 THEN 'U'
    WHEN 218 THEN 'U'
    WHEN 219 THEN 'U'
    WHEN 220 THEN 'U'
    WHEN 221 THEN 'Y'
    WHEN 222 THEN 'b'
    WHEN 223 THEN 'B'
    WHEN 224 THEN 'a'
    WHEN 225 THEN 'a'
    WHEN 226 THEN 'a'
    WHEN 227 THEN 'a'
    WHEN 228 THEN 'a'
    WHEN 229 THEN 'a'
    WHEN 230 THEN 'a'
    WHEN 231 THEN 'c'
    WHEN 232 THEN 'e'
    WHEN 233 THEN 'e'
    WHEN 234 THEN 'e'
    WHEN 235 THEN 'e'
    WHEN 236 THEN 'i'
    WHEN 237 THEN 'i'
    WHEN 238 THEN 'i'
    WHEN 239 THEN 'i'
    WHEN 240 THEN 'o'
    WHEN 241 THEN 'n'
    WHEN 242 THEN 'o'
    WHEN 243 THEN 'o'
    WHEN 244 THEN 'o'
    WHEN 245 THEN 'o'
    WHEN 246 THEN 'o'
    WHEN 247 THEN '-'
    WHEN 248 THEN 'o'
    WHEN 249 THEN 'u'
    WHEN 250 THEN 'u'
    WHEN 251 THEN 'u'
    WHEN 252 THEN 'u'
    WHEN 253 THEN 'y'
    WHEN 254 THEN 'b'
    WHEN 255 THEN 'y'
  END
RETURN ''
END

上面的代码是通用的,因此您可以调整字符映射以删除所有非字母字符,例如您可以在匹配可打印的 7 位 ASCII 字符时使用这样的代码(这假定不区分大小写的排序规则):

IF @Char NOT LIKE '[a-z]' RETURN ''

要查看 8 位 ASCII 符号的字符映射是否正常工作,请运行以下代码:

DECLARE @I   INT
DECLARE @Msg VARCHAR(32)

SET @I = 128

WHILE @I < 256
BEGIN
    SELECT @Msg = CAST(@I AS VARCHAR) + 
    ': ' + 
    CHAR(@I) + 
    '=' + 
    dbo.fnCharToAscii(CHAR(@I))
    PRINT @Msg
    SET @I = @I + 1 
END

现在您可以创建一个 UDF 来处理字符串:

CREATE FUNCTION dbo.fnStringToAscii
(
  @Value AS VARCHAR(8000)
)
RETURNS
  VARCHAR(8000) 
AS
BEGIN
IF (@Value IS NULL OR DATALENGTH(@Value) = 0)
  RETURN ''

DECLARE @Index  INT
DECLARE @Result VARCHAR(8000)

SET @Result = ''
SET @Index  = 1

WHILE (@Index <= DATALENGTH(@Value))
BEGIN
  SET @Result = @Result + dbo.fnCharToAscii(SUBSTRING(@Value, @Index, 1))
  SET @Index = @Index + 1   
END

RETURN @Result
END
GO

【讨论】:

    【解决方案4】:

    您可以通过使用带有不区分重音的排序规则的 COLLATE 子句来将带重音的字母字符与非字母字符进行比较,从而避免硬编码的 REPLACE 语句:

    DECLARE 
      @s1 NVARCHAR(200),
      @s2 NVARCHAR(200)
    
    SET @s1 = N'aèàç=.32s df' 
    
    SET @s2 = N''
    SELECT @s2 = @s2 + no_accent 
    FROM ( 
      SELECT 
        SUBSTRING(@s1, number, 1) AS accent,
        number
      FROM master.dbo.spt_values 
      WHERE TYPE = 'P'
      AND number BETWEEN 1 AND LEN(@s1) 
    ) s1 
    INNER JOIN (
      SELECT NCHAR(number) AS no_accent
      FROM master.dbo.spt_values 
      WHERE type = 'P'
      AND (number BETWEEN 65 AND 90 OR number BETWEEN 97 AND 122) 
    ) s2 
      ON s1.accent COLLATE LATIN1_GENERAL_CS_AI = s2.no_accent 
    ORDER BY number
    
    SELECT @s1 
    SELECT @s2 
    
    /*
    aèàç=.32s df
    aeacsdf
    */
    

    【讨论】:

      【解决方案5】:

      嗯,这并没有好很多,但它至少是一个 tsql 集解决方案

      declare @TempString varchar(100)
      
      set @TempString='textàè containing éìòaccentsç''''` and things-'
      
      select @TempString=
          replace(
              replace(
                  replace(
                      replace(
                          replace(
                              replace(
                                  replace(
                                      replace(
                                          replace(
                                              replace(
                                                  replace(@TempString,' ', '') 
                                              ,'à', 'a')
                                          ,'è', 'e') 
                                      ,'é', 'e')
                                  ,'ì', 'i')
                              ,'ò', 'o') 
                          ,'ù', 'u') 
                      ,'ç', 'c') 
                  ,'''', '') 
              ,'`', '')
          ,'-', '') 
      
      
      
      select @TempString
      

      【讨论】:

      • 你称之为“固定解决方案”的是什么?这是一个完全程序化的批处理。
      • @isme 这是一套解决方案,因为我可以将逻辑转储到单个更新语句中并在一个事务中更新整个表,而不是像 OP 的原始语句那样拥有多个事务。
      • 您能否通过将代码示例重写为包含许多行的表上的 SELECT 语句来证明这一点?
      • @isme 我不想将其编辑到我的答案中,所以这里是:textsnip.com/84da22
      • 感谢您的快速修复
      【解决方案6】:

      AFAIK,没有“看起来相似”的 unicode/UTF-X 字符的直接映射。除非有人有更酷的东西,否则我建议采用蛮力方法,以便在那之前完成工作。

      听起来你需要做 2 次传球。第一遍将首先替换看起来相似的字母,然后遍历并删除所有剩余的非英文字母。

      这篇文章可以帮助你创建一个用户定义的函数,这样你就可以使用正则表达式来代替几十个 REPLACE 调用:http://msdn.microsoft.com/en-us/magazine/cc163473.aspx

      这是我在这个案例中一直使用的字典:

          public static Dictionary<char, string> NonEnglishLetterMapping = new Dictionary<char, string>
          {
                {'a', "áàâãäåāăą"}
              //, {'b', ""}
              , {'c', "ćĉċč"}
              , {'d', "ďđ"}
              , {'e', "éëêèēĕėę"}
              //, {'f', ""}
              , {'g', "ĝğġģ"}
              , {'h', "ĥħ"}
              , {'i', "ìíîïĩīĭįı"}
              , {'j', "ĵ"}
              , {'k', "ķĸ"}
              , {'l', "ĺļľŀł"}
              //, {'m', ""}
              , {'n', "ñńņňʼnŋ"}
              , {'o', "òóôõöōŏőơ"}
              //, {'p', ""}
              //, {'q', ""}
              , {'r', "ŕŗř"}
              , {'s', "śŝşšș"}
              , {'t', "ţťŧț"}
              , {'u', "ùúûüũūŭůűųư"}
              //, {'v', ""}
              , {'w', "ŵ"}
              //, {'x', ""}
              , {'y', "ŷ"}
              , {'z', "źżž"}
          };
      

      【讨论】:

      • 是的,谢谢你的想法,无论如何我试图在 T-SQL 中获得所需的结果,而不使用 CLR 函数
      【解决方案7】:

      通过架构中的两个辅助表,您只需使用 SELECT 语句即可转换数据。

      首先声明一个视图来实现一个数字表,从 1 到 65536。以下技术归功于Itzik Ben-Gan

      CREATE VIEW Sequence
      AS
      WITH T1(_) AS (SELECT NULL UNION ALL SELECT NULL),
      T2(_) AS (SELECT NULL FROM T1 AS L CROSS JOIN T1 AS R),
      T3(_) AS (SELECT NULL FROM T2 AS L CROSS JOIN T2 AS R),
      T4(_) AS (SELECT NULL FROM T3 AS L CROSS JOIN T3 AS R),
      T5(_) AS (SELECT NULL FROM T4 AS L CROSS JOIN T4 AS R)
      SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS Number
      FROM T5;
      

      接下来声明带有变音符号的字符及其非变音符号等值字符之间的映射。此示例数据并非完整映射,仅作为示例:

      CREATE TABLE UndiacriticMap (
        DiacriticCharacter CHAR(1) NOT NULL PRIMARY KEY,
        UndiacriticCharacter CHAR(1) NOT NULL
      );
      
      INSERT INTO UndiacriticMap (
        DiacriticCharacter,
        UndiacriticCharacter
      )
      VALUES
        ('à', 'a'),
        ('è', 'e'),
        ('é', 'e'),
        ('ì', 'i'),
        ('ò', 'o'),
        ('ç', 'c');
      

      最后声明一个表,其中有一列包含测试数据。数据来源于问题和DForck42's answer

      CREATE TABLE TestData (
        ID INT NOT NULL PRIMARY KEY,
        String VARCHAR(50) NOT NULL
      );
      
      INSERT INTO TestData (
        ID,
        String
      )
      VALUES
        (1, 'textàè containing éìòaccentsç''''` and things-'),
        (2, 'aèàç=.32s df');
      

      有了这些对象,下面的SELECT 语句以关系方式处理测试数据,除了非关系黑客将字符连接在一起。 “黑盒 XML 方法”是由于 Anith Sen:

      WITH CharacterWise (ID, Symbol, Position) AS (
        SELECT
          ID,
          SUBSTRING(TestData.String, Sequence.Number, 1),
          Sequence.Number
        FROM TestData
        INNER JOIN Sequence ON
          Sequence.Number <= LEN(TestData.String)
      ),
      Stripped (ID, Symbol, Position) AS (
        SELECT
          ID,
          CASE 
            WHEN UndiacriticMap.DiacriticCharacter IS NOT NULL
            THEN UndiacriticMap.UndiacriticCharacter
            ELSE CASE 
              WHEN CharacterWise.Symbol LIKE '[a-z]' COLLATE Latin1_General_BIN
              THEN CharacterWise.Symbol
              ELSE ''
            END
          END,
          CharacterWise.Position
        FROM CharacterWise
        LEFT OUTER JOIN UndiacriticMap ON
          UndiacriticMap.DiacriticCharacter = CharacterWise.Symbol
      )
      SELECT
        TestData.ID,
        TestData.String,
        (
          SELECT Stripped.Symbol AS [text()]
          FROM Stripped
          WHERE TestData.ID = Stripped.ID
          ORDER BY Stripped.Position
          FOR XML PATH('')
        ) AS StrippedString
      FROM TestData;
      

      查询产生以下结果集:

      ID          String                                             StrippedString
      ----------- -------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      1           textàè containing éìòaccentsç''` and things-       textaecontainingeioaccentscandthings
      2           aèàç=.32s df                                       aeacsdf
      

      【讨论】:

        【解决方案8】:

        我知道这并不优雅,但是当整理不起作用并且您无法使用函数时,您可以将这个嵌套替换用于大多数使用的变音符号。我发布了这个,所以你不必自己再次输入:)

        select REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(myfield,'é','e'),'ê','e'),'ë','e'),'è','e'),'É','E'),'È','E'),'Ê','E'),'Ë','E'),'ð','D'),'Ð','D'),'â','a'),'à','a'),'á','a'),'ã','a'),'æ','a'),'à','a'),'å','a'),'Å','A'),'À','A'),'Á','A'),'Â','A'),'Ã','A'),'Æ','A'),'ä','a'),'Ä','A'),'ï','i'),'î','i'),'ì','i'),'í','i'),'Ì','I'),'Í','I'),'Î','I'),'Ï','I'),'ô','o'),'ò','o'),'ó','o'),'õ','o'),'ø','o'),'Ò','O'),'Ó','O'),'Ô','O'),'Õ','O'),'Ø','O'),'ö','o'),'Ö','O'),'û','u'),'ù','u'),'ú','u'),'Ù','U'),'Ú','U'),'Û','U'),'Ü','U'),'ü','u'),'ñ','n'),'Ñ','N'),'Ç','C'),'ç','c'),'ý','y'),'ÿ','y'),'Ý','Y'),'þ','T'),'Þ','t'),'ß','ss') from mytable
        

        【讨论】:

          【解决方案9】:

          离我只有两分钱

          select * From XXX  
              where cast(word as varchar(max)) collate SQL_Latin1_General_CP1253_CI_AI = 'sluiten' collate SQL_Latin1_General_CP1253_CI_AI
          

          【讨论】:

            【解决方案10】:
            select * from database_name.table_name 
            where countries LIKE '%é%'
            or countries like'%é%'
            or countries like'%ê%'
            or countries like'%ë%'
            or countries like'%è%'
            or countries like'%É%'
            or countries like'%È%'
            or countries like'%Ê%'
            or countries like'%Ë%'
            or countries like'%ð%'
            or countries like'%Ð%'
            or countries like'%â%'
            or countries like'%à%'
            or countries like'%á%'
            or countries like'%ã%'
            or countries like'%æ%'
            or countries like'%à%'
            or countries like'%å%'
            or countries like'%Å%'
            or countries like'%À%'
            or countries like'%Á%'
            or countries like'%Â%'
            or countries like'%Ã%'
            or countries like'%Æ%'
            or countries like'%ä%'
            or countries like'%Ä%'
            or countries like'%ï%'
            or countries like'%î%'
            or countries like'%ì%'
            or countries like'%í%'
            or countries like'%Ì%'
            or countries like'%Í%'
            or countries like'%Î%'
            or countries like'%Ï%'
            or countries like'%ô%'
            or countries like'%ò%'
            or countries like'%ó%'
            or countries like'%õ%'
            or countries like'%ø%'
            or countries like'%Ò%'
            or countries like'%Ó%'
            or countries like'%Ô%'
            or countries like'%Õ%'
            or countries like'%Ø%'
            or countries like'%ö%'
            or countries like'%Ö%'
            or countries like'%û%'
            or countries like'%ù%'
            or countries like'%ú%'
            or countries like'%Ù%'
            or countries like'%Ú%'
            or countries like'%Û%'
            or countries like'%Ü%'
            or countries like'%ü%'
            or countries like'%ñ%'
            or countries like'%Ñ%'
            or countries like'%Ç%'
            or countries like'%ç%'
            or countries like'%ý%'
            or countries like'%ÿ%'
            or countries like'%Ý%'
            or countries like'%þ%'
            or countries like'%Þ%'
            or countries like'%ß%';
            

            【讨论】:

              【解决方案11】:

              我正在为another question 写这个答案,但是当我去发布它时,OP 删除了这个问题......所以我会在这里发布这个,因为它是相关的。这不使用WHILE 或多行标量函数(在最受好评的答案中),我提供了nvarcharvarchar 解决方案:

              nvarchar:

              CREATE FUNCTION dbo.RemoveAccents_N (@String nvarchar(4000)) 
              RETURNS table
              AS RETURN
              
                  WITH N AS(
                      SELECT N
                      FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
                  Tally AS(
                      SELECT TOP (LEN(@String)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
                      FROM N N1, N N2, N N3, N N4)
                  SELECT (SELECT CASE WHEN V.CS LIKE '[A-z]' THEN V.CS ELSE V.YS END
                          FROM Tally T
                               CROSS APPLY (VALUES(SUBSTRING(@String,T.I,1), CONVERT(varchar(4000),SUBSTRING(@String,T.I,1)) COLLATE SQL_Latin1_General_CP1253_CI_AI))V(YS,CS)
                          FOR XML PATH(N''),TYPE).value('.','nvarchar(4000)') AS AccentlessString;
              

              varchar:

              CREATE FUNCTION dbo.RemoveAccents (@String varchar(8000)) 
              RETURNS table
              AS RETURN
              
                  WITH N AS(
                      SELECT N
                      FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
                  Tally AS(
                      SELECT TOP (LEN(@String)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
                      FROM N N1, N N2, N N3, N N4)
                  SELECT (SELECT CASE WHEN V.CS LIKE '[A-z]' THEN V.CS ELSE V.YS END
                          FROM Tally T
                               CROSS APPLY (VALUES(SUBSTRING(@String,T.I,1), SUBSTRING(@String,T.I,1) COLLATE SQL_Latin1_General_CP1253_CI_AI))V(YS,CS)
                          FOR XML PATH(N''),TYPE).value('.','varchar(8000)') AS AccentlessString;
              

              函数调用如下:

              SELECT *
              FROM (VALUES(N'Åìèë Öàíêîâ @11 ώЙ⅔♠♪'))V(YourString)
                   CROSS APPLY dbo.RemoveAccents_N(V.YourString) RA;
              

              【讨论】:

                【解决方案12】:

                简化为:

                CREATE OR ALTER FUNCTION F_CLEAN_ACCENT_STRING(@NAME NVARCHAR(128))
                RETURNS NVARCHAR(128)
                AS
                BEGIN
                   DECLARE @OUT NVARCHAR(128) = '', @I TINYINT = 1, @C CHAR(1);
                   WHILE @I <= LEN(@NAME)
                   BEGIN
                      IF @C NOT LIKE '[A-Z0-9_]' COLLATE French_CI_AI
                         SET @OUT = @OUT + '_';
                      ELSE 
                         SET @OUT = @OUT + CHAR(ASCII(SUBSTRING(@NAME, @I, 1) COLLATE SQL_Latin1_General_CP1253_CI_AI));
                      SET @I += 1;
                   END;
                   RETURN @OUT;
                END;
                GO
                
                SELECT dbo.F_CLEAN_ACCENT_STRING('Électricîté de Fränce') AS UNACCENT;
                
                UNACCENT
                ----------------------
                Electricite de France
                

                【讨论】:

                  【解决方案13】:

                  在 postgress 10 中:

                  create extension unaccent;# as root in Your db, for each db
                  select unaccent("ąęśłóŻŹŁÓĄĘ");
                  

                  :)

                  【讨论】:

                    【解决方案14】:

                    在 mySql 中作为函数(转换 + 其他东西)

                    DELIMITER $$
                    CREATE DEFINER=`root`@`localhost` FUNCTION `txt2slug`(`txt` VARCHAR(50)) RETURNS varchar(50) CHARSET utf8mb4
                    BEGIN   
                        DECLARE pl_char VARCHAR(10) DEFAULT "ęóąśłżźćń";
                        DECLARE en_char VARCHAR(10) DEFAULT "eoaslzzcn";
                        DECLARE slug VARCHAR(50) DEFAULT (txt); 
                        DECLARE pos INT DEFAULT 1;  
                            
                        SET slug = LOWER(TRIM(slug));   
                        SET slug = REGEXP_REPLACE(slug, "[,;:!?.]", "");    
                        SET slug = REGEXP_REPLACE(slug, " ", "-");  
                            
                        WHILE pos <= LENGTH(pl_char) DO     
                            SET slug = REGEXP_REPLACE(slug, SUBSTRING(pl_char, pos, 1), SUBSTRING(en_char, pos, 1));
                            SET pos = pos + 1;
                        END WHILE;  
                            
                        RETURN slug;    
                        
                    END$$
                    DELIMITER ;
                            
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2015-08-30
                      • 2011-04-25
                      • 1970-01-01
                      • 2010-09-19
                      • 2012-12-10
                      相关资源
                      最近更新 更多