admin

SQL Server:在uniqueidentifier上加入

sql

我有两个桌子BackupRequests

以下是两个表的脚本

后备

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)与表中的名称匹配RequestIdRequests并且状态为1。所以这是我编写的查询

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行。内部联接位于varcharuniqueidentifier,并且此联接而不是像“等于”比较那样工作,而像“包含”比较那样工作。我想知道它是如何工作的,这样我就可以确保在没有任何意外情况的情况下使用此代码。


阅读 197

收藏
2021-06-07

共1个答案

admin

当您比较不同数据类型的两列时,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

这是可以在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 MATCHEXPR 1006SSMS中很难看到什么做什么,但如果你打开XML文件,你会发现这个

<ColumnReference Column="Expr1006" />
<ScalarOperator ScalarString="CONVERT_IMPLICIT(uniqueidentifier,@userbackup.[_FILENAME] as [u].[_FILENAME],0)">

如有疑问,请检查执行计划,并在比较时始终确保匹配数据类型。

2021-06-07