事故原因:
最近有个项目需要把oracle数据库替换成postgresql数据库,本来以为一切顺利,最后测试的时候发现所有序列都迁移错了,于是第一时间找到数据库迁移的同事,请求重新迁移,但是由于数据库迁移的同事事务繁忙,直接给我甩过来一堆从oracle库里导出来的序列创建语句。
解决方法
由于序列不支持 or replace 的语法,所以拿到create语句之后面临的选择就有以下两个:
第一个方法是,直接对create语句进行分析,分析出序列的序列名称,序列的当前值,然后把筛选出的值放入临时表,一个select语句直接拼出所有的alter语句,这个方法如果所有序列都存在,倒是很简单,如果不是,则需要像方法二一样,写一个存过执行所有的修改语句,才能完成任务,而且存过逻辑中还涉及到不存在的时候要进行新增,工作量只多不少。以下是部分文本筛选逻辑。如下语句放入文本编辑器中:
ctrl+f替换
CREATE SEQUENCE 替换成空
英文双引号替换成空
INCREMENT替换成 INCREMENT,前面加许多空格即可。
替换结果如图:
然后按住alt键,鼠标下拉选住后面哪些不是序列名称的部分,删除,最后把所有的空格替换成空即可。
如果要筛选其他的值,同样的道理。啥,为啥不写个python脚本处理一下,能两下干完的活,我坚决不干第三下。
前文提到这种方法再当前所有序列都存在的情况下倒是挺简单,但是问题是我遇到的是有些存在,有些不存在,所以这种方法不太适合。
第二种方法,筛选出所有的序列,全部删除,然后执行create语句。
由于删除不存在的序列会报错,导致整个脚本停止执行,所以最好写个存过,存过如下:
CREATE OR REPLACE FUNCTION drop_all_seq()
RETURNS void AS $$
DECLARE
item RECORD;
BEGIN
FOR item IN ( SELECT seq_name FROM tmp_seq ) loop
BEGIN
EXECUTE'drop sequence ' || item.seq_name || ';';
EXCEPTION
WHEN OTHERS THEN
INSERT INTO err_seq VALUES (item.seq_name);
END;
END loop;
END;
$$ LANGUAGE plpgsql;
把筛选出的序列名称插入到tmp_seq表里,然后执行上门的存过就完成了所有序列的删除,其中不存在的序列名称存放再err_seq表里,方便以后查问题,然后就可以执行create语句了,就完成了序列的调整了。