【问题标题】:compare s, t with ş, ţ in SQL Server在 SQL Server 中将 s, t 与 ş, ţ 进行比较
【发布时间】:2025-12-02 21:05:02
【问题描述】:

我关注了这篇帖子How do I perform an accent insensitive compare (e with è, é, ê and ë) in SQL Server?,但它对“ş”、“ţ”字符没有帮助。

如果城市名称是“iaşi”,则不会返回任何内容:

SELECT *
  FROM City
 WHERE Name COLLATE Latin1_general_CI_AI LIKE '%iasi%' COLLATE Latin1_general_CI_AI

如果城市名称是“iaşi”,这也不会返回任何内容(注意 LIKE 模式中的外国 ş):

SELECT *
  FROM City
 WHERE Name COLLATE Latin1_general_CI_AI LIKE '%iaşi%' COLLATE Latin1_general_CI_AI

我正在使用 SQL Server Management Studio 2012。
我的数据库和列排序规则是“Latin1_General_CI_AI”,列类型是 nvarchar。

我怎样才能让它工作?

【问题讨论】:

    标签: sql sql-server tsql sql-server-2012


    【解决方案1】:

    在 SQL Server 2008 排序规则版本为 100 were introduced

    排序规则Latin1_General_100_CI_AI 似乎可以满足您的要求。

    以下应该有效:

    SELECT * FROM City WHERE Name LIKE '%iasi%' COLLATE Latin1_General_100_CI_AI
    

    【讨论】:

      【解决方案2】:

      这个问题困扰了我一段时间,直到现在我终于弄明白了。 假设您的表或列是 SQL_Latin1_General_CP1_CI_AS 排序规则,如果您这样做:

      update 
          set myCol = replace(myCol , N'ș', N's')
      from MyTable
      

      update 
          set myCol = replace(myCol,N'ț',N't')
      from MyTable
      

      替换功能不会找到这些字符,因为您的键盘(罗马尼亚语标准键盘)生成的“ș”与数据库中的“ş”或“ţ”不同。 作为比较:ţț 和 şș - 您可以看到它们不同,因为重音更接近“s”或“t”字符。

      相反,您必须这样做:

      update 
          set myCol = replace(myCol , N'ş', N's')
      from MyTable
      

      update 
          set myCol = replace(myCol,N'ţ',N't')
      from MyTable
      

      【讨论】:

        【解决方案3】:

        您指定的字符不是 Latin1 代码页的一部分,因此除了Latin1_General_CI_AI 中的序数之外,它们无法以任何其他方式进行比较。事实上,我假设它们在给定的排序规则中根本不起作用。

        如果您只使用一种排序规则,只需使用正确的排序规则(例如,如果您的数据是土耳其语,请使用 Turkish_CI_AI)。如果您的数据来自多种不同的语言,则必须使用 unicode 和正确的排序规则。

        但是,还有一个问题。在罗马尼亚语或土耳其语等语言中,ş不是重音 s,而是一个完全独立的字符 - 请参阅 http://collation-charts.org/mssql/mssql.0418.1250.Romanian_CI_AI.html。与例如对比。 šs 的重音形式。

        如果你真的需要ş等于s,你必须手动替换原来的字符。

        此外,当您使用 unicode 列(nvarchar 和一堆)时,请确保您也使用 unicode literals,即。使用N'%iasi%' 而不是'%iasi%'

        【讨论】:

        • "...您必须(要)手动替换原始字符",您确定这是唯一的解决方案吗?这个问题仅与 MSSQL 有关吗? MySQL 呢?
        • @superware 好吧,如果 MySQL 正确地遵循 Unicode 标准,它也会有同样的问题。就剧本而言,这两个字母没有任何共同之处。当然,它们看起来有点相似,但实际上并不相关。当然,有些人在想用英文键盘书写时可能会使用相似的字符,但这对于脚本并不重要。
        【解决方案4】:

        您只需要在like 操作之前更改name 字段的排序规则。检查下面的测试代码

        DECLARE @city TABLE ( NAME NVARCHAR(20) )
        
        INSERT INTO @city
            VALUES ( N'iaşi' )
        
        SELECT *
            FROM @city
            WHERE name LIKE 'iasi'
        --No return
        
        SELECT *
            FROM @city
            WHERE name COLLATE Latin1_general_CI_AI LIKE '%iasi%'
        --Return 1 row
        

        【讨论】:

          【解决方案5】:

          我猜不是最整洁的解决方案,但如果您知道问题只是“ş”和“ţ”字符,是否可以接受替换?

          SELECT *
          FROM City
          WHERE replace(replace(Name,'ş','s'),'ţ','t') LIKE COLLATE Latin1_general_CI_AI '%iasi%' COLLATE Latin1_general_CI_AI
          

          【讨论】:

          • 它不会返回任何东西,即使我搜索“iaşi”
          • 如果您的搜索词中也有特殊字符,您也需要在搜索词中进行替换。虽然还不如离开是'iasi'而不是'iaşi'。我认为其他人的建议应该是您的第一个电话点。