sql - 带有错误 GUID 的 Transact-SQL Select 语句结果
问题描述
我们有一个带有 GUID 主键的表。当我搜索一个特定的键时,我可以使用:
SELECT * FROM products WHERE productID='34594289-16B9-4EEF-9A1E-B35066531DE6'
SELECT * FROM products WHERE productID LIKE '34594289-16B9-4EEF-9A1E-B35066531DE6'
结果(两者):
product_ID Prd_Model
------------------------------------ --------------------------------------------------
34594289-16B9-4EEF-9A1E-B35066531DE6 LW-100
(1 row affected)
我们有一个客户使用我们的 ID,但添加了更多文本以在他们自己的系统中创建某种复合字段。他们向我发送了其中一个值进行查找,我得到了意想不到的结果。我打算修剪后缀但忘记了,所以我运行了这个:
SELECT * FROM products WHERE productID='34594289-16B9-4EEF-9A1E-B35066531DE6_GBR_USD'
当我运行它时,我意外地得到了相同的结果:
product_ID Prd_Model
------------------------------------ --------------------------------------------------
34594289-16B9-4EEF-9A1E-B35066531DE6 LW-062
(1 row affected)
现在,如果我在搜索时从 GUID 末尾修剪一个值,我什么也得不到(GUID 短 1 位):
SELECT * FROM products WHERE productID='34594289-16B9-4EEF-9A1E-B35066531DE'
结果:
product_ID Prd_Model
------------------------------------ --------------------------------------------------
(0 rows affected)
当使用 LIKE 命令而不是 '=' 并且如果我将后缀添加到末尾时,该语句将返回零结果。这是我所期望的。
那么为什么在语句中使用'='时,末尾添加后缀的较长字符串会返回结果?它显然忽略了 36 个字符的 GUID 长度之外的任何内容,但我不知道为什么。
解决方案
这种行为记录在案:
转换 uniqueidentifier 数据
为了从字符表达式转换的目的,uniqueidentifier 类型被视为字符类型,因此受制于转换为字符类型的截断规则。也就是说,当字符表达式转换为不同大小的字符数据类型时,对于新数据类型来说太长的值将被截断。请参阅示例部分。
因此,字符串值在被隐式转换(由于数据类型优先级)为 a时'34594289-16B9-4EEF-9A1E-B35066531DE6_GBR_USD'
被截断,并且不出所料地等于自身,因此返回该行。'34594289-16B9-4EEF-9A1E-B35066531DE6'
uniqueidentifier
'34594289-16B9-4EEF-9A1E-B35066531DE6'
文档确实举了一个例子:
以下示例演示了当值对于要转换的数据类型而言太长时截断数据。因为 uniqueidentifier 类型限制为 36 个字符,所以超过该长度的字符将被截断。
DECLARE @ID NVARCHAR(max) = N'0E984725-C51C-4BF4-9960-E1C80E27ABA0wrong'; SELECT @ID, CONVERT(uniqueidentifier, @ID) AS TruncatedValue;
这是结果集。
String TruncatedValue -------------------------------------------- ------------------------------------ 0E984725-C51C-4BF4-9960-E1C80E27ABA0wrong 0E984725-C51C-4BF4-9960-E1C80E27ABA0
但是,我觉得你说下面的语句不返回任何行很奇怪:
SELECT *
FROM products
WHERE productID='34594289-16B9-4EEF-9A1E-B35066531DE'
虽然是真的,但它不会返回行,它也会出错:
从字符串转换为唯一标识符时转换失败。
它并不意味着您的专栏不是一个事实,这意味着uniqueidentifier
您的第一个陈述不正确;因为较长的字符串不会被截断。这意味着问题中的其中一个陈述可能是错误的;要么你的列是a uniqueidentifier
,因此你得到结果,但在后者中得到一个错误,或者它不是,两个语句都不会返回结果集。正如您在此演示中看到的:
CREATE TABLE dbo.YourTable (UID uniqueidentifier, String varchar(36));
INSERT INTO dbo.YourTable (UID,String)
VALUES('34594289-16B9-4EEF-9A1E-B35066531DE6','34594289-16B9-4EEF-9A1E-B35066531DE6');
GO
--Returns data
SELECT *
FROM dbo.YourTable
WHERE UID = '34594289-16B9-4EEF-9A1E-B35066531DE6_GBR_USD'
GO
--Errors
SELECT *
FROM dbo.YourTable
WHERE UID = '34594289-16B9-4EEF-9A1E-B35066531DE';
GO
--Returns no data
SELECT *
FROM dbo.YourTable
WHERE String = '34594289-16B9-4EEF-9A1E-B35066531DE6_GBR_USD'
GO
--Returns no data
SELECT *
FROM dbo.YourTable
WHERE String = '34594289-16B9-4EEF-9A1E-B35066531DE'
GO
DROP TABLE dbo.YourTable;
推荐阅读
- javascript - 在 Cypress 中重试命令失败后的选项
- c++ - 在 C++ 中删除字符串中非字母的所有字符
- stanford-nlp - 斯坦福 CoreNLP 能否在给定自定义 POS 的情况下对单词进行词形还原?
- angular - 模板更新不会在测试中发生
- java - 如何使用 java 从 gcp 存储桶下载文件夹?
- php - 如何在主目录而不是ubuntu的子目录中安装wordpress?
- angular - Auth0 与 NGRX 的集成
- django - 从 Django 中的其他 save() 方法继承时表单 save() 方法中的冲突
- reactjs - 在 reactjs 应用程序中使用 youtube 数据 api 时出现 Gapi 错误
- scala - Kafka 消费者不会间歇性地轮询记录