SQLiteのテーブルに新しい列を挿入しますか?


354

私は列を持つテーブルを持っていますnameqtyrate。次に、列と列のCOLNew間に新しい列を追加する必要がnameありqtyます。2つの列の間に新しい列を追加するにはどうすればよいですか?

回答:


677

2つのオプションがあります。まず、次のように新しい列を追加するだけです。

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

2つ目は、さらに複雑ですが、実際に列を必要な場所に配置するには、テーブルの名前を変更します。

ALTER TABLE {tableName} RENAME TO TempOldTable;

次に、欠落している列を含む新しいテーブルを作成します。

CREATE TABLE {tableName} (name TEXT, COLNew {type} DEFAULT {defaultValue}, qty INTEGER, rate REAL);

そして、古いデータを入れます:

INSERT INTO {tableName} (name, qty, rate) SELECT name, qty, rate FROM TempOldTable;

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

DROP TABLE TempOldTable;

必要に応じてすべての名前を完全に変更できるので、2番目のオプションをお勧めします。


26
私は最初のオプションに行き、secendオプションのうちデフォルトのオプションを使用しますALTER TABLE {tableName} ADD COLUMN COLNew {type} DEFAULT {defaultValue}; より重要:(列を並べ替える理由を考えてください。)すべてのレコードアクション(挿入や追加など)で常に列名を使用してください。これにより、テーブルを変更した後にコードで間違いが発生することがなくなります。
michel.iamit 2013

5
ちなみに、一部のフィールドタイプでは、ALTER TABLEにデフォルト値を追加できません。sqlite.org/ lang_altertable.html
michel.iamit

9
インデックスを再作成することを忘れないでください
JanTuroň2014

5
トリガーも再作成する必要があります
Christopher K.

7
外部キーによって引き起こされる潜在的な制約違反を忘れないでください:「...しかし、外部キーアクションまたは制約違反を呼び出す可能性があります。」(sqlite.org/foreignkeys.html#fk_schemacommandsを参照); その間、回避策として外部キーを無効にすることができますPRAGMA foreign_keys = ON;sqlite.org/foreignkeys.html#fk_enableを参照)
Trinimon

112

SQLの他の列のに列追加するのではなく、追加するだけです。それらがどこに置かれるかは完全にDBMS次第です。カラムが正しい順序で出てくるようにするための適切な場所は、カラムを配置するときですselect

言い換えると、それらを順序どおりにしたい場合は{name,colnew,qty,rate}、以下を使用します。

select name, colnew, qty, rate from ...

SQLiteでは、次のようなalter table例を使用する必要があります。

alter table mytable add column colnew char(50)

2
SELECT * FROM mytable
EML 2014

新しい列の既存の行で指定しない場合、デフォルト値セットは何ですか?
ジェイコブ

12
select *まったく実行する必要があるユースケースはほとんどありません。テーブルのディスカバリーを行いたいプログラムには便利な場合がありますが、大部分の用途では、必要なもの、したがって必要な順序を明示的に指定する必要があります。
paxdiablo 2014

4
これが「受け入れられた答え」ではないのは正気ではありません。元の質問自体は、RDBMSのしくみがまったく理解されていないことを示しています。
VadaPoché17年

12

クエリで新しい列を追加できます

ALTER TABLE TableName ADD COLUMN COLNew CHAR(25)

ただし、既存の列の間ではなく、最後に追加されます。


11

SQLiteは、テーブルの最後に列を追加したり、テーブルの名前を変更したりするために使用できるALTER TABLEサポートを制限しています。

テーブルの構造にさらに複雑な変更を加える場合は、テーブルを再作成する必要があります。既存のデータを一時テーブルに保存し、古いテーブルを削除し、新しいテーブルを作成してから、一時テーブルからデータをコピーして戻すことができます。

たとえば、列名が「a」と「c」の「t1」という名前のテーブルがあり、このテーブルから列「b」を挿入するとします。次の手順は、これを行う方法を示しています。

BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,c);
INSERT INTO t1_backup SELECT a,c FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b, c);
INSERT INTO t1 SELECT a,c FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;

これで、次のように新しいデータを挿入する準備ができました。

UPDATE t1 SET b='blah' WHERE a='key'

私のテストでは、行INSERT INTO t1 SELECT a,c FROM t1_backup;によってエラーが発生します。「テーブルt1には3つの列がありますが、2つの値が指定されました:INSERT INTO t1 SELECT a、c FROM t1_backup;」。正しい行は次のようになりますINSERT INTO t1 (a,c) SELECT a,c FROM t1_backup;
JnLlnd

5
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
UPDATE {tableName} SET COLNew = {base on {type} pass value here};

この更新は、null値を処理するために必要であり、必要に応じてデフォルト値を入力します。あなたの場合と同様に、paxdiabloがすでに言ったように、SELECTクエリを呼び出す必要があり、列の順序を取得します。

SELECT name, colnew, qty, rate FROM{tablename}

私の意見では、カーソルから値を取得するための列名:

private static final String ColNew="ColNew";
String val=cursor.getString(cursor.getColumnIndex(ColNew));

したがって、インデックスが変更されても、アプリケーションで問題が発生することはありません。

これは、そうでない場合、CREATE temptableまたはRENAME tableまたはを使用CREATEしている場合、たとえばバッテリーが切れているときにトランザクションが発生した場合など、慎重に処理しないとデータが失われる可能性が高いという意味で安全な方法です。


4

私も同じ問題に直面しており、コメントに記載されているように、受け入れられた回答で提案されている2番目の方法は、外部キーを処理するときに問題になる可能性があります。

私の回避策は、データベースをSQLファイルにエクスポートして、INSERTステートメントに列名が含まれていることを確認することです。私はそのための便利な機能を備えたDBite for SQLiteを使用してそれを行います。その後、create tableステートメントを編集して、必要な場所に新しい列を挿入し、dbを再作成するだけです。

* nixのようなシステムでは、

cat db.sql | sqlite3 database.db

これが非常に大きなデータベースでどの程度実現可能かはわかりませんが、私の場合はうまくいきました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.