【问题标题】:How to check if a string is a uniqueidentifier?如何检查字符串是否是唯一标识符?
【发布时间】:2011-01-10 17:00:44
【问题描述】:

uniqueidentifier (SQL Server) 是否有等效于 IsDate 或 IsNumeric 的方法? 或者有什么相当于 (C#) TryParse 的吗?

否则我将不得不编写自己的函数,但我想确保我不会重新发明轮子。

我试图涵盖的场景如下:

SELECT something FROM table WHERE IsUniqueidentifier(column) = 1

【问题讨论】:

  • 我不明白你想要达到什么目的。您想选择某个列的值为唯一标识符的所有行吗?业务场景是什么?如果一个列是用来保存一个唯一标识符的,那么它的值不是为空还是实际上是一个唯一标识符?还能是什么?
  • 我正在使用名称的 guid 创建数据库(构建服务器上的集成测试)。我想列出那些数据库(select * from sys.databases where IsUniqueidentifier(name))
  • 啊,明白了——你不是指 uniqueidentifier 数据类型,只是一个字符串。

标签: sql sql-server


【解决方案1】:

SQL Server 2012 使用 TRY_CONVERT(UNIQUEIDENTIFIER, expression) 让这一切变得更容易

SELECT something
FROM   your_table
WHERE  TRY_CONVERT(UNIQUEIDENTIFIER, your_column) IS NOT NULL;

对于 SQL Server 的早期版本,现有答案遗漏了一些要点,这意味着它们可能与 SQL Server 实际上会毫无怨言地强制转换为 UNIQUEIDENTIFIER 的字符串不匹配,或者最终仍可能导致无效转换错误。

SQL Server 接受包裹在 {} 或不包裹的 GUID。

此外,它还会忽略字符串末尾的无关字符。例如,SELECT CAST('{5D944516-98E6-44C5-849F-9C277833C01B}ssssssssss' as uniqueidentifier)SELECT CAST('5D944516-98E6-44C5-849F-9C277833C01BXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' as uniqueidentifier) 都成功了。

在大多数默认排序规则下,LIKE '[a-zA-Z0-9]' 最终会匹配 ÀË 等字符

最后,如果将结果中的行转换为 uniqueidentifier,将转换尝试放在 case 表达式中很重要,因为转换可能在行被 WHERE 过滤之前发生。

所以(借用@r0d30b0y's idea)一个更健壮的版本可能是

;WITH T(C)
     AS (SELECT '5D944516-98E6-44C5-849F-9C277833C01B'
         UNION ALL
         SELECT '{5D944516-98E6-44C5-849F-9C277833C01B}'
         UNION ALL
         SELECT '5D944516-98E6-44C5-849F-9C277833C01BXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
         UNION ALL
         SELECT '{5D944516-98E6-44C5-849F-9C277833C01B}ssssssssss'
         UNION ALL
         SELECT 'ÀD944516-98E6-44C5-849F-9C277833C01B'
         UNION ALL
         SELECT 'fish')
SELECT CASE
         WHEN C LIKE expression + '%'
               OR C LIKE '{' + expression + '}%' THEN CAST(C AS UNIQUEIDENTIFIER)
       END
FROM   T
       CROSS APPLY (SELECT REPLACE('00000000-0000-0000-0000-000000000000', '0', '[0-9a-fA-F]') COLLATE Latin1_General_BIN) C2(expression)
WHERE  C LIKE expression + '%'
        OR C LIKE '{' + expression + '}%' 

【讨论】:

  • 将此答案标记为已接受,因为 SQL Server 2012 很好地解决了我的原始问题。
  • 刚刚有一个时刻在 StackOverflow 上看到答案让我很开心。不知何故,我没有看到 TRY_CONVERT 存在。
  • 如果您不需要样式参数,还有TRY_CASTTRY_PARSE不支持uniqueidentifier所以不需要考虑。
  • 赞成 TRY_CONVERT。不知道有这么厉害。太糟糕了,我需要它的服务器是 SQL Server 2008。
【解决方案2】:

不是我的,是在网上找到的……我想分享一下。

SELECT 1 WHERE @StringToCompare LIKE 
       REPLACE('00000000-0000-0000-0000-000000000000', '0', '[0-9a-fA-F]');

【讨论】:

  • 不错,但是所有这些零都可能导致难以追查的错字:)。恕我直言,这是对您的想法的轻微改进,以确保空 UNIQUEIDENTIFIER 的格式正确:SELECT 1 WHERE @StringToCompare LIKE Replace(Cast(Cast(0 AS BINARY) AS UNIQUEIDENTIFIER), '0', '[0-9a-fA-F]');
  • 找不到 BigQuery SQL 版本,所以我想在这里分享我的。 SELECT 1 WHERE REGEXP_REPLACE(@StringToCompare, r'[0-9A-Fa-f]', '0') like '00000000-0000-0000-0000-000000000000'
  • 如果你想把它存储在一个变量DECLARE @IsGuid AS BIT = (SELECT TOP 1 CASE WHEN '61d086f0-80e3-482f-ab6a-7279ab18cc3d' LIKE Replace(Cast(Cast(0 AS BINARY) AS UNIQUEIDENTIFIER), '0', '[0-9a-fA-F]') THEN 1 ELSE 0 END)
【解决方案3】:
SELECT something 
  FROM table1 
 WHERE column1 LIKE '[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]';

更新:

...但我更喜欢@r0d30b0y 回答中的方法:

SELECT something 
  FROM table1 
 WHERE column1 LIKE REPLACE('00000000-0000-0000-0000-000000000000', '0', '[0-9a-fA-F]');

【讨论】:

  • 你可以把它变成一个函数,就像 pcofre 建议的那样:Create FUNCTION [dbo].[IsAGuid] (@Data varchar(50)) RETURNS bit WITH SCHEMABINDING AS BEGIN return case when @Data like '[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]' then 1 else 0 end END
【解决方案4】:

我不知道您可以使用“开箱即用”的任何内容 - 恐怕您必须自己编写。

如果可以:尝试在 C# 库中编写它并将其作为 SQL-CLR 程序集部署到 SQL Server 中 - 那么您可以使用 Guid.TryParse() 之类的东西,这肯定比 T-SQL 中的任何东西更容易使用....

【讨论】:

    【解决方案5】:

    r0d30b0y 答案的变体是使用 PATINDEX 在字符串中查找...

    PATINDEX('%'+REPLACE('00000000-0000-0000-0000-000000000000', '0', '[0-9a-fA-F]')+'%',@StringToCompare) > 0
    

    必须使用在 URL 字符串中查找 Guid..

    HTH

    戴夫

    【讨论】:

      【解决方案6】:

      喜欢保持简单。一个 GUID 有四个 - 甚至,如果只是一个字符串

      WHERE 列如 '%-%-%-%-%'

      【讨论】:

      • “我在校外种了 100-200 个勿忘我”是我最喜欢的 GUID
      【解决方案7】:

      虽然是较旧的帖子,但只是一个快速测试的想法......

      SELECT  [A].[INPUT],
              CAST([A].[INPUT] AS [UNIQUEIDENTIFIER])
      FROM   (
                  SELECT '5D944516-98E6-44C5-849F-9C277833C01B' Collate Latin1_General_100_BIN AS [INPUT]
                  UNION ALL
                  SELECT '{5D944516-98E6-44C5-849F-9C277833C01B}'
                  UNION ALL
                  SELECT '5D944516-98E6-44C5-849F-9C277833C01BXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
                  UNION ALL
                  SELECT '{5D944516-98E6-44C5-849F-9C277833C01B}ssssssssss'
                  UNION ALL
                  SELECT 'ÀD944516-98E6-44C5-849F-9C277833C01B'
                  UNION ALL
                  SELECT 'fish'
              ) [A]
      WHERE   PATINDEX('[^0-9A-F-{}]%', [A].[INPUT]) = 0
      

      【讨论】:

        【解决方案8】:

        这是一个基于一些早期 cmets 概念的函数。这个功能非常快。

        CREATE FUNCTION [dbo].[IsGuid] (@input varchar(50))  
            RETURNS bit AS  
        BEGIN
        
        RETURN 
            case when @input like '[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]'
            then 1 else 0 end
        END
        GO
        
        /* 
        Usage: 
        
        select [dbo].[IsGuid]('123') -- Returns 0
        select [dbo].[IsGuid]('ebd8aebd-7ea3-439d-a7bc-e009dee0eae0') -- Returns 1
        
        select * from SomeTable where dbo.IsGuid(TableField) = 0 -- Returns table with all non convertable items!
        
        */
        

        【讨论】:

          【解决方案9】:
          DECLARE @guid_string nvarchar(256) = 'ACE79678-61D1-46E6-93EC-893AD559CC78'
          
          SELECT
              CASE WHEN @guid_string LIKE '________-____-____-____-____________'
              THEN CONVERT(uniqueidentifier, @guid_string)
              ELSE NULL
          END
          

          【讨论】:

          • 请解释你的代码是做什么的以及它是怎么做的。
          • 嗨,它不检查字符是否对 UUID 有效,但它检查字符数适合 UUID 适合的位置...下划线是“任何字符”的通配符,所以使用它们的倍数,您可以指定字符串的长度。所以 LIKE 语句匹配 UUID 的模式。如果它不是 UUID 模式,那么它将返回 NULL。
          【解决方案10】:

          您可以编写自己的 UDF。这是避免使用 SQL-CLR 程序集的简单近似。

          CREATE FUNCTION dbo.isuniqueidentifier (@ui varchar(50))  
          RETURNS bit AS  
          BEGIN
          
          RETURN case when
              substring(@ui,9,1)='-' and
              substring(@ui,14,1)='-' and
              substring(@ui,19,1)='-' and
              substring(@ui,24,1)='-' and
              len(@ui) = 36 then 1 else 0 end
          
          END
          GO
          

          然后您可以对其进行改进以检查它是否只是 HEX 值。

          【讨论】:

          • 你的函数认为------------------------------------是一个唯一标识符;)
          • 您可以将此与 onedaywhen 的回答结合起来:Create FUNCTION [dbo].[IsAGuid] (@Data varchar(50)) RETURNS bit WITH SCHEMABINDING AS BEGIN return case when @Data like '[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]' then 1 else 0 end END
          【解决方案11】:

          我用:

          ISNULL(convert(nvarchar(50), userID), 'NULL') = 'NULL'
          

          【讨论】:

            【解决方案12】:

            我有一些使用 AutoFixture 生成的测试用户,它默认使用 GUID 生成字段。我需要删除的用户的名字字段是 GUID 或唯一标识符。这就是我最终来到这里的原因。

            我能够将你的一些答案拼凑成这个。

            SELECT UserId FROM [Membership].[UserInfo] Where TRY_CONVERT(uniqueidentifier, FirstName) is not null

            【讨论】:

              【解决方案13】:

              将 RLIKE 用于 MYSQL

              SELECT 1 WHERE @StringToCompare
              RLIKE REPLACE('00000000-0000-0000-0000-000000000000', '0', '[0-9a-fA-F]');
              

              【讨论】:

                【解决方案14】:

                在最简单的情况下。当您确定给定的字符串不能包含 4 个“-”符号时。

                SELECT * FROM City WHERE Name LIKE('%-%-%-%-%')
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2014-06-27
                  • 2010-10-13
                  • 2022-03-31
                  • 2013-05-12
                  • 2015-05-23
                  • 1970-01-01
                  相关资源
                  最近更新 更多