0

Rails アプリ用に PG データベースを移行する必要があります。テーブルの 1 つの列の型を boolean から int に更新しています。コードは次のとおりです。

class ChangeAdminToInt < ActiveRecord::Migration
  def up
    execute '
      ALTER TABLE "users"
      ALTER COLUMN "admin"
      TYPE int USING ("admin"::int)
      SET DEFAULT "1"
      '
  end
end

実行するbundle exec rake db:migrateと、次のエラーが表示されます。

PG::Error: ERROR:  syntax error at or near "SET"
LINE 5:  SET DEFAULT "1"

しかし、コードを次のように切り替えると:

class ChangeAdminToInt < ActiveRecord::Migration
  def up
    execute '
      ALTER TABLE users 
      ALTER COLUMN admin 
      TYPE int USING (admin::int);
      SET DEFAULT 1
      '
  end
end

エラーが発生します:

PG::Error: ERROR:  syntax error at or near "TYPE"
LINE 5:  TYPE int USING ("admin"::int)

問題は関数にとどまらず、むしろ 5 行目にあるため、データベースは 5 行目を気に入らないと思います。PG が実行コマンドの一部のみを解析している引用符の長さに制限はありますか? 多くのタイプの構文、一重引用符/二重引用符、%q/%Q ブロック、引用符全体を 1 行にまとめてみましたが、構文エラーは依然として TYPE と SET DEFAULT の前の方を指しています。確かに問題は ALTER ではありません ここで何が起こっているのですか?

どんな助けでも大歓迎です。完全に明らかな何かを見逃した場合はお知らせください。ところでいくつかのGemfile:

source 'https://rubygems.org'
ruby '1.9.3'

gem 'rails', '~> 4.0.1.rc3'
gem 'bootstrap-sass', '2.3.2.0'
gem 'bcrypt-ruby', '~> 3.1.1'
gem 'faker', '1.1.2'
gem 'will_paginate', '3.0.4'
gem 'bootstrap-will_paginate', '0.0.9'
gem 'safe_attributes'

group :development, :test do
  gem 'pg', '0.15.1'
  gem 'sqlite3'
  gem 'rspec-rails', '2.13.1'
  gem 'guard-rspec', '2.5.0'
  gem 'spork-rails', github: 'sporkrb/spork-rails'
  gem 'guard-spork', '1.5.0'
  gem 'childprocess', '0.3.6'
end

そして、開発環境用の database.yml:

development:
  adapter: postgresql
  encoding: utf8
  database: project_development
  pool: 5
  username: postgres
4

2 に答える 2

1

私はそれを考え出した!

PostgreSQL Web サイトからのこの引用 http://www.postgresql.org/docs/8.1/static/sql-altertable.html

この柔軟性のため、USING 式は列のデフォルト値 (存在する場合) には適用されません。結果は、デフォルトに必要な定数式ではない場合があります。これは、古い型から新しい型への暗黙的なキャストまたは代入キャストがない場合、USING 句が指定されていても、ALTER TYPE がデフォルトの変換に失敗する可能性があることを意味します。このような場合は、DROP DEFAULT でデフォルトを削除し、ALTER TYPE を実行してから、SET DEFAULT を使用して適切な新しいデフォルトを追加します。同様の考慮事項が、列に関連するインデックスと制約に適用されます。

最初にタイプを変更しようとすると、古いデフォルトが気に入りません。最初に新しいデフォルトを設定すると、convert と入力する方法がわかりません。This articleは、私の特定の操作を行う正しい方法は、最初にデフォルトを削除し、タイプを変更してから、新しいデフォルトを設定することであると述べています

これが私のために働いたコードです。

class ChangeAdminToInt < ActiveRecord::Migration
  def up
    execute %q(
      ALTER TABLE users 
      ALTER COLUMN admin DROP DEFAULT,
      ALTER COLUMN admin TYPE int USING ("admin"::int),
      ALTER COLUMN admin SET DEFAULT 1;
      )
  end
end

そしてそれだけです!

于 2013-10-25T17:37:35.743 に答える
0

USING句が正しいとは思いません。これは、postgre ドキュメント ( http://www.postgresql.org/docs/8.0/static/sql-altertable.html )からのものです。

オプションの USING 句は、古い列の値から新しい列の値を計算する方法を指定します。省略した場合、デフォルトの変換は、古いデータ型から新しいデータ型への代入キャストと同じです。古い型から新しい型への暗黙的なキャストまたは代入キャストがない場合は、USING 句を指定する必要があります。

したがって、USING は、古い値の型から新しい値の型を計算する方法を postgres に伝えるために使用されます。USING ("admin"::int)あなたの質問の意味がよくわかりません。USING 句を省略するか、次のようにしてみてください。

USING CASE WHEN "admin" = TRUE THEN 1 ELSE 0 END
于 2013-10-25T08:47:35.993 に答える