【发布时间】:2009-02-24 17:47:47
【问题描述】:
生成将在 INSERT 语句中立即使用的 ID 号的最佳、独立于 DBMS 的方法是什么,同时保持 ID 大致按顺序排列?
【问题讨论】:
标签: sql rdbms-agnostic
生成将在 INSERT 语句中立即使用的 ID 号的最佳、独立于 DBMS 的方法是什么,同时保持 ID 大致按顺序排列?
【问题讨论】:
标签: sql rdbms-agnostic
独立于 DBMS?那是个问题。最常见的两种方法是自动递增列和序列,大多数 DBMS 只做其中一种,但不会同时做这两种方法。因此,与数据库无关的方法是让另一个表的一列具有一个值,您可以锁定、选择、更新和解锁。
通常我会说“与 DBMS 无关”,并使用 PostgreSQL 中的序列或 MySQL 中的自动增量列来实现。就我的目的而言,同时支持这两种方法总比试图找出一种适用于任何地方的方法要好。
【讨论】:
如果您可以使用您选择的编程语言创建Globally Unique Identifier (GUID) - 将其视为您的 id。
在进行故障排除时,它们更难使用(输入 INT 的where 条件要容易得多),但也有一些优点。通过在本地将 GUID 分配为您的键,您可以轻松地建立父子记录关系,而无需先将父级保存到数据库并检索 id。而且由于 GUID,根据定义,是唯一的,您不必担心增加服务器上的密钥。
【讨论】:
有自动递增或顺序
这是什么意思,这是您最不担心的事情?
您将如何处理 SQL 本身? MySQL 有限制,
SQL Server 有顶,
Oracle 有排名
还有一百万个其他的东西,比如触发器、改变表语法等等
【讨论】:
是的,原始 SQL 中的明显方式(以及我的偏好顺序)是 a) 序列 b) 自增字段。更好、更现代、更独立于 DBMS 的方法是根本不接触 SQL,而是使用(好的)ORM。
【讨论】:
没有通用的方法来做到这一点。如果有,每个人都会使用它。从定义上讲,SQL 厌恶这个想法 - 它是基于集合的逻辑的一种反模式(尽管在许多实际案例中很有用)。
您尝试从其他地方插入标识值的最大问题是当 SQL 语句涉及多条记录时,必须同时生成多个值。
如果您需要它,请将其作为数据库选择要求的一部分,以便与您的应用程序一起使用。任何严肃的 DBMS 产品都会提供自己的使用机制,并且很容易围绕 DML 中的差异进行编码。变化几乎都在 DDL 中。
【讨论】:
我总是选择特定于数据库的解决方案,但如果你真的有这样做,通常的方法是实现你自己的序列。您的 RDBMS 必须支持事务。
您创建一个包含 int 列的序列表并使用第一个数字作为种子,然后您的事务逻辑看起来像这样
开始交易 更新 tblSeq 设置 intID = intID + 1 从 tblSeq 中选择 @myID = intID 插入 tblData (intID, ...) 值 (@myID, ...) 结束交易事务强制写入锁,这样下一个排队的插入不能在记录插入到 tblData 之前更新 tblSeq 值。只要所有插入都通过此事务,那么您生成的 ID 就是按顺序生成的。
【讨论】:
使用自动递增的 id 列。
【讨论】:
真的有理由让它们按顺序排列吗?如果您只是将其用作 ID,那么您应该只能使用 UUID 的一部分或 md5(now()) 的前几个数字。
【讨论】:
你可以花点时间按摩一下。相当于
DateTime.Now.Ticks
所以应该是 YYYYMMDDHHMMSSSS
【讨论】:
它可能有点横向方法,但一个好的 ORM 类型库可能至少能够隐藏差异。例如,在 Ruby 中有 ActiveRecord(通常用于但不完全与 Ruby the Rails Web 框架相关联),它具有迁移功能。在与平台无关的代码中声明的表定义中,数据类型、顺序 id 生成和索引创建等实现细节被推到您的视野之下。
我已经在 SQLite 上透明地开发了一个模式,然后在 MS SQL Server 上实现了它,后来移植到了 Oracle。无需更改生成我的架构定义的代码。
正如我所说,它可能不是您想要的,但封装变化的最简单方法是使用已经为您完成封装的库。
【讨论】:
仅使用 SQL,以下可能是其中一种方法:
【讨论】: