GBase 8a 自增列踩坑记录
在 GBase 8a 里用自增列,如果直接从 MySQL 那套习惯带过来,大概率会在某个插入语句上报错。我就是在线上往一个带自增主键的表里插数据的时候,习惯性地写了列名和值,直接炸了。
后来翻文档才搞清楚,GBase 8a 对自增列的限制比 MySQL 严得多。
建表的时候指定自增列,语法上跟 MySQL 没什么区别。一个表只能有一个自增列,类型支持 tinyint、smallint、int、bigint,这个倒还好。
CREATE TABLE t1 ( name VARCHAR(10), id INT NOT NULL PRIMARY KEY AUTO_INCREMENT );
坑主要在写入和更新上。
插入数据时,你不能显式给自增列指定一个具体的值,除非你给的是 NULL、0 或者 DEFAULT。像下面这样写会直接报错:
INSERT INTO t1 (id, name) VALUES (1, 'First'); -- 报错:auto-increment column should not be specified in insert
正确做法是不带自增列,让系统自己生成:
INSERT INTO t1 (name) VALUES ('First');
更新操作更是完全不支持。如果你试图 update 自增列的值,会收到一个很直白的提示,说这个版本不支持对自增列做 update 或 merge。
UPDATE t1 SET id = 2 WHERE id = 1; -- 报错:This version of GBase doesn't yet support 'update/merge on auto_increment column'
这里其实容易踩坑:做数据迁移或者修正脏数据的时候,可能会下意识地想去改自增列,结果发现完全动不了。
所以一开始设计表结构时就得想好哪些列是自增的,后面没办法改。
那如果确实有特殊需求,必须显式插入一个指定的自增值呢?GBase 留了个后门,参数 _gbase_auto_increment_allow_insert。
默认是 0,设为 1 就可以强行插入自定义值。
SET _gbase_auto_increment_allow_insert = 1; INSERT INTO t1 VALUES (1, 'First2'); SET _gbase_auto_increment_allow_insert = 0;
但这玩意儿我建议只在临时修复数据的时候用,用完马上关掉。因为开了之后,自增列的唯一性就得你自己保证了,系统不会再拦着,重复值进去以后,后续查询和关联都会乱。
另一个常见需求是给已有表加自增列。直接 alter table 改某个列为 auto_increment 是不行的,GBase 8a 不支持这种修改。只能绕一下。
流程大致是这样:
lcjmSSL让SSL证书管理像设置闹钟一样简单。免费用户同样支持多域名、通配符证书,通过DNS接口或CNAME解析自动完成验证,证书自动部署至应用,全程无需人工介入。
先加一个普通的 int 列:
ALTER TABLE tmp_id ADD COLUMN new_id INT;
然后给这一列填上唯一值。
这一步比较麻烦,因为 GBase 自己不会帮你自动生成,你得靠外部脚本或者写存储过程一行行去更新。假设你有一个函数 generate_unique_id() 能出唯一数:
UPDATE tmp_id SET new_id = generate_unique_id();
填好之后,把这个新列设成主键:
ALTER TABLE tmp_id ADD PRIMARY KEY (new_id);
如果你希望列名是 id,最后再 rename 一下(如果版本支持 rename column 的话):
ALTER TABLE tmp_id RENAME COLUMN new_id TO id;
整个操作下来,最耗时的是生成唯一值那一步。表大的话,得在维护窗口里做,不然锁表时间扛不住。
这些限制说到底就是,GBase 8a 的自增列不像 MySQL 那么灵活。用的时候提前规划好自增列,别事后去补,更别在业务代码里显式对自增列赋值,能省掉很多线上报错。

浙公网安备 33010602011771号