近期想把我们的某些rails项目从sqlserver迁移到postgres,由于我们的rails项目里夹杂很多的find_by_sql,而sqlserver与postgreSQL里很多语法/方法不同,需要sql的翻译处理。没有找到特别合适的插件做这件事情,只好自己动手。
一. 环境:
rails版本:3.0.7; ruby版本:1.8.7;
二. 主要步骤和方法:
1.导数据
利用Navicat for PostgreSQL将数据从sqlserver拷贝到postgreSQL
2.导完数据发现表无id,添加id
添加id有各种方法,你都可以尝试。当然你也可以用我在下面写的ruby代码。
3.添加id后发现id不自增长,为id添加sequence。
具体sql操作方法参可以参考http://tian-wang.iteye.com/blog/1051227。
由于我们已有数据,所以设置sequence时要指定start with n,其中n = max(id) + 1 。
特别要注意的是postgreSQL表名、字段名、序列名等最好不要用大写;序列名大写时会报错: relation "sequence_name" does not exist。
还有一点需要ruby程序员注意的是postgreSQL中的单双引号与ruby中单双引号意义完全不同,一不小心容易出错。
由于项目表数目太多,我写了一段ruby代码来完成这件事情(第二步和第三步),没有优化,先将就用着,至于怎么调用,不用多说了吧,哈哈:
module CommonExtensions
module OneTimeUsedForMigrate
extend ActiveSupport::Concern
#注意:postgreSQL的单双引号 和 ruby的单双引号不同,要特别注意
#postgreSQL表名、字段名、序列名等最好不要用大写
#序列名大写时会报错:ActiveRecord::StatementInvalid: PG::Error: ERROR: relation "tables_id_seq" does not exist
module ClassMethods
def fixed_for_pk
tables = fixed_all_table_names
Common.fixed_deal_with_primary_keys(tables)
end
def fixed_deal_with_primary_keys(tables)
tables.each do |table|
if fixed_has_primary_key?(table)
pk = fixed_get_pk_name(table)
else
pk = fixed_set_primary_key(table)
end
if pk
sequence_name = fixed_add_sequence(table, pk, true, true)
fixed_associate_pk_and_sequence(table, pk, sequence_name)
end
end
end
def fixed_add_sequence(table,pk,reset_seq=false,force=false)
sequence_name = fixed_get_pk_sequence_name(table,pk)
if reset_seq #强制删除主键上的sequence?
begin
delete_sql = "DROP SEQUENCE \"#{sequence_name}\" CASCADE "
Article.find_by_sql(delete_sql)
rescue
end
end
if force #删除主键为空的列
delete_null_id_sql = "delete from \"public\"