SQLiteデータベーステーブルの列の名前を変更するにはどうすればよいですか?


296

SQLiteデータベースのいくつかのテーブルのいくつかの列の名前を変更する必要があります。以前にstackoverflow でも同様の質問がされたことは知っていますが、SQL全般に関する質問であり、SQLiteのケースについては触れられていません。

ALTER TABLEの SQLiteドキュメントから、そのようなことを「簡単に」(つまり、単一のALTER TABLEステートメントで)実行することは不可能であることがわかります。

SQLiteでそのようなことを行う一般的なSQLの方法を誰かが知っているのではないかと思っていました。


あなたは使用してそれを行うことができますsqliteのためのDBブラウザをかなり簡単に
マット・G

1
受け入れられたとして、この答えをマークご検討くださいstackoverflow.com/a/52346199/124486
エヴァンキャロル

回答:


66

これは2018-09-15(3.25.0)で修正されました

ALTER TABLEコマンドを拡張します:

  • tableを使用して、テーブル内の列の名前を変更するためのサポートを追加しALTER TABLEますRENAME COLUMN oldname TO newname
  • テーブルの名前変更機能を修正して、トリガーとビューで名前が変更されたテーブルへの参照も更新するようにします。

以下に記載されている新しい構文を見つけることができます ALTER TABLE

RENAME COLUMN TO構文は、新しい列名にテーブルのテーブル名の列名を変更します。列名は、テーブル定義内と、列を参照するすべてのインデックス、トリガー、ビュー内の両方で変更されます。列名を変更すると、トリガーまたはビューに意味のあいまいさが生じるRENAME COLUMN場合、エラーで失敗し、変更は適用されません。

ここに画像の説明を入力してください 画像ソース:https : //www.sqlite.org/images/syntax/alter-table-stmt.gif

例:

CREATE TABLE tab AS SELECT 1 AS c;

SELECT * FROM tab;

ALTER TABLE tab RENAME COLUMN c to c_new;

SELECT * FROM tab;

db-fiddle.comデモ


Androidサポート

執筆時点では、AndroidのAPI 27はSQLiteパッケージバージョン3.19を使用しています

Androidが使用している現在のバージョンと、このアップデートがSQLiteのバージョン3.25.0で提供されることに基づいて、Androidにこのサポートが追加されるまで、少し待つ必要があります(約API 33)。

そして、それでも、API 33より古いバージョンをサポートする必要がある場合、これを使用することはできません。


8
Androidの移行を実装していますが、残念ながらIntelliJは有効なSQLコマンドではないという警告を表示しています。database.execSQL("ALTER TABLE content RENAME COLUMN archiveCount TO dismissCount")COLUMは赤で強調表示されており、TOが予想され、「COLUMN」を取得しました。残念ながら、AndroidはまだSQLiteバージョン3.19を使用しているため、これは私には機能しません。
Adam Hurwitz、2018年

1
編集:system.data.sqlite.org/index.html/doc/trunk/www/faq.wiki#q1で、1.0.109.x)が実際にSQLite 3.24とSystem.Data.SQLiteを使用していることを発見しました SQLite 3.25の使用は今月リリースされる予定です。
rychlmoj

1
参考までに、残念ながらこれはまだAndroidのSQLiteライブラリで実装されていません。うまくいけば、彼らはすぐに更新されます。
Adam Hurwitz、2018

3
Androidサポートのセクションを追加して、他の人が期待を裏切らないようにしました。SQLite 3.19のAndroid 27の現在の使用状況に基づいて、この機能がAndroidに追加される前に、おおよそAPI 33まで待つ必要があります。それでも、最新バージョンでのみサポートされます。はぁ。
ジョシュアピンター

1
@JoshuaPinter私の答えを拡張してくれてありがとう。
Lukasz Szozda、2018

448

テーブルがあり、「colb」の名前を「col_b」に変更する必要があるとします。

まず、古いテーブルの名前を変更します。

ALTER TABLE orig_table_name RENAME TO tmp_table_name;

次に、古いテーブルに基づいて、更新された列名で新しいテーブルを作成します。

CREATE TABLE orig_table_name (
  col_a INT
, col_b INT
);

次に、元のテーブルの内容をコピーします。

INSERT INTO orig_table_name(col_a, col_b)
SELECT col_a, colb
FROM tmp_table_name;

最後に、古いテーブルを削除します。

DROP TABLE tmp_table_name;

このすべてをラップBEGIN TRANSACTION;し、COMMIT;おそらく良いアイデアです。


51
そして、あなたの指標を忘れないでください。
トムメイフィールド、

11
非常に重要なことに、上記のサンプルコードにはトランザクションがありません。BEGIN / END(またはROLLBACK)で全体をラップして、名前変更が正常に完了するか、まったく完了しないようにする必要があります。
ロジャービン

4
Androidでこれを実行したい人は、SQLiteDatabase.beginTransaction()
bmaupin

7
インデックスをコピーする答えのコードには何もありません。空のテーブルを作成してデータを入れると、構造とデータのみがコピーされます。メタデータ(インデックス、外部キー、制約など)が必要な場合は、ステートメントを発行して、置き換えられたテーブルにメタデータを作成する必要もあります。
トムメイフィールド

17
SQLiteの.schemaコマンドはCREATE TABLE、既存のテーブルを作成するステートメントを表示するのに便利です。その出力を取得し、必要に応じて変更し、実行して新しいテーブルを作成できます。このコマンドは、CREATE INDEXインデックスを作成するために必要なコマンドも表示します。これにより、トーマスの懸念がカバーされます。もちろん、変更する前に必ずこのコマンドを実行してください。
Mike DeSimone

56

いろいろ調べてみる、DBite for SQLiteと呼ばれるこのマルチプラットフォーム(Linux | Mac | Windows)のグラフィカルツールで、非常にユーザーフレンドリーな方法で列の名前を実際に変更できます。

編集| テーブルの変更| テーブルを選択| フィールドを編集します。クリッククリック!出来上がり!

ただし、これをプログラムで行う方法を誰かが共有したい場合は、喜んでお知らせします。


1
同じことを行うFirefoxアドオンもあります。名前を変更する列を右クリックし、[列の編集]を選択します。
Jacob Hacker、2014年

1
openSUSEでも、パッケージとして利用できます: software.opensuse.org/package/sqlitebrowser

投票数が多いのは変だ。ここではプログラミングについて話しています(コード)。なぜあなたはこの答えをここに投稿したのですか?
user25

2
私の質問にはコードでこれを行う方法についての言及はありません。SQLite DBで列の名前を変更する方法を知りたかっただけです。
joce

@joce愛してる!!! (兄弟のように)私をフィールドに入れ替えました、出来上がり。MS AccessテーブルをSQLiteにエクスポートしましたが、フィールドの1つに3桁の前に数字がありました:3YearLetterSent。Visual Studioはテーブルからクラスを作成しましたが、フィールド名の前の "3"桁が詰まっています。私はこれを知っています、ただ見ていませんでした。
JustJohn 2019年

53

ALTER COLUMNがないことは事実ですが、列の名前変更、NOT NULL制約の削除、またはデータ型の変更のみを行う場合は、次の一連のコマンドを使用できます。

注:これらのコマンドはデータベースを破壊する可能性があるので、バックアップがあることを確認してください

PRAGMA writable_schema = 1;
UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';
PRAGMA writable_schema = 0;

接続を閉じて再度開くか、データベースをバキュームしてスキーマに変更を再読み込みする必要があります。

例えば:

Y:\> sqlite3 booktest  
SQLite version 3.7.4  
Enter ".help" for instructions  
Enter SQL statements terminated with a ";"  
sqlite> create table BOOKS ( title TEXT NOT NULL, publication_date TEXT NOT NULL);  
sqlite> insert into BOOKS VALUES ("NULLTEST",null);  
Error: BOOKS.publication_date may not be NULL  
sqlite> PRAGMA writable_schema = 1; 
sqlite> UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE BOOKS ( title TEXT NOT NULL, publication_date TEXT)' WHERE NAME = 'BOOKS';  
sqlite> PRAGMA writable_schema = 0;  
sqlite> .q  

Y:\> sqlite3 booktest  
SQLite version 3.7.4  
Enter ".help" for instructions  
Enter SQL statements terminated with a ";"  
sqlite> insert into BOOKS VALUES ("NULLTEST",null);  
sqlite> .q  

参考文献:


pragma writable_schema
このプラグマがオンの場合、通常のUPDATE、INSERT、およびDELETEステートメントを使用してデータベースを変更できるSQLITE_MASTERテーブル。警告:このプラグマを誤用すると、データベースファイルが破損する可能性があります。

テーブルの変更
SQLiteは、ALTER TABLEの限定されたサブセットをサポートしています。SQLiteのALTER TABLEコマンドを使用すると、ユーザーはテーブルの名前を変更したり、既存のテーブルに新しい列を追加したりできます。列の名前を変更したり、列を削除したり、テーブルに制約を追加または削除したりすることはできません。

ALTER TABLE構文


3
危険ですが、おそらく最も簡単な答えです。
Tek

2
はい、非常に高速です- 危険なのは、「最初にバックアップがあることを確認してください」という意味です
Noah

6
sqliteファイルの形式は非常にシンプルで、この操作が有効なのはそのためです。ファイル形式には、テーブルに関する2組の情報しかありません。プレーンテキストとしての実際のCREATE TABLEコマンドと、その値がCREATEコマンドのフィールドの順序で表示される行です。つまり、sqliteコードはデータベースを開き、各CREATEコマンドを解析して、メモリに列情報を動的に構築します。そのため、タイプや制約を変更しても、同じ列数になるようにCREATEコマンドを変更するコマンドはすべて機能します。
Thomas Tempelmann、2016

3
@ThomasTempelmannただし、クエリプランナーは制約が成立すると想定しているため、データセットによって満たされない制約を追加すると問題が発生します。
fuz 2016

2
@ThomasTempelmann 制約の削除は常に問題ありません。すべての行で制約が満たされていれば、制約を追加しても問題ありませんが、確認する必要があります。
fuz 2016

18

最近、私はSQLite3で、pointsという名前のテーブルにcolumms id、lon、latを付けて実行する必要がありました。誤って、テーブルがインポートされたとき、緯度の値はlon列に格納され、その逆も同様でしたので、明らかな修正はそれらの列の名前を変更することです。だからトリックは:

create table points_tmp as select id, lon as lat, lat as lon from points;
drop table points;
alter table points_tmp rename to points;

これがあなたに役立つことを願っています!


このメソッドは、PK値を適切にコピーせず、非表示のROWID列を自動的に作成します。必ずしも問題ではありませんが、それが私にとって問題になったため、指摘したかったのです。
TPoschel

4
「UPDATEポイントSET lon = lat、lat = lon;」を実行する方が簡単ではないでしょうか?
kstep 2013年

1
この答えは、正しい順序でプロセスを実行します。最初に一時テーブルを作成してデータを設定してから、元のテーブルを破棄します。
Xeoncross 2013年

14

sqliteのドキュメントを引用:

SQLiteは、ALTER TABLEの限定されたサブセットをサポートします。SQLiteのALTER TABLEコマンドを使用すると、ユーザーはテーブルの名前を変更したり、既存のテーブルに新しい列を追加したりできます。列の名前を変更したり、列を削除したり、テーブルに制約を追加または削除したりすることはできません。

もちろん、できることは、新しいレイアウトで新しいテーブルを作成し、SELECT * FROM old_table受け取った値を新しいテーブルに入力することです。


7

まず、これは私を驚かせたものの1つです。列の名前を変更するには、完全に新しいテーブルを作成し、古いテーブルから新しいテーブルにデータをコピーする必要があります...

SQLiteの操作を行うために私が上陸したGUIはBaseです。実行されたすべてのコマンドを表示する気の利いたログウィンドウがあります。Baseを介して列の名前を変更すると、ログウィンドウに必要なコマンドが入力されます。

ベースログウィンドウ

これらは簡単にコピーして、必要な場所に貼り付けることができます。私にとっては、それはActiveAndroid移行ファイルに含まれています。同様に、コピーされたデータにはSQLiteコマンドのみが含まれ、タイムスタンプなどは含まれません。

うまくいけば、一部の人々の時間を節約できます。


参考までにActiveAndroidを使用している場合、ActiveAndroidがそれを処理するため、およびの行を省略できます。BEGIN TRANSACTION;COMMIT;
Joshua Pinter

6

ケース1:SQLite 3.25.0以降

SQLiteのバージョン3.25.0のみが列名の変更をサポートしています。デバイスがこの要件を満たしている場合は、非常に簡単です。以下のクエリはあなたの問題を解決します:

ALTER TABLE "MyTable" RENAME COLUMN "OldColumn" TO "NewColumn";

ケース2:SQLiteの古いバージョン

少しトリッキーかもしれない結果を得るには、別のアプローチに従う必要があります

たとえば、次のようなテーブルがあるとします。

CREATE TABLE student(Name TEXT, Department TEXT, Location TEXT)

列の名前を変更したい場合 Location

ステップ1:元のテーブルの名前を変更します。

ALTER TABLE student RENAME TO student_temp;

ステップ2:次にstudent、正しい列名で新しいテーブルを作成します。

CREATE TABLE student(Name TEXT, Department TEXT, Address TEXT)

ステップ3:元のテーブルから新しいテーブルにデータをコピーします。

INSERT INTO student(Name, Department, Address) SELECT Name, Department, Location FROM student_temp;

注:上記のコマンドはすべて1行である必要があります。

ステップ4:元のテーブルを削除します。

DROP TABLE student_temp;

これらの4つのステップで、SQLiteテーブルを手動で変更できます。また、新しいテーブルでインデックス、ビューア、またはトリガーも再作成する必要があることに注意してください。


1
Android Studioでsqlliteデータベースのバージョンを3.29.0にアップグレードする方法(APIレベル28を使用しています)
Nathani Software

SQLiteのバージョンは、アプリが動作するデバイスによって定義されます。デバイスに依存します。
Febin Mathew、

1
古いsqliteを使用している場合は、上記の4つのステップはお勧めしません。sqlite.org/lang_altertable.htmlの「注意」セクションを参照してください
ジェフ

3

テーブルの列<id>を<_id>に変更

 String LastId = "id";

    database.execSQL("ALTER TABLE " + PhraseContract.TABLE_NAME + " RENAME TO " + PhraseContract.TABLE_NAME + "old");
    database.execSQL("CREATE TABLE " + PhraseContract.TABLE_NAME
    +"("
            + PhraseContract.COLUMN_ID + " INTEGER PRIMARY KEY,"
            + PhraseContract.COLUMN_PHRASE + " text ,"
            + PhraseContract.COLUMN_ORDER  + " text ,"
            + PhraseContract.COLUMN_FROM_A_LANG + " text"
    +")"
    );
    database.execSQL("INSERT INTO " +
            PhraseContract.TABLE_NAME + "("+ PhraseContract.COLUMN_ID +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +")" +
            " SELECT " + LastId +" , "+ PhraseContract.COLUMN_PHRASE + " , "+ PhraseContract.COLUMN_ORDER +" , "+ PhraseContract.COLUMN_FROM_A_LANG +
            " FROM " + PhraseContract.TABLE_NAME + "old");
    database.execSQL("DROP TABLE " + PhraseContract.TABLE_NAME + "old");

3

目的の列名COLNewで新しい列を作成します。

ALTER TABLE {tableName} ADD COLUMN COLNew {type};

古い列COLOldの内容を新しい列COLNewにコピーします。

INSERT INTO {tableName} (COLNew) SELECT {COLOld} FROM {tableName}

注:上記の行にはブラケットが必要です。


2

前述したように、SQLite Database Browserというツールがあります。ありがたいことに、このツールは、ユーザーまたはアプリケーションによって実行されたすべての操作のログを保持します。これを1回実行してアプリケーションログを確認すると、関連するコードが表示されます。クエリをコピーして、必要に応じて貼り付けます。私のために働いた。お役に立てれば


2

公式ドキュメントから

オプションで、ディスク上のコンテンツにまったく影響を与えない変更のために、より単純で高速な手順を使用できます。次の簡単な手順は、CHECKまたはFOREIGN KEYまたはNOT NULL制約の削除、列の名前の変更、または列のデフォルト値の追加または削除または変更に適しています。

  1. トランザクションを開始します。

  2. PRAGMA schema_versionを実行して、現在のスキーマバージョン番号を確認します。この番号は、以下のステップ6で必要になります。

  3. PRAGMA writable_schema = ONを使用してスキーマ編集をアクティブにします。

  4. UPDATEステートメントを実行して、sqlite_masterテーブルのテーブルXの定義を変更します。UPDATE sqlite_master SET sql = ... WHERE type = 'table' AND name = 'X';

    注意:このようにsqlite_masterテーブルに変更を加えると、変更に構文エラーが含まれている場合、データベースが破損して読み取り不可能になります。重要なデータを含むデータベースでUPDATEステートメントを使用する前に、別の空のデータベースでUPDATEステートメントを慎重にテストすることをお勧めします。

  5. テーブルXへの変更が他のテーブルまたはインデックスにも影響する場合、またはトリガーがスキーマ内のビューである場合、UPDATEステートメントを実行して、他のテーブルインデックスとビューも変更します。たとえば、列の名前が変更された場合、その列を参照するすべてのFOREIGN KEY制約、トリガー、インデックス、およびビューを変更する必要があります。

    注意:繰り返しになりますが、このようにsqlite_masterテーブルに変更を加えると、変更にエラーが含まれている場合、データベースが破損して読み取り不可能になります。重要なデータを含むデータベースで使用する前に、この手順全体を別のテストデータベースで慎重にテストし、この手順を実行する前に重要なデータベースのバックアップコピーを作成してください。

  6. PRAGMA schema_version = Xを使用してスキーマバージョン番号をインクリメントします。Xは、上記の手順2で見つかった古いスキーマバージョン番号より1つ大きくなります。

  7. PRAGMA writable_schema = OFFを使用してスキーマ編集を無効にします。

  8. (オプション)PRAGMA完全性チェックを実行して、スキーマの変更がデータベースに損傷を与えていないことを確認します。

  9. 上記のステップ1で開始したトランザクションをコミットします。


PRAGMA integer_checkは、スキーマのエラーを検出しません。
Graymatter

そしてそれの何が問題なのですか?
Mohammad Yahia

1

ピンチで実行する必要がある場合、および最初の列がデフォルトで作成された場合の1つのオプションは、必要な新しい列を作成し、それに内容をコピーして、基本的に古い列を「破棄」することです(それはそのままです)存在するが、使用/更新しないなど)

例:

alter table TABLE_NAME ADD COLUMN new_column_name TYPE NOT NULL DEFAULT '';
update TABLE_NAME set new_column_name = old_column_name;
update TABLE_NAME set old_column_name = ''; -- abandon old column, basically

これは列を残します(そして、それがNOT NULLで作成されたがデフォルトなしで作成された場合、それを無視する将来の挿入は失敗する可能性があります)が、それが使い捨てのテーブルである場合、トレードオフは受け入れられる可能性があります。それ以外の場合は、ここで説明した他の回答の1つを使用するか、列の名前を変更できる別のデータベースを使用してください。



-3

sqlite3 yourdb .dump> /tmp/db.txt
編集/tmp/db.txtで列名を変更作成行
sqlite2 yourdb2 </tmp/db.txt
mv / move yourdb2 yourdb


3
答えは何の情報も提供しません。コード/命令の束は、それが機能する理由や実行した場合に何が起こるかについての追加情報なしで吐き出されます
RGLSV
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.