使用 SQL Server 的 uniqueidentifier 字段类型

SQL Server 自 2008 版起引入了 uniqueidentifier 字段,它存储的是一个 UUID, 或者叫 GUID,内部存储为 16 个字节。SQL Server 可用两个函数来生成 uniqueidentifier, 分别是 NEWID() 和 NEWSEQUENTIALID(), 后者只能用作字段的默认值。Java 也有一个 UUID 工具类 java.uti.UUID, UUID.randomUUID().toString() 生成一个随机的 UUID 字符串,在 java.util.UUID 也是用两个 long 字段表示内部状态。

SQL Server 的 uniqueidentifier 类型字段表明了内部如何存储,在我们操作它时,它的外在表现形式都是一个固定格式 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 的字符串,不区分大小写的。

本文所使用的 SQL Server 是 2017 版,通过 Docker 来启动的

docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=yourStrong(!)Password' -p 1433:1433 -d microsoft/mssql-server-linux:2017-latest

然后我们创建一个带有 uniqueidentifier 类型字段的表

默认值也可以指定为 NEWSEQUENTIALID(), uniqueidentifier 字段不指定默认值也没问题。上面把 id 设置为主键,接下为了验证大小写的问题。

关于 NEWID() 与 NEWSEQUENTIALID() 的一个显著区别是

SELECT NEWID();        --这句是合法的
SELECT NEWSEQUENTIALID();    -- 这条语句出错,提示该函数只能用作创建表时 uniquidentifier 类型字段的默认值

用 SQL 语句插入

第三条语句在第二条 id 的小写形式,破坏了唯一性约束,因为大小写字符串只是一种外面表现形式,第四条语句把第一个字母改成了 X 后,它实际不是一个有效的 GUID。

所以往数据库表中插入或更新 uniqueidentifier 字段时,相当于把字符用 java.uti.UUID.fromString("your-input") 转换输入为 UUID 对象

  • 如果不能转换为 UUID 对象,操作失败
  • 转换后的 UUID  对象再看是否违反了唯一性约束,因此输入字符的大小写不敏感

查询 uniqueidentifier 字段

展示为字符串,因为大小写不敏感,所以下面的条件查询

select * from customers where id='a972c577-dfb0-064e-1189-0154c99310daac12'

也可以查出 name 为 "World" 的记录,由于 SQL Server 是把该字符串转换为 UUID 来比较的,因此与输入的外在形式无关。

JDBC 操作 uniqueidentifier 字段

也是把它当作字符串来看待,rs.getString(..), pstmt.setString(index, "<UUID-STRING>"),只是这个字符串必须是一个符合规格的 UUID。

执行后插入一条新记录,并查询显示出所有的记录

A972C577-DFB0-064E-1189-0154C99310DA=>World
4A69AA7E-2136-48B2-951C-3EC52942534D=>From JDBC
2F7EB3C8-F4E3-4ECF-9727-B2898CC70F75=>Hello

还有一个小发现就是,查询显示出来的结果与插入的顺序是不一致的。

pstmt.setObject(1, UUID.randomUUID())

也没问题,上面最终也是会调用 UUID.randomUUID().toString() 方法,说到底 SQL Server 在插入该字段数据之前收到的还是一个字符串。

SQL Server JDBC 驱动的 PreparedStatement 实现类是 SQLServerPreparedStatement, 它有 setUniqueIdentifier(...) 方法,不过仍然是接收字符串,与 setString(...) 没什么不同。

总之 SQL Server 的 uniqueidentifier 字段是内部存储 16 字节,外部表现为字符串的类型,操作是接受的字符串必须是一个合法的 GUID(UUID) 串就行。

链接:

  1. uniqueidentifier (Transact-SQL)

类别: Database, Java/JEE. 标签: , . 阅读(140). 订阅评论. TrackBack.

Leave a Reply

avatar