我正在尝试将现有列转换为标识。
到目前为止,我可以通过以下方式轻松完成这项工作:
alter table list alter column id set generated always as identity (start with 0);
不幸的是,我需要它从表中已有的最大数据开始。
我尝试了以下内容,但它抱怨子查询。
alter table list alter column id set generated always as identity (start with (select max(id) from list);
单独运行时子查询返回正常。
答案 0 :(得分:8)
我在blog: How to add IDENTITY column to existing table上找到了一个有趣的解决方案,
添加非空整数列
您需要为它提供默认值,否则db2将拒绝它为非null
alter table public.clicks add column id integer not null default 0
从列中删除默认值
我不确定为什么需要它,因为互联网上的一些手册省略了这一步但我没有在DB2 9.7.3 LUW上没有它的情况下工作
alter table public.clicks alter column id drop default
现在将列设置为始终生成
alter table public.clicks alter column id set generated always as identity
重组表使其可写
reorg table public.clicks
现在用生成的itentity值替换零
update public.clicks set id = default
并可选择为表创建id列主键
alter table public.clicks add constraint pkey primary key(id)
使用存储过程的另一种解决方案
将数据迁移到DB2时重新启动IDENTITY列
如果使用IDENTITY列创建表,并且您需要确保您的标识列从加载数据的最后一个最大值开始。 IBM Data Movement Tool会自动执行此操作,但如果您不使用该工具并希望将标识列的起始值与数据库中的数据同步,则可以使用此存储过程来同步数据。 link
--#SET TERMINATOR @
CREATE PROCEDURE RESETIDENTITYSTARTVALUE
(
IN schemaname VARCHAR(128),
IN tablename VARCHAR(128)
)
BEGIN
DECLARE sqlcode INTEGER;
DECLARE maxid BIGINT;
DECLARE idcolname VARCHAR(128);
DECLARE stmttxt VARCHAR(1000);
DECLARE s STATEMENT;
DECLARE cur CURSOR FOR s;
SELECT colname INTO idcolname
FROM SYSCAT.COLUMNS
WHERE tabname = tablename
AND tabschema = schemaname
AND identity = 'Y';
IF SQLCODE = 100 THEN
SIGNAL SQLSTATE '78000'
SET MESSAGE_TEXT = 'can''t find identity column';
END IF;
SET stmttxt = 'SELECT MAX("' || idcolname || '") FROM "' ||
schemaname || '"."' || tablename || '"';
PREPARE s FROM stmttxt;
SET maxid = 0;
OPEN cur;
FETCH cur INTO maxid;
CLOSE cur;
SET stmttxt = 'ALTER TABLE "' || schemaname || '"."' || tablename ||
'" ALTER COLUMN "' || idcolname ||
'" RESTART WITH ' || CHAR(maxid + 1);
EXECUTE IMMEDIATE stmttxt;
END
@
db2 connect to sample
db2 -tf sp.sql
db2 terminate
DB2手册:如果要修改标识列
修改标识列定义
如果要重新创建一个表,然后执行导入或加载操作,并且如果表中有一个IDENTITY列,那么它将重置为在重新创建表内容后从1开始生成IDENTITY值。将新行插入此重新创建的表时,您不希望IDENTITY列再次从1开始。
您不希望IDENTITY列中出现重复值。为防止这种情况发生,您应该:
SELECT MAX(<IDENTITY column>)
。这将返回与表的IDENTITY列值相等的值。ALTER TABLE <table name> ALTER COLUMN <IDENTITY column> RESTART WITH <last counter value + 1>