【问题标题】:SERIAL-like INT columnSERIAL-like INT 列
【发布时间】:2011-03-29 21:25:25
【问题描述】:

我有一个应用程序,根据添加或更新的交易类型,票号可能会增加也可能不会增加。我不能将 SERIAL 数据类型用于票号,因为无论交易类型如何,它都会递增,因此我将票号定义为 INT。因此,在多用户环境中,如果用户 A 正在添加或更新交易并且用户 B 也在做同样的事情,我会测试 tran 类型,如果需要下一个票号,那么

LET ticket = (SELECT MAX(ticket) [WITH ADDLOCK or UPDLOCK?] FROM transactions) + 1

但是,这必须在行被提交或麻烦开始时准确地完成。你能想出更好的方法来做到这一点:Informix、Oracle、MySQL、SQL-Server、4Js/Genero 或其他 RDBMS?这是决定我将在哪个 RDBMS 中重写我的应用程序的主要因素之一。

【问题讨论】:

    标签: mysql sql-server database oracle informix


    【解决方案1】:

    这就是创建序列的目的,并且大多数数据库都支持它(MySQL 是唯一一个没有序列的数据库——尽管不能 100% 确定 Informix)

    任何依赖于 SELECT MAX(id) 反模式的算法要么在多用户环境中非常缓慢,要么在多用户环境中根本无法正常工作。

    如果您还需要支持 MySQL,我建议在每个数据库中使用“本机”“自动增量”类型(PostgreSQL 的串行,MySQL 的 auto_increment,SQL Server 的标识,Oracle 中的序列 + 触发器和以此类推)并让驱动返回生成的ID值

    在 JDBC 中有一个 getGeneratedKeys() 方法,我相信其他接口也有类似的东西。

    【讨论】:

      【解决方案2】:

      使用 Informix DBMS,SERIAL 列在插入后不会改变;实际上,您根本无法更新 SERIAL 值。您可以插入一个以 0 作为值的新值 - 在这种情况下会生成一个新值 - 或者您可以插入一些其他值。如果另一个值已经存在并且存在唯一约束,则将失败;如果它不存在,或者串行列上没有唯一约束,那么它将成功。如果插入的值大于先前插入的最大值,则下一个要插入的数字将再次大一。如果插入的数字较小或为负数,则对下一个数字没有影响。

      因此,您可以在不更改值的情况下进行更新 - 没问题。如果您需要更改数字,则必须执行删除和插入(或插入和删除),其中插入中包含零。如果您更喜欢一致性并使用事务,则始终可以删除,然后(重新)插入具有相同编号或零的行以触发新编号。这假设您有一种运行 SQL 的编程语言;我不认为您可以调整 ISQL 和 Perform 来自动执行此操作。

      所以,在这一点上,我在 Informix 上看不到问题。

      使用适当版本的 IDS(任何受支持的版本),您也可以使用 SEQUENCE 来控制插入的值。这是基于 Oracle 语法和概念的; DB2 也支持这一点。其他 DBMS 有其他等效(但不同)的机制来处理自动生成的数字。

      【讨论】:

      • PostgreSQL 有序列,从 7.x 开始也有 SERIAL,其作用类似于 MySQL 的 auto_increment 或 SQL Server 的 IDENTITY...
      【解决方案3】:

      从你的标签很难判断你使用的是什么数据库。

      对于 SQL Server(因为它已列出)我建议

      ticket_num = (SELECT MAX(ticket_number) FROM transactions with (updlock)) + 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-10
        • 2019-11-16
        • 2017-05-03
        • 2018-04-21
        • 2021-03-27
        • 2016-07-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多