表增加字段

由于需求变更,需要增加字段。但是呢,发现postgre中使用的是标准的sql语法,并没有指定在哪个位置插入字段的语法,默认的ALTER TABLE table_name ADD COLUMN new_field语法,不支持类似mysql的after语法,只能插在表的最后。网上大概找了下,也没有什么优化的方法。

有如下变通:1、新建表,复制旧数据到新表,删除旧表,2、或者创建视图,来保证顺序一致。(建立一个视图)

本文记录一下方式1的迁移方法。

结论

对表进行etl转换,最好将计算字段放到表的前面,这样方便后续的扩展。

一般语法

ALTER TABLE table_name ADD COLUMN kafka_time timestamp without time zone;

只能在末尾增加字段。

迁移前

临时表结构

create table i1_import_raw (
    ship_id varchar(20),
    clraddr text,
    -- 以下为新增字段
    psmdb_ft smallint,
    psmdb_loc smallint,
    Recv_Prov varchar(32),
    Recv_City varchar(32),
    Recv_Coty varchar(32)
) with (appendonly=true, compresslevel=5, orientation=column, compresstype=zlib)
Distributed by (ship_id);

目标表结构

create table i1_order (    
    ship_id varchar(20),
    clraddr text,
    -- 欲在此处增加新字段
    batch_time timestamp without time zone,  -- 批处理转换成时间戳
) with (appendonly=true, compresslevel=5, orientation=column, compresstype=zlib)
Distributed by (ship_id)

数据转换脚本

由于导入数据的时候,先将数据导入到临时表,然后执行如下,将临时表的数据导入到正式表。

psql -d develop -h  localhost -U gpadmin  -p 5432  -c "insert into i1_$table select *,to_timestamp(substring(batch from 3),'yyyyMMddhh24miss') as batch_time from i1_import_raw;"

正是由于,当时建表的时候,没有想到新增字段这样的需求,错误的将计算字段放到了末尾。结果导致新增字段时,需要重新迁移表。

迁移

临时表迁移

可以直接在表后面,增加字段。

ALTER TABLE i1_import_raw ADD COLUMN psmdb_ft   smallint;
ALTER TABLE i1_import_raw ADD COLUMN psmdb_loc smallint;
ALTER TABLE i1_import_raw ADD COLUMN Recv_Prov  varchar(32);
ALTER TABLE i1_import_raw ADD COLUMN Recv_City  varchar(32);
ALTER TABLE i1_import_raw ADD COLUMN Recv_Coty  varchar(32);

正式表,却不能使用上面的方式来增加字段。

-- 无法工作
ALTER TABLE i1_order ADD COLUMN psmdb_ft smallint after ;
-- 上面只能在最后添加,计算字段 batch_time 结果在中间,行不通。

ALTER TABLE ADD COLUMN只会在最后添加新列,作为最后一列. 要在另一个位置创建新列,您需要重新创建表并从此新表中的旧/当前表中复制数据.

正式表

重建表结构

create table i1_order2 (
    batch_time timestamp without time zone,  -- 批处理转换成时间戳
    -- 注意,上面存放计算字段,下面存放临时表一样的结构,下次就可以直接 add修改了。
    ship_id varchar(20),
    clraddr text,
    -- 新增的字段
    psmdb_ft smallint,
    psmdb_loc smallint,
    Recv_Prov varchar(32),
    Recv_City varchar(32),
    Recv_Coty varchar(32)
) with (appendonly=true, compresslevel=5, orientation=column, compresstype=zlib)
Distributed by (ship_id);

迁移过程

-- 为了匹配上字段,每个都逐一增加列名
-- 一般方式
insert into i1_order2 select * from i1_order ;
-- 先测试 
insert into i1_order2 (batch_time,ship_id) select batch_time,ship_id from i1_order limit 10;
-- 整体迁移
-- 字段列表   如 fields1,fields2
insert into i1_order2 (字段列表) select 字段列表  from i1_order;
-- 经测试发现,及时部分字段,insert部分也能省略
insert into i1_order2 select 字段列表  from i1_order;

-- 切换表名
drop table i1_order;
alter table i1_order2 rename to i1_order;
-- 其他,如统计新表的内容等。

替换脚本

转换的时候,将计算字段放到最前面。这样方便后续增加字段。

# 调整一下计算字段的顺序
psql -d  develop   -h  localhost   -U gpadmin  -p 5432  -c "insert into i1_$table select to_timestamp(substring(batch from 3),'yyyyMMddhh24miss'),* as batch_time from i1_import_raw;"