我们遇到的问题是,我们的Informix DB序列号列(SERIAL类型)已达到最大限制。 我们将其手动重新设置为" 1"每当我们遇到这个问题时。
有没有办法在不进行任何应用程序更改的情况下使用序列/循环来解决这个问题?
我们通过将值设为" 0"来插入数据。并且Informix会自动将其递增。
答案 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
以不同的方式检索。