我有一个应用程序,根据所添加或更新的交易类型,票号可能会增加也可能不会增加。我不能将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的一个主要因素。
答案 0 :(得分:2)
使用Informix DBMS,SERIAL列在插入后不会改变;实际上,您根本无法更新SERIAL值。您可以插入一个新值,其中0为值 - 在这种情况下会生成新值 - 或者您可以插入一些其他值。如果另一个值已经存在并且存在唯一约束,那么将失败;如果它不存在,或者串行列上没有唯一约束,那么它将成功。如果插入的值大于先前插入的最大值,则要插入的下一个数字将再次变大。如果插入的数字较小或为负数,则对下一个数字没有影响。
因此,您可以在不更改值的情况下进行更新 - 没问题。如果需要更改数字,则必须执行删除并插入(或插入和删除),其中插入的内容为零。如果您更喜欢一致性并且使用事务,则可以始终删除,然后(重新)插入具有相同数字或零的行以触发新数字。假设你有一个运行SQL的编程语言;我不认为你可以调整ISQL和Perform来自动完成。
所以,在这一点上,我没有看到Informix上的问题。
使用适当版本的IDS(支持的任何内容),您也可以使用SEQUENCE来控制插入的值。这基于Oracle语法和概念; DB2也支持这一点。其他DBMS具有其他等效(但不同)的机制来处理自动生成的数字。
答案 1 :(得分:1)
从您的代码中,很难说出您正在使用的数据库。
对于SQL Server(因为它已列出)我建议
ticket_num = (SELECT MAX(ticket_number) FROM transactions with (updlock)) + 1
答案 2 :(得分:1)
这就是为大多数数据库创建的序列和大多数数据库所支持的序列(MySQL是唯一没有序列的 - 不是100%肯定Informix)
任何依赖于 SELECT MAX(id)反模式的算法在多用户环境中要么死得慢,要么在多用户环境中无法正常工作。
如果您还需要支持MySQL,我建议在每个数据库中使用“本机”“自动增量”类型(PostgreSQL的串行,MySQL的auto_increment,SQL Server的标识,Oracle中的序列+触发器)等等)让驱动程序返回生成的ID值
在JDBC中有一个getGeneratedKeys()方法,我确信其他接口也有类似的东西。