如何检查VARCHAR字符串是否为(非)十六进制?

4

TL;DR 如何在选择行时测试字符串是否为十六进制?


如果我有一个包含GUID的表,其中一些是Base36而不是十六进制:

  ID | GUID
  ===|=================================
   1 | CAFEBABECAFED00DB16B00B515BADA55
   2 | 0123456789ABCDEFGHIJKLMNOPQRSTUV
   3 | DEADBEAF4D15EA5EDEFEC8EDFEE1DEAD

我希望获取所有GUID不是纯十六进制的行。

对于单个值,我可以尝试CONVERT(VARBINARY(32),[GUID],2)来查看是否失败,但我不能在查询中执行此操作。如果我可以查询WHERE isNaN(parseInt(GUID,16)),那么它将是无故障的(同时必须应用于所有行)。

当然,我可以全文搜索F后面的字母(WHERE [GUID] LIKE '%g%' OR [GUID] LIKE '%h%' OR …),但这种最后的手段导致我提出了这个问题:

如何查询仅包含(非)十六进制字段?

4个回答

5
;WITH rw AS
(
    SELECT '0000AF0012B' ishexornot
    UNION ALL
    SELECT '0000AF0012G'
    UNION ALL
    SELECT '0000AF0012 '
)
SELECT *, CASE WHEN ishexornot LIKE '%[^0-9A-F]%' THEN 0 ELSE 1 END
FROM rw

so

WHERE [GUID] LIKE '%[^0-9A-F]%'


使用CTE对实际想法有重要意义吗? - dakab
@dakab CTE在这里用于填充一些数据。 - Ivan Starostin

3

只需使用带通配符的LIKE来指定特定范围:

SELECT * FROM [GUIDs] WHERE [GUID] LIKE '%[g-z]%';

3

从SQL Server 2012开始,你可以使用TRY_CONVERT()函数:

declare @t table (
    Id int identity (1,1) primary key,
    Value varchar(100) not null
);

insert into @t (Value)
values
('F6AA1EE0-DF55-43E8-92ED-B2A84E621485'),
('F32E4621CE004C47889DEBDA9BA790AF'),
('09F94C95-9004-4C7C-8F5D-9CA374546288'),
('5DAFD4C7-C780-4F32-9BF1-52027371546A'),
('4D81BD419BFE42EA956E715023EF3B77');

select t.*
from @t t
where try_convert(uniqueidentifier, t.Value, 2) is null;

CONVERT() 不同的是,样例中的查询没有错误,并返回第 2 行和第 5 行。


这是SQL Server 2008 R2。然而,让我们假设问题与版本无关。你如何使用try_convert,它又有什么作用? - dakab
谢谢,现在它更加全面了。这个内置函数显然是为此目的而设计的。我只希望有一天能用到它。 - dakab

0
在Postgres中,您可以使用 POSIX正则表达式
select "GUID" ~ '[0-9A-F]{32}' as is_hex from the_table;

上面的代码检查字符串的长度是否为32。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接