我有两个桌子Backup和Requests。
Backup
Requests
以下是两个表的脚本
后备
CREATE TABLE UserBackup( FileName varchar(70) NOT NULL, )
文件名由GUID表示。有时还有一些与文件有关的其他信息。因此,我们在表中输入了类似guid_ADD的条目。
要求
CREATE TABLE Requests( RequestId UNIQUEIDENTIFIER NOT NULL, Status int Not null )
以下是一些示例行:
UserBackup 表:
FileName 15b993cc-e8be-405d-bb9f-0c58b66dcdfe 4cffe724-3f68-4710-b785-30afde5d52f8 4cffe724-3f68-4710-b785-30afde5d52f8_Add 7ad22838-ddee-4043-8d1f-6656d2953545
请求 表:
RequestId Status 15b993cc-e8be-405d-bb9f-0c58b66dcdfe 1 4cffe724-3f68-4710-b785-30afde5d52f8 1 7ad22838-ddee-4043-8d1f-6656d2953545 2
我需要从userbackup表返回所有行,该表的名称(GUID)与表中的名称匹配RequestId,Requests并且状态为1。所以这是我编写的查询
RequestId
Select * from UserBackup inner join Requests on UserBackup.FileName = Requests.RequestId where Requests.Status = 1
而且这很好。它给我以下结果
FileName RequestId Status 15b993cc-e8be-405d-bb9f-0c58b66dcdfe 15b993cc-e8be-405d-bb9f-0c58b66dcdfe 1 4cffe724-3f68-4710-b785-30afde5d52f8 4cffe724-3f68-4710-b785-30afde5d52f8 1 4cffe724-3f68-4710-b785-30afde5d52f8_Add 4cffe724-3f68-4710-b785-30afde5d52f8 1
这正是我想要的。但是我不明白它是如何工作的。如果您注意到结果也返回4cffe724-3f68-4710-b785-30afde5d52f8_Add行。内部联接位于varchar和uniqueidentifier,并且此联接而不是像“等于”比较那样工作,而像“包含”比较那样工作。我想知道它是如何工作的,这样我就可以确保在没有任何意外情况的情况下使用此代码。
4cffe724-3f68-4710-b785-30afde5d52f8_Add
varchar
uniqueidentifier
当您比较不同数据类型的两列时,SQL Server将尝试以较低的优先级进行隐式转换。
以下来自MSDN文档: uniqueidentifier
下面的示例演示了当值对于要转换为的数据类型而言太长时,数据将被截断。因为uniqueidentifier类型限制为36个字符,所以超过该长度的字符将被截断。
DECLARE @ID nvarchar(max) = N'0E984725-C51C-4BF4-9960-E1C80E27ABA0wrong'; SELECT @ID, CONVERT(uniqueidentifier, @ID) AS TruncatedValue;
http://msdn.microsoft.com/en- us/library/ms187942.aspx
文档很清楚,数据被 截断了
每当您不确定自己的联接操作时,都可以进行验证Actual Execution Plan。
Actual Execution Plan
这是可以在SSMS或SQL Sentry Plan Explorer中运行的测试示例
DECLARE @userbackup TABLE ( _FILENAME VARCHAR(70) ) INSERT INTO @userbackup VALUES ( '15b993cc-e8be-405d-bb9f-0c58b66dcdfe' ), ( '4cffe724-3f68-4710-b785-30afde5d52f8' ), ( '4cffe724-3f68-4710-b785-30afde5d52f8_Add' ) , ( '7ad22838-ddee-4043-8d1f-6656d2953545' ) DECLARE @Requests TABLE ( requestID UNIQUEIDENTIFIER ,_Status INT ) INSERT INTO @Requests VALUES ( '15b993cc-e8be-405d-bb9f-0c58b66dcdfe', 1 ) , ( '4cffe724-3f68-4710-b785-30afde5d52f8', 1 ) , ( '7ad22838-ddee-4043-8d1f-6656d2953545', 2 ) SELECT * FROM @userbackup u JOIN @Requests r ON u.[_FILENAME] = r.requestID WHERE r.[_Status] = 1
而不是常规join操作SQL Server正在做HASH MATCH与EXPR 1006SSMS中很难看到什么做什么,但如果你打开XML文件,你会发现这个
join
HASH MATCH
EXPR 1006
<ColumnReference Column="Expr1006" /> <ScalarOperator ScalarString="CONVERT_IMPLICIT(uniqueidentifier,@userbackup.[_FILENAME] as [u].[_FILENAME],0)">
如有疑问,请检查执行计划,并在比较时始终确保匹配数据类型。