我想寫(Ruby)腳本,將所有外鍵和唯一約束放在我的PostgreSQL數據庫,然後重新添加它們。如何從PostgreSQL數據庫中刪除唯一約束?
FK部分似乎工作正常。
但是,刪除並重新創建唯一約束不起作用。
我認爲原因是當創建唯一約束時,PostgreSQL會隨之創建一個索引,並且在刪除唯一約束時該索引不會自動刪除。當腳本嘗試重新添加唯一約束那麼,我得到這樣一個錯誤......
PG::Error: ERROR: relation "unique_username" already exists
: ALTER TABLE users ADD CONSTRAINT unique_username UNIQUE (username)
事實上,當我看DB在pgAdmin的GUI工具,該索引存在。
問題是,我如何在腳本中找到它並放下它?
這裏是我的腳本...
manage_constraints.rake
namespace :journal_app do
desc 'Drop constraints'
task :constraints_drop => :environment do
sql = %Q|
SELECT
constraint_name, table_catalog, table_name
FROM
information_schema.table_constraints
WHERE
table_catalog = 'journal_app_#{Rails.env}'
AND
constraint_name NOT LIKE '%_pkey'
AND
constraint_name NOT LIKE '%_not_null';
|
results = execute_sql(sql)
results.each do |row|
puts "Dropping constraint #{row['constraint_name']} from table #{row['table_name']}."
execute_sql("ALTER TABLE #{row['table_name']} DROP CONSTRAINT #{row['constraint_name']}")
end
end
# --------------------------------------------------------------------------------------------------------------------
desc 'Drops constraints, then adds them'
task :constraints_add => :environment do
Rake::Task['journal_app:constraints_drop'].invoke
UNIQUE_KEYS = [
{
:name => 'unique_username',
:table => 'users',
:columns => ['username']
},
{
:name => 'unique_email',
:table => 'users',
:columns => ['email']
}
]
FKs = [
{
:name => 'fk_entries_users',
:parent_table => 'users',
:child_table => 'entries',
:on_delete => 'CASCADE'
},
{
:name => 'fk_entries_entry_tags',
:parent_table => 'entries',
:child_table => 'entry_tags',
:on_delete => 'CASCADE'
},
# etc...
]
UNIQUE_KEYS.each do |constraint|
sql = "ALTER TABLE #{constraint[:table]} ADD CONSTRAINT #{constraint[:name]} UNIQUE (#{constraint[:columns].join(', ')})"
puts "Adding unique constraint #{constraint[:name]} to table #{constraint[:table]}."
puts ' SQL:'
puts " #{sql}"
execute_sql(sql)
end
FKs.each do |fk|
sql = %Q|
ALTER TABLE #{fk[:child_table]} ADD CONSTRAINT #{fk[:name]} FOREIGN KEY (#{fk[:parent_table].singularize}_id)
REFERENCES #{fk[:parent_table]} (id)
ON UPDATE NO ACTION ON DELETE #{fk[:on_delete]}|.strip!
puts "Adding foreign key #{fk[:name]}."
puts ' SQL:'
puts " #{sql}"
execute_sql(sql)
end
end
end
def execute_sql(sql)
ActiveRecord::Base.connection.execute(sql)
end
唯一約束和唯一索引之間沒有區別。爲什麼不開始在psql命令行上首先執行查詢,而不是添加一層潛在的混淆。另外請注意,約束和索引名稱不是本地的表,這就是爲什麼當你讓db爲你選擇一個默認名稱時,它們通常以表名開頭。 –
「*當唯一約束被刪除時,該索引不會自動刪除*」。那是錯的。刪除唯一約束時,會刪除索引***。你可能不會「下降」,因此pgAdmin仍然顯示它? –