我们如何在Informix中为SERIAL类型的列循环序列号?

时间:2017-03-09 22:25:25

标签: informix

我们遇到的问题是,我们的Informix DB序列号列(SERIAL类型)已达到最大限制。 我们将其手动重新设置为" 1"每当我们遇到这个问题时。

有没有办法在不进行任何应用程序更改的情况下使用序列/循环来解决这个问题?

我们通过将值设为" 0"来插入数据。并且Informix会自动将其递增。

2 个答案:

答案 0 :(得分:1)

您可以通过插入一个显式数字为2,147,483,647(2 31 -1)的行来回收SERIAL列,然后插入另一行数字为0.这将重置计数器到1,但后续尝试插入新的序列号(插入值为0)可能会与预先存在的行发生冲突,然后INSERT将失败(但下一次尝试将使用下一个序列号)。

示例:

SQL[2416]: CREATE TABLE serial_wraparound
         > (
         >     number SERIAL NOT NULL PRIMARY KEY,
         >     name VARCHAR(20) NOT NULL UNIQUE
         > );
SQL[2417]: INSERT INTO serial_wraparound(number, name) VALUES(0, "The first");
SQL[2418]: INSERT INTO serial_wraparound(number, name) VALUES(0, "The second");
SQL[2419]: SELECT * FROM serial_wraparound;
1|The first
2|The second
SQL[2420]: INSERT INTO serial_wraparound(number, name) VALUES(2147483647, "The last");
SQL[2421]: SELECT * FROM serial_wraparound;
1|The first
2|The second
2147483647|The last
SQL[2422]: INSERT INTO serial_wraparound(number, name) VALUES(0, "Recycling");
SQL -268: Unique constraint (jleffler.u162_426) violated.
ISAM -100: ISAM error:  duplicate value for a record with unique key.
SQLSTATE: 23000 at /dev/stdin:8
SQL[2423]: INSERT INTO serial_wraparound(number, name) VALUES(0, "Recycling");
SQL -268: Unique constraint (jleffler.u162_426) violated.
ISAM -100: ISAM error:  duplicate value for a record with unique key.
SQLSTATE: 23000 at /dev/stdin:9
SQL[2424]: INSERT INTO serial_wraparound(number, name) VALUES(0, "Recycling");
SQL[2425]: SELECT * FROM serial_wraparound;
1|The first
2|The second
2147483647|The last
3|Recycling
SQL[2426]: 

类似的行为适用于SERIAL8和BIGSERIAL列,但环绕值为9,223,372,036,854,775,807(2 63 -1)。如果您反复耗尽20亿个序列号,也许您应该考虑更新您的应用程序以使用BIGSERIAL,这样您就可以使用最多9个数字的数字。从长远来看,它可能更简单。 (不要使用SERIAL8(或INT8);我提到它是为了完整性。新代码应该使用BIGSERIAL和BIGINT。是的,有原因。)

(命令解释器是我的SQLCMD - 可从国际Informix用户组的软件存储库的ESQL / C部分获得,IIUG。)

您还可以使用ALTER TABLE更改列中的值,但请注意,如果您未在ALTER TABLE中重新指定主键属性,则主键属性会丢失。这是一个单一的陈述序列(如果您真的很好奇,则为2455):

+ DROP TABLE IF EXISTS serial_wraparound;
+ CREATE TABLE serial_wraparound (number SERIAL NOT NULL PRIMARY KEY, NAME VARCHAR(20) NOT NULL UNIQUE);
+ trace off;
+ INFO INDEXES FOR serial_wraparound 
P|jleffler|u171_494|jleffler| 171_494|number|||||||||||||||
U|jleffler|u171_495|jleffler| 171_495|name|||||||||||||||
+ INSERT INTO serial_wraparound(number, NAME) VALUES(0, "The first");
+ INSERT INTO serial_wraparound(number, NAME) VALUES(0, "The second");
+ SELECT * FROM serial_wraparound;
1|The first
2|The second
+ ALTER TABLE serial_wraparound MODIFY(number SERIAL(248761) NOT NULL PRIMARY KEY);
+ trace off;
+ INFO INDEXES FOR serial_wraparound 
P|jleffler|u171_498|jleffler| 171_494|number|||||||||||||||
U|jleffler|u171_495|jleffler| 171_495|name|||||||||||||||
+ continue on;
+ INSERT INTO serial_wraparound VALUES(0, "The modified");
+ INSERT INTO serial_wraparound VALUES(0, "The petrified");
+ SELECT * FROM serial_wraparound;
1|The first
2|The second
248761|The modified
248762|The petrified
+ ALTER TABLE serial_wraparound MODIFY(number SERIAL(2147483647) NOT NULL PRIMARY KEY);
+ trace off;
+ INFO INDEXES FOR serial_wraparound 
P|jleffler|u171_500|jleffler| 171_494|number|||||||||||||||
U|jleffler|u171_495|jleffler| 171_495|name|||||||||||||||
+ INSERT INTO serial_wraparound VALUES(0, "The inconsequential");
+ INSERT INTO serial_wraparound VALUES(0, "The ungainly");
SQL -268: Unique constraint (jleffler.u171_500) violated.
ISAM -100: ISAM error:  duplicate value for a record with unique key.
SQLSTATE: 23000 at <<temp>>:27
+ SELECT * FROM serial_wraparound;
1|The first
2|The second
248761|The modified
248762|The petrified
2147483647|The inconsequential
+ INSERT INTO serial_wraparound VALUES(0, "The insubordinate");
SQL -268: Unique constraint (jleffler.u171_500) violated.
ISAM -100: ISAM error:  duplicate value for a record with unique key.
SQLSTATE: 23000 at <<temp>>:29
+ SELECT * FROM serial_wraparound;
1|The first
2|The second
248761|The modified
248762|The petrified
2147483647|The inconsequential
+ INSERT INTO serial_wraparound VALUES(0, "The piscatorial");
+ SELECT * FROM serial_wraparound;
1|The first
2|The second
248761|The modified
248762|The petrified
2147483647|The inconsequential
3|The piscatorial
+ INSERT INTO serial_wraparound VALUES(0, "The equatorial");
+ SELECT * FROM serial_wraparound;
1|The first
2|The second
248761|The modified
248762|The petrified
2147483647|The inconsequential
3|The piscatorial
4|The equatorial

这表明ALTER TABLE可用于设置下一个值 - 首先使用248,761(任意,即使不是随机),然后再次使用2,147,483,647。你不能减少数字,这就是你必须使用2 31 -1技巧的原因。

INFO INDEXES语句用于确保保留主键约束 - 一些中间版本丢失了主键(唯一性)约束,从而得到了我想要的不同结果。 trace on(和off)命令将命令回显关闭;你不想知道INFO INDEXES经历的卷积(或者你可以通过自己获得SQLCMD来找到它)。它是由SQLCMD(和DB-Access)管理的语句; Informix服务器本身并不了解它。在这方面,它类似于OUTPUT和LOAD以及UNLOAD等。

答案 1 :(得分:0)

将列类型更改为bigserial,这是一种64位自动增量类型,适合应用程序的long数据类型,而无需进行更改。

正如@JonathanLeffler所指出的,如果您的应用程序检索到生成的最后一个序列,您将不得不更改该代码,因为最后添加的bigserial以不同的方式检索。