varcharフィールドの型を整数に変更:「整数型に自動的にキャストすることはできません」


154

小さなテーブルがあり、特定のフィールドにタイプ「文字可変」が含まれています。「Integer」に変更しようとしていますが、キャストできないというエラーが表示されます。

これを回避する方法はありますか、または別のテーブルを作成し、クエリを使用してレコードをそのテーブルに取り込む必要があります。

フィールドには整数値のみが含まれます。


どのALTER TABLEを試みましたか、そして特定のエラーメッセージは何でしたか?
muが短すぎます

@muistooshort phppgadminからalterを使用してみました。列を選択し、新しいフィールドタイプを入力しようとしました。エラーがある:SQL error: ERROR: column "MID" cannot be cast to type integer
itsols

3
最初はテーブルのバックアップです。次に、同じテーブルに整数型の別の列(たとえば、field2)を作成できます。field1からfield2へのキャストから整数値を選択します。次に、列の名前を変更します。
イゴール

@Igorですが、新しい列はテーブルの最後にありますよね?同じ位置に置くことはできませんか?
itols

2
@itsols列の位置を気にすることは、通常、アプリケーション設計が不明瞭である兆候です。ほとんどの場合SELECT、列の序数位置に依存せずに、明示的に名前が付けられた列とリストを使用する必要があります。とはいえ、回答で与えられたアプローチは列の位置を保持します。
クレイグリンガー、2012年

回答:


264

からtextまたはvarcharへの暗黙の(自動)キャストintegerはありません(つまり、フィールドをvarchar予期する関数に渡すintegerことも、varcharフィールドをフィールドに割り当てることintegerもできません)。したがって、ALTER TABLE ... ALTER COLUMN ... TYPEを使用して明示的なキャストを指定する必要があります。 ..使用

ALTER TABLE the_table ALTER COLUMN col_name TYPE integer USING (col_name::integer);

テキストフィールドに空白が含まれている可能性があることに注意してください。その場合は、次を使用します。

ALTER TABLE the_table ALTER COLUMN col_name TYPE integer USING (trim(col_name)::integer);

変換前に空白を削除します。

これは、コマンドがで実行された場合のエラーメッセージから明らかですが、PgAdmin psql-IIIが完全なエラーを表示していない可能性があります。psqlPostgreSQL 9.2 でテストすると、次のようになります。

=> CREATE TABLE test( x varchar );
CREATE TABLE
=> insert into test(x) values ('14'), (' 42  ');
INSERT 0 2
=> ALTER TABLE test ALTER COLUMN x TYPE integer;
ERROR:  column "x" cannot be cast automatically to type integer
HINT:  Specify a USING expression to perform the conversion. 
=> ALTER TABLE test ALTER COLUMN x TYPE integer USING (trim(x)::integer);
ALTER TABLE        

USINGリンクを追加してくれて@muistooshortに感謝します。

こちらもご覧ください この関連質問。それはRailsの移行に関するものですが、根本的な原因は同じであり、答えが当てはまります。

それでもエラーが発生する場合は、列の値と関係がない可能性がありますが、この列または列のデフォルト値に対するインデックスは型キャストに失敗する可能性があります。インデックスは、ALTER COLUMNの前に削除し、後で再作成する必要があります。デフォルト値は適切に変更する必要があります。


お時間をいただきありがとうございます。しかし、私はこれを機能させるようには思えません。私はあなたのALTER行を試してみましたが、「使用中の構文エラー」というエラーが表示されます
itols

私のステートメント:ALTER TABLE "tblMenus" ALTER COLUMN "MID" USING(trim( "MID"):: integer);
itols

1
@itsols完全に私の間違い。あなたのコメントを見た通りに修正しました。改訂版をご覧ください。それはデモコードに含まれており、最初の一般的な例ではありませんでした。
クレイグリンガー、2012年

どうもありがとう!この答えは私に多くのトラブルと時間を節約しました。niether phppgadminもpgAdminでは、機能としてこれを持っている理由かしら...
itsols

@itsolsほとんどのコアチームはPgAdminにそれほど関心がなく、使用しているチームはほとんどありません。いくつかの迷惑な使いやすさのイボと機能制限があります。これはそのうちの1つにすぎません。PgAdminを使用する専門家はほとんどいないため、専門家はPgAdminを悩ませる問題を修正する意欲がありません。私は自分でそれを使用していませんpsql。私は、バックアップに関してpgAdminでのユーザビリティについて暴言のビットを書き、しばらく前に復元:blog.ringerc.id.au/2012/05/...
クレイグ・リンガー

70

これは私のために働いた。

varchar列をintに変更します

change_column :table_name, :column_name, :integer

得た:

PG::DatatypeMismatch: ERROR:  column "column_name" cannot be cast automatically to type integer
HINT:  Specify a USING expression to perform the conversion.

に変更

change_column :table_name, :column_name, 'integer USING CAST(column_name AS integer)'

この演習をデータで試しましたか?
itols 2014

3
列にあるものが整数である
限り

うまくいきません。ruby 2.2.3とレール4.2.3を使用しています
Thinh D. Bui

@ ThinhD.Bui-私のために働く、2.3.0、レール4.2.6
Philip

1
デフォルトにも注意してください
Francisco Quintero 2016

17

あなたはそれを次のように行うことができます:

change_column :table_name, :column_name, 'integer USING CAST(column_name AS integer)'

またはこれを試してください:

change_column :table_name, :column_name, :integer, using: 'column_name::integer'

このトピックについて詳しく知りたい場合は、この記事をお読みください:https : //kolosek.com/rails-change-database-column


8

これを試してください、それは確かに動作します。

文字列の列を整数に変換するRailsマイグレーションを作成するとき、通常は次のようにします。

change_column :table_name, :column_name, :integer

ただし、PostgreSQLは文句を言うでしょう。

PG::DatatypeMismatch: ERROR:  column "column_name" cannot be cast automatically to type integer
HINT:  Specify a USING expression to perform the conversion.

「ヒント」は基本的に、これを実行することを確認する必要があること、およびデータを変換する方法を示します。マイグレーションでこれを言ってください:

change_column :table_name, :column_name, 'integer USING CAST(column_name AS integer)'

上記は、他のデータベースアダプターから知っていることを模倣します。数値以外のデータがある場合、結果は予期しないものになる可能性があります(結局、整数に変換しています)。


もう1つポイントを追加したかったので、change_columnには注意してください。それは不可逆的です。これを元に戻すには、マイグレーションで上下を使用することをお勧めします。
Mukesh Kumar Gupta

2
PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: ""エラーが発生
Shaig Khaligli

6

同じ問題が発生しました。変更しようとしている列にデフォルトの文字列値があることに気づいたとき。デフォルト値を削除すると、エラーは解消されました:)


また、この列の既存のインデックスが問題になる可能性があります。ALTERの前に削除し、後で再作成する必要があります。
Envek

1

誤って整数をテキストデータと混合していない場合は、最初に以下の更新コマンドを実行する必要があります(上にない場合、alter tableは失敗します)。

UPDATE the_table SET col_name = replace(col_name, 'some_string', '');

3
regexp_replace(col_name, '[^0-9.]','','g')不要な文字や空白を取り除こうとしているような場合は、そのほうがいいでしょう。ただし、科学的表記を保持NaNしたい場合は、もう少し洗練されたものが必要になります。Inf10E42
クレイグリンガー2013

1

開発環境(または本番環境の場合は、データのバックアップである可能性があります)で作業している場合は、最初にDBフィールドからデータを消去するか、値を0に設定します。

UPDATE table_mame SET field_name= 0;

その後、以下のクエリを実行し、クエリを正常に実行した後、schemamigrationに移行スクリプトを実行します。

ALTER TABLE table_mame ALTER COLUMN field_name TYPE numeric(10,0) USING field_name::numeric;

それはあなたを助けると思います。


0

同じ問題がありました。列のデフォルトをリセットし始めました。

change_column :users, :column_name, :boolean, default: nil
change_column :users, :column_name, :integer, using: 'column_name::integer', default: 0, null: false
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.