【问题标题】:SQL Server GUID sometimes valid and sometimes notSQL Server GUID 有时有效,有时无效
【发布时间】:2017-07-29 06:06:12
【问题描述】:

我遇到了 GUID 的问题,我已将其范围缩小到 LIKE 运算符的问题。

当以下在我的服务器上运行时

DECLARE @Problem NVARCHAR(1000) = N'58C21BC6-081B-4E57-BFE1-5B11AAC662F1';

DECLARE @GuidPattern NVARCHAR(1000) = 
    REPLICATE('[0-9A-Fa-f]', 8)
    + '-'
    + REPLICATE('[0-9A-Fa-f]', 4)
    + '-'
    + REPLICATE('[0-9A-Fa-f]', 4)
    + '-'
    + REPLICATE('[0-9A-Fa-f]', 4)
    + '-'
    + REPLICATE('[0-9A-Fa-f]', 12);

SELECT
    CASE
        WHEN @Problem LIKE @GuidPattern THEN 1
        ELSE 0
    END AS [FollowsPattern];

答案是0,但是当我在本地机器上运行完全相同的代码时,答案是1。

在我看来,字符串实际上是一个有效的 GUID,所以答案在这两种情况下都应该是 1。我所知道的所有其他确认 GUID 有效的方法也都成功了,无论是在本地还是在服务器上:

SELECT
    CASE
        WHEN CAST(@Problem AS UNIQUEIDENTIFIER) = @Problem THEN 1
        ELSE 0
    END AS [IsGuid1]; -- 1

SELECT
    CASE
        WHEN CONVERT(UNIQUEIDENTIFIER, @Problem) = @Problem THEN 1
        ELSE 0
    END AS [IsGuid2]; -- 1

SELECT
    CASE
        WHEN TRY_CONVERT(UNIQUEIDENTIFIER, @Problem) IS NOT NULL THEN 1
        ELSE 0
    END AS [IsGuid3]; -- 1

服务器版本是

Microsoft SQL Server 2016 (RTM) - 13.0.1601.5 (X64) 
    Apr 29 2016 23:23:58 
    Copyright (c) Microsoft Corporation
    Enterprise Edition: Core-based Licensing (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: ) (Hypervisor)

而我的本地安装版本是

Microsoft SQL Server 2014 - 12.0.2000.8 (X64)
    Feb 20 2014 20:04:26
    Copyright (c) Microsoft Corporation
    Express Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) 

默认排序规则不一样(本地SQL_Latin1_General_CP1_CI_AS 和服务器上的Danish_Norwegian_CI_AS),但我认为这并不重要,因为无论如何我都在处理Unicode。 在任何一台机器上添加一个额外的COLLATE 子句与另一台的排序规则没有区别。 更新:不正确,排序规则是问题的根源。我只在变量声明中测试了不同的排序规则,而不是在比较本身中。

【问题讨论】:

  • GUID 由我无法控制的集成提供,用于跨多个表关联行。一切都表明集成确实使用了 NEWID 的等效项,但我在这里使用了一个字符串常量,因为我能够追踪一个导致问题的特定 GUID 实例(我们收到的绝大多数没有)。不过,这并不能解释问题。
  • rextester.com 返回 1
  • @McNets 缩减版给出相同的结果(即服务器上的空结果集和本地1)。
  • 对不起我的第一条评论,完全弄错了......如果我理解正确:你的问题是:它是怎么来的,第一个代码在我的本地安装中返回 1而相同的代码在您的服务器上返回 0? 问题不是:我如何证明字符串是否是有效的 GUID?

标签: sql-server tsql sql-server-2014 sql-server-2016


【解决方案1】:

我想问题是整理。

看看:http://rextester.com/IRQEFU33639

如果您使用默认排序规则:

SELECT
    CASE
        WHEN @Problem LIKE @GuidPattern THEN 1
        ELSE 0
    END AS [FollowsPattern];

结果 = 1

相反,如果您强制使用 Danish_Norwegian_CI_AS 排序规则:

SELECT
    CASE
        WHEN @Problem collate Danish_Norwegian_CI_AS  LIKE @GuidPattern THEN 1
        ELSE 0
    END AS [FollowsPattern];

它返回 0。

我建议将排序规则强制为 SQL_Latin1_General_CP1_CI_AS 或其他运行良好的排序规则。

SELECT
    CASE
        WHEN @Problem COLLATE SQL_Latin1_General_CP1_CI_AS LIKE @GuidPattern THEN 1
        ELSE 0
    END AS [FollowsPattern];

为了方便起见,也许可以使用INLINE User Defined Function。

【讨论】:

  • 我检查了这个,这似乎是真的,排序规则是造成这种情况的原因。我必须承认,我没想到会这样......
  • 我想它与正则表达式有关,也许对于挪威语你需要改变它。
  • 是的,你必须处理它。我建议使用内联 udf 以使其更短。
  • 这解决了问题。在丹麦语和挪威语中,AA 在Z 之后被整理为Å(参见en.wikipedia.org/wiki/%C3%85)。
【解决方案2】:

强制使用标准排序规则

SELECT
    CASE
        WHEN @Problem COLLATE Latin1_General_CI_AS LIKE @GuidPattern COLLATE Latin1_General_CI_AS THEN 1
        ELSE 0
    END AS [FollowsPattern];

原因是Danish_Norwegian_CI_AS排序规则中如何匹配“a”。

请参阅SQL 'Like' operator and 'aa' 了解更多我使用丹麦语_挪威语_CI_AS 进行演示的地方

【讨论】:

  • 是的,这可能是最好的解决方案。我最初在 SSIS 作业的 GUID 列中查找 GUID 时遇到了这个问题 - 与我在问题中描述的情况有些不同 - 所以我必须以某种方式适应实际问题。
猜你喜欢
  • 2013-03-07
  • 2015-02-11
  • 2012-08-02
  • 2015-03-31
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多