什么是GUID? (What is a GUID?)
GUID is a 16 byte binary SQL Server data type that is globally unique across tables, databases, and servers. The term GUID stands for Globally Unique Identifier and it is used interchangeably with UNIQUEIDENTIFIER.
GUID是16字节的二进制SQL Server数据类型,在表,数据库和服务器之间全局唯一。 GUID代表全局唯一标识符,可与UNIQUEIDENTIFIER互换使用。
To create a GUID in SQL Server, the NEWID() function is used as shown below:
要在SQL Server中创建GUID,将使用NEWID()函数,如下所示:
SELECT NEWID()
Execute the above line of SQL multiple times and you will see a different value every time. This is because the NEWID() function generates a unique value whenever you execute it.
多次执行上面SQL行,您每次都会看到一个不同的值。 这是因为NEWID()函数每执行一次都会生成一个唯一值。
To declare a variable of type GUID, the keyword used is UNIQUEIDENTIFIER as mentioned in the script below:
要声明类型为GUID的变量,使用的关键字是UNIQUEIDENTIFIER,如以下脚本中所述:
DECLARE @UNI UNIQUEIDENTIFIER
SET @UNI = NEWID()
SELECT @UNI
As mentioned earlier, GUID values are unique across tables, databases, and servers. GUIDs can be considered as global primary keys. Local primary keys are used to uniquely identify records within a table. On the other hand, GUIDs can be used to uniquely identify records across tables, databases, and servers.
如前所述,GUID值在表,数据库和服务器之间是唯一的。 GUID可以视为全局主键。 本地主键用于唯一标识表中的记录。 另一方面,GUID可用于唯一地标识跨表,数据库和服务器的记录。
问题GUID解决了 (The Problem GUID Solves)
Let’s see what issues we face if we have redundant records within tables across different databases and how GUID solves these issues.
让我们看看如果我们在不同数据库的表中有冗余记录会遇到什么问题,以及GUID如何解决这些问题。
Execute the following script.
执行以下脚本。
CREATE DATABASE EngDB
GO
USE EngDB
GO
CREATE TABLE EnglishStudents
(
Id INT PRIMARY KEY IDENTITY,
StudentName VARCHAR (50)
)
GO
INSERT INTO EnglishStudents VALUES ('Shane')
INSERT INTO EnglishStudents VALUES ('Jonny')
In the script above, we create a database named “EngDB”. We then create a table “EnglishStudents” within this database. The table has two columns: Id and StudentName. The Id column is the primary key column and we set it to auto increment using Identity as the constraint. Finally, we insert two records for students called ‘Shane’ and ‘Jonny’ into the “EnglishStudents” table.
在上面的脚本中,我们创建一个名为“ EngDB”的数据库。 然后,我们在此数据库中创建一个表“ EnglishStudents”。 该表有两列:Id和StudentName。 Id列是主键列,我们使用Identity作为约束将其设置为自动递增。 最后,我们将两个名为“ Shane”和“ Jonny”的学生记录插入“ EnglishStudents”表中。
Now if you select all the records from the “EnglishStudents” table, you should see the following output:
现在,如果您从“ EnglishStudents”表中选择所有记录,您将看到以下输出:
Id | StudentName |
1 | Shane |
2 | Jonny |
ID | 学生姓名 |
1个 | 谢恩 |
2 | 强尼 |
Now, let’s create another database “MathDB”, create a table “MathStudents” in the DB and insert some records into the table. Execute the following script to do so.
现在,让我们创建另一个数据库“ MathDB”,在数据库中创建表“ MathStudents”,并将一些记录插入表中。 执行以下脚本。
CREATE DATABASE MathDB
GO
USE MathDB
GO
CREATE TABLE MathStudents
(
Id INT PRIMARY KEY IDENTITY,
StudentName VARCHAR (50)
)
GO
INSERT INTO MathStudents VALUES ('Sally')
INSERT INTO MathStudents VALUES ('Edward')
The MathStudents table of the MathDB should have the following records.
MathDB的MathStudents表应具有以下记录。
Id | StudentName |
1 | Sally |
2 | Edward |
ID | 学生姓名 |
1个 | 莎莉 |
2 | 爱德华 |
Now if you select all the records from the EnglishStudents table of the EngDB and MathStudents table of the MathDB, you will see that records from both tables will have the same values for the primary key columns Id. Execute the following script to see this result:
现在,如果您从EngDB的EnglishStudents表和MathDB的MathStudents表中选择所有记录,您将看到两个表中的记录将具有相同的主键列ID值。 执行以下脚本以查看此结果:
SELECT * FROM EngDB.dbo.EnglishStudents
SELECT * FROM MathDB.dbo.MathStudents
You will see the following output in SQL Server Management Studio
您将在SQL Server Management Studio中看到以下输出
The student records from different tables that exist in two different databases have the same value for the Id column. This is the default behavior of SQL Server.
来自两个不同数据库中不同表的学生记录的Id列具有相同的值。 这是SQL Server的默认行为。
Now let’s create a new table “Student” that contains the union of all the records from the MathStudents table and EnglishStudents table. Execute the following script:
现在,我们创建一个新表“ Student”,其中包含MathStudents表和EnglishStudents表中所有记录的并集。 执行以下脚本:
USE EngDB
GO
CREATE TABLE Students
(
Id INT PRIMARY KEY,
StudentName NVARCHAR (50)
)
GO
INSERT INTO Students
SELECT * FROM EngDB.dbo.EnglishStudents
UNION ALL
SELECT * FROM MathDB.dbo.MathStudents
In the above script, we create a new table “Students” in the EngDB. This table contains Id and StudentName columns.
在上面的脚本中,我们在EngDB中创建一个新表“ Students”。 该表包含Id和StudentName列。
If you try to run the above script, you will see an error:
如果尝试运行上述脚本,则会看到错误:

This error is due to both the MathStudents and EnglishStudents table having the same values for the Id column which is also the primary key column for the newly created Students table. Therefore, when we try to insert the union of the records from MathStudents and EnglishStudents tables, the “Violation of PRIMARY KEY constraint” error occurs. Execute the following script to see what we are actually trying to insert in the Students table.
此错误是由于MathStudents和EnglishStudents表的Id列(也是新创建的Students表的主键列)具有相同的值。 因此,当我们尝试从MathStudents和EnglishStudents表中插入记录的并集时,会发生“违反PRIMARY KEY约束”错误。 执行以下脚本,以查看我们实际尝试在“学生”表中插入的内容。
SELECT * FROM EngDB.dbo.EnglishStudents
UNION ALL
SELECT * FROM MathDB.dbo.MathStudents
However, what if we want records to have unique values across multiple databases? For instance, we want that the Id column of the EnglishStudents table and the MathStudents table to have unique values, even if they belong to different databases. This is when we need to use the GUID data type.
但是,如果我们希望记录在多个数据库中具有唯一值怎么办? 例如,我们希望EnglishStudents表和MathStudents表的Id列具有唯一的值,即使它们属于不同的数据库也是如此。 这是我们需要使用GUID数据类型的时候。
You can see that students Shane and Sally both have Ids of 1 while Jonny and Edward both have Ids of 2. This causes the violation of primary key constraint for the Students table.
您会看到学生Shane和Sally的ID均为1,而Jonny和Edward的ID均为2。这导致违反了Student表的主键约束。
GUID解决方案 (Solution with GUID)
Now, let’s see how GUID can be used to solve this issue
现在,让我们看看如何使用GUID解决此问题
Let’s create a table EngStudents1 within the EngDB but this time we change the data type of the Id column from INT to UNIQUEIDENTIFIER. To set a default value for the column we will use the default keyword and set the default value as the value returned by the ‘NEWID()’ function.
让我们在EngDB中创建一个表EngStudents1,但是这次我们将Id列的数据类型从INT更改为UNIQUEIDENTIFIER。 要为该列设置默认值,我们将使用default关键字,并将默认值设置为'NEWID()'函数返回的值。
This will ensure that whenever a new record is inserted in the EngStudents1 table, by default, the NEWID() function generates a unique value for the Id column. When inserting the records, we simply have to specify “default” as value for the first column. This will insert a default unique value to the Id column. Execute the following script to create EngStudents1 table:
这将确保每当在EngStudents1表中插入新记录时,默认情况下,NEWID()函数都会为Id列生成唯一值。 插入记录时,我们只需指定“默认”作为第一列的值。 这会将默认唯一值插入Id列。 执行以下脚本来创建EngStudents1表:
USE EngDB
GO
CREATE TABLE EnglishStudents1
(
Id UNIQUEIDENTIFIER PRIMARY KEY default NEWID(),
StudentName VARCHAR (50)
)
GO
INSERT INTO EnglishStudents1 VALUES (default,'Shane')
INSERT INTO EnglishStudents1 VALUES (default,'Jonny')
Now if you select all the records from EnglishStudents1 table, you will a result that looks like this:
现在,如果您从EnglishStudents1表中选择所有记录,则结果将如下所示:
Id | StudentName |
4B900A74-E2D9-4837-B9A4-9E828752716E | Jonny |
AEDC617C-D035-4213-B55A-DAE5CDFCA366 | Shane |
ID | 学生姓名 |
4B900A74-E2D9-4837-B9A4-9E828752716E | 强尼 |
AEDC617C-D035-4213-B55A-DAE5CDFCA366 | 谢恩 |
Note: Your values for the Id column will be different from the ones shown in the above table, because they are generated randomly on the fly. However, they should be globally unique.
注意: “ Id”列的值将不同于上表中显示的值,因为它们是即时生成的。 但是,它们应该是全局唯一的。
In the same way, create another table MathStudents1 in the MathDB database. Execute the following script:
以相同的方式,在MathDB数据库中创建另一个表MathStudents1。 执行以下脚本:
USE MathDB
GO
CREATE TABLE MathStudents1
(
Id UNIQUEIDENTIFIER PRIMARY KEY default NEWID(),
StudentName VARCHAR (50)
)
GO
INSERT INTO MathStudents1 VALUES (default,'Sally')
INSERT INTO MathStudents1 VALUES (default,'Edward')
Again if you try to retrieve all the records from the MathStudents1 table of the MathDB database, you will see results similar to the one below:
再次,如果您尝试从MathDB数据库的MathStudents1表中检索所有记录,您将看到类似于以下结果:
Id | StudentName |
69121893-3AFC-4F92-85F3-40BB5E7C7E29 | Sally |
CB77CCE6-C2CB-471B-BDD4-5DAC8C93B756 | Edward |
ID | 学生姓名 |
69121893-3AFC-4F92-85F3-40BB5E7C7E29 | 莎莉 |
CB77CCE6-C2CB-471B-BDD4-5DAC8C93B756 | 爱德华 |
Now we have globally unique values in the Id columns of both the EnglishStudents1 and MathStudents1 table. Let’s create a new Table named Student1s and just as we did before, try to insert the union of the records from EnglishStudents1 and MathStudents1. This time we will see that there will be no “Violation of PRIMARY KEY constraint” error, since the values in the Id column of both EnglishStudents1 and MathStudents1 are unique across both the EngDB and MathDB databases.
现在,我们在EnglishStudents1和MathStudents1表的Id列中具有全局唯一值。 让我们创建一个名为Student1s的新表,就像以前一样,尝试插入EnglishStudents1和MathStudents1中记录的并集。 这次,我们将看到不会出现“违反PRIMARY KEY约束”错误,因为EnglishStudents1和MathStudents1的Id列中的值在EngDB和MathDB数据库中都是唯一的。
USE EngDB
GO
CREATE TABLE Students1
(
Id UNIQUEIDENTIFIER PRIMARY KEY,
StudentName NVARCHAR (50)
)
GO
INSERT INTO Students1
SELECT * FROM EngDB.dbo.EnglishStudents1
UNION ALL
SELECT * FROM MathDB.dbo.MathStudents1
You can see in the above script that the type of the Id column is UNIQUEIDENTIFIER. Run the above script and then try to retrieve all the records from the Students1 table and you should see results similar to the following:
您可以在上面的脚本中看到,Id列的类型为UNIQUEIDENTIFIER。 运行上面的脚本,然后尝试从Students1表中检索所有记录,您应该看到与以下内容类似的结果:
Id | StudentName |
69121893-3AFC-4F92-85F3-40BB5E7C7E29 | Sally |
CB77CCE6-C2CB-471B-BDD4-5DAC8C93B756 | Edward |
4B900A74-E2D9-4837-B9A4-9E828752716E | Jonny |
AEDC617C-D035-4213-B55A-DAE5CDFCA366 | Shane |
ID | 学生姓名 |
69121893-3AFC-4F92-85F3-40BB5E7C7E29 | 莎莉 |
CB77CCE6-C2CB-471B-BDD4-5DAC8C93B756 | 爱德华 |
4B900A74-E2D9-4837-B9A4-9E828752716E | 强尼 |
AEDC617C-D035-4213-B55A-DAE5CDFCA366 | 谢恩 |
You can see that using GUID, we are able to insert a union of records from two different databases into a new table without any “Violation of PRIMARY KEY constraint” error.
您可以看到,使用GUID,我们可以将两个不同数据库中的记录并集插入到新表中,而不会出现“违反PRIMARY KEY约束”错误。
参考资料 (References)
- Using UNIQUEIDENTIFIER 使用UNIQUEIDENTIFIER
- Video on GUID and UNIQUEIDENTIFIER 有关GUID和UNIQUEIDENTIFIER的视频
- GUID vs INT Debate GUID与INT辩论
本的其他精彩文章 (Other great articles from Ben)
Difference between Identity & Sequence in SQL Server |
What is the difference between Clustered and Non-Clustered Indexes in SQL Server? |
Understanding the GUID data type in SQL Server |
SQL Server中身份和序列之间的区别 |
SQL Server中的聚集索引和非聚集索引有什么区别? |
了解SQL Server中的GUID数据类型 |
翻译自: https://www.sqlshack.com/understanding-the-guid-data-type-in-sql-server/