DB2:将现有列转换为标识

时间:2013-12-30 22:37:53

标签: db2

我正在尝试将现有列转换为标识。

到目前为止,我可以通过以下方式轻松完成这项工作:

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);

单独运行时子查询返回正常。

1 个答案:

答案 0 :(得分:8)

我在blog: How to add IDENTITY column to existing table上找到了一个有趣的解决方案,

  1. 添加非空整数列 您需要为它提供默认值,否则db2将拒绝它为非null alter table public.clicks add column id integer not null default 0

  2. 从列中删除默认值 我不确定为什么需要它,因为互联网上的一些手册省略了这一步但我没有在DB2 9.7.3 LUW上没有它的情况下工作 alter table public.clicks alter column id drop default

  3. 现在将列设置为始终生成 alter table public.clicks alter column id set generated always as identity

  4. 重组表使其可写 reorg table public.clicks

  5. 现在用生成的itentity值替换零 update public.clicks set id = default

  6. 并可选择为表创建id列主键 alter table public.clicks add constraint pkey primary key(id)

  7. 使用存储过程的另一种解决方案

    将数据迁移到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列中出现重复值。为防止这种情况发生,您应该:

    1. 重新创建表格。
    2. 使用MODIFIED BY IDENTITYOVERRIDE子句将数据加载到表中。数据将加载到表中,但不会为行生成标识值。
    3. 运行查询以获取IDENTITY列的最后一个计数器值:SELECT MAX(<IDENTITY column>)。这将返回与表的IDENTITY列值相等的值。
    4. 使用ALTER TABLE语句的RESTART子句:ALTER TABLE <table name> ALTER COLUMN <IDENTITY column> RESTART WITH <last counter value + 1>
    5. 在表格中插入新行。将根据RESTART WITH子句中指定的值生成IDENTITY列值。
    6. 将所有数据输入表格后,使用SET INTEGRITY语句设置表格的完整性。