繁体   English   中英

为 SQL 插入生成 ID 的最佳方法是什么?

[英]What is the best way to generate an ID for a SQL Insert?

生成将在 INSERT 语句中立即使用的 ID 号的最佳、独立于 DBMS 的方法是什么,使 ID 大致按顺序排列?

DBMS 独立? 那是个问题。 两种最常见的方法是自动递增列和序列,大多数 DBMS 只做其中之一,但不会同时做这两个。 因此,独立于数据库的方法是拥有另一个表,其中一列具有您锁定的一个值,select,更新和解锁。

通常我会说“与 DBMS 无关”,并使用 PostgreSQL 中的序列或 MySQL 中的自动增量列来实现。 就我的目的而言,支持两者都比试图找出一种适用于任何地方的方法要好。

如果您可以使用您选择的编程语言创建全局唯一标识符(GUID) - 将其视为您的 id。

在进行故障排除时,它们更难使用(输入 INT 的where条件要容易得多),但也有一些优点。 通过在本地将 GUID 分配为您的键,您可以轻松地建立父子记录关系,而无需先将父项保存到数据库并检索 id。 并且由于 GUID,根据定义,是唯一的,您不必担心增加服务器上的密钥。

有自动递增或顺序

这有什么意义,这是你最不担心的?

您将如何处理 SQL 本身? MySQL 有限制,

SQL 服务器有顶,

Oracle 有等级

然后还有一百万个其他的东西,比如触发器、改变表语法等

是的,原始 SQL (以及我的偏好顺序)中的明显方法是 a) 序列 b) 自动增量字段。 更好、更现代、更独立于 DBMS 的方法是根本不碰 SQL,而是使用(好的)ORM。

没有通用的方法可以做到这一点。 如果有,每个人都会使用它。 SQL 根据定义厌恶这个想法 - 它是基于集合的逻辑的反模式(尽管在许多实际情况下很有用)。

您尝试从其他地方插入标识值的最大问题是,当 SQL 语句涉及多个记录时,必须同时生成多个值。

如果您需要它,请将其作为您的选择要求的一部分,以便数据库与您的应用程序一起使用。 任何严肃的 DBMS 产品都会提供自己的使用机制,并且很容易围绕 DML 中的差异进行编码。 变化几乎都在 DDL 中。

对于 DB 特定的解决方案,我总是使用 go,但如果你真的必须这样做的通常方法是实现你自己的序列。 您的 RDBMS 必须支持事务。

您创建一个包含 int 列的序列表并使用第一个数字作为种子,然后您的事务逻辑看起来像这样

begin transaction
update tblSeq set intID = intID + 1
select @myID = intID from tblSeq

inset into tblData (intID, ...) values (@myID, ...)
end transaction

事务强制写锁,这样下一个排队的插入不能在记录插入到 tblData 之前更新 tblSeq 值。 只要所有通过此事务插入 go ,那么您生成的 ID 就是按顺序生成的。

只有 SQL,以下可能是方法之一:

  1. 创建一个表以包含您需要的起始 id
  2. 首次部署应用程序时,应用程序应读取其上下文中的值。
  3. 此后,根据需要递增 id(以线程安全方式) 3.1 将 id 写入数据库(以线程安全方式)始终保持更新值 3.2 不要将其写入数据库,只需在 memory(线程- 安全的方式)
  4. 如果由于任何原因服务器出现故障,请将当前 id 值写入数据库
  5. 当服务器再次启动时,它将从上次离开的位置进行选择。

使用自动递增的 id 列。

他们真的有理由必须按顺序排列吗? 如果您只是将其用作 ID,那么您应该只能使用 UUID 的一部分或 md5(now()) 的前几个数字。

你可以花时间按摩它。 它相当于类似的东西

DateTime.Now.Ticks

所以它就像 YYYYMMDDHHMMSSSS

它可能有点横向方法,但一个好的 ORM 类型库可能至少能够隐藏差异。 For example, in Ruby there is ActiveRecord (commonly used in but not exclusively tied to the Ruby the Rails web framework) which has Migrations. 在与平台无关的代码中声明的表定义中,数据类型、顺序 id 生成和索引创建等实现细节被推到您的视野之下。

我在 SQLite 上透明地开发了一个模式,然后在 MS SQL 服务器上实现了它,后来移植到 Oracle。 无需更改生成我的架构定义的代码。

正如我所说,它可能不是您想要的,但封装变化的最简单方法是使用已经为您完成封装的库。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM