Masukkan kolom baru ke dalam tabel di sqlite?

354

Aku punya tabel dengan kolom name, qty, rate. Sekarang saya perlu menambahkan kolom baru COLNewdi antara kolom namedan qty. Bagaimana cara menambahkan kolom baru di antara dua kolom?

Penguji
sumber

Jawaban:

677

Anda memiliki dua opsi. Pertama, Anda bisa menambahkan kolom baru dengan yang berikut ini:

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

Kedua, dan lebih rumit, tetapi sebenarnya akan menempatkan kolom di tempat yang Anda inginkan, adalah mengganti nama tabel:

ALTER TABLE {tableName} RENAME TO TempOldTable;

Kemudian buat tabel baru dengan kolom yang hilang:

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

Dan isi dengan data lama:

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

Kemudian hapus tabel lama:

DROP TABLE TempOldTable;

Saya lebih suka opsi kedua, karena akan memungkinkan Anda untuk mengubah nama semuanya jika perlu.

Rasimaztion
sumber
27
Saya akan memilih opsi pertama, dan menggunakan opsi default dari opsi secend. ALTER TABLE {tableName} ADD COLUMN COLNew {type} DEFAULT {defaultValue}; Lebih penting: (memikirkan mengapa Anda ingin memesan kolom ..) gunakan dalam setiap aksi rekaman (seperti menyisipkan atau menambahkan) selalu nama kolom, dengan cara ini, Anda tidak akan pernah mendapatkan kesalahan di mana pun dalam kode Anda setelah mengubah tabel.
michel.iamit
5
Omong-omong: nilai default tidak dapat ditambahkan di ALTER TABLE untuk beberapa fieldtypes: sqlite.org/lang_altertable.html
michel.iamit
9
jangan lupa untuk membuat kembali indeks
Jan Turoň
5
Anda juga harus membuat ulang pemicu
Christopher K.
7
Jangan lupa potensi pelanggaran batasan yang disebabkan oleh kunci asing: "... tetapi dapat meminta tindakan kunci asing atau batasan kendala." (lihat sqlite.org/foreignkeys.html#fk_schemacommands ); sebagai solusi Anda dapat menonaktifkan kunci asing sementara itu: PRAGMA foreign_keys = ON;(lihat sqlite.org/foreignkeys.html#fk_enable )
Trinimon
112

Anda tidak menambahkan kolom antara kolom lain dalam SQL, Anda hanya menambahkannya. Di mana mereka ditempatkan sepenuhnya terserah pada DBMS. Tempat yang tepat untuk memastikan bahwa kolom keluar dalam urutan yang benar adalah ketika Anda selectmelakukannya.

Dengan kata lain, jika Anda menginginkannya dalam urutan {name,colnew,qty,rate}, Anda menggunakan:

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

Dengan SQLite, Anda perlu menggunakan alter table, contohnya adalah:

alter table mytable add column colnew char(50)
paxdiablo
sumber
2
SELECT * FROM mytable?
EML
Berapa nilai default yang ditetapkan jika kita tidak menentukannya di baris kolom baru yang ada?
Yakub
12
Ada sangat sedikit kasus penggunaan yang harus Anda lakukan select *sama sekali. Terkadang berguna untuk program yang ingin melakukan pencarian tabel tetapi, untuk sebagian besar penggunaan, Anda harus secara eksplisit menentukan apa yang Anda inginkan dan karenanya urutan yang Anda inginkan.
paxdiablo
4
Gila bagaimana ini bukan "jawaban yang diterima". Pertanyaan asli itu sendiri menunjukkan kurangnya pemahaman tentang bagaimana RDBMS bekerja.
Vada Poché
12

Anda dapat menambahkan kolom baru dengan kueri

ALTER TABLE TableName ADD COLUMN COLNew CHAR(25)

Tapi itu akan ditambahkan di akhir, bukan di antara kolom yang ada.

Mudassir
sumber
11

SQLite memiliki dukungan ALTER TABLE terbatas yang dapat Anda gunakan untuk menambahkan kolom ke ujung tabel atau mengubah nama tabel.

Jika Anda ingin membuat perubahan yang lebih kompleks dalam struktur tabel, Anda harus membuat ulang tabel. Anda dapat menyimpan data yang ada ke tabel sementara, letakkan tabel lama, buat tabel baru, lalu salin kembali data dari tabel sementara.

Misalnya, Anda memiliki tabel bernama "t1" dengan nama kolom "a" dan "c" dan Anda ingin menyisipkan kolom "b" dari tabel ini. Langkah-langkah berikut menggambarkan bagaimana ini bisa dilakukan:

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;

Sekarang Anda siap untuk memasukkan data baru seperti:

UPDATE t1 SET b='blah' WHERE a='key'
CJH
sumber
Dalam pengujian saya, baris INSERT INTO t1 SELECT a,c FROM t1_backup;menyebabkan kesalahan: "tabel t1 memiliki 3 kolom tetapi 2 nilai disediakan: INSERT INTO t1 SELECT a, c FROM t1_backup;". Baris yang benar adalahINSERT 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};

Pembaruan ini diperlukan untuk menangani nilai nol, dengan memasukkan nilai default seperti yang Anda butuhkan. Seperti dalam kasus Anda, Anda perlu menelepon SELECTpermintaan dan Anda akan mendapatkan urutan kolom, seperti yang sudah dikatakan paxdiablo :

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

dan menurut saya, nama kolom Anda untuk mendapatkan nilai dari kursor:

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

jadi jika indeks berubah, aplikasi Anda tidak akan menghadapi masalah.

Ini adalah cara yang aman dalam arti bahwa sebaliknya, jika Anda menggunakan CREATE temptableatau RENAME tableatau CREATE, akan ada kemungkinan tinggi kehilangan data jika tidak ditangani dengan hati-hati, misalnya dalam kasus di mana transaksi Anda terjadi saat baterai habis.

Naval Kishor Jha
sumber
4

Saya menghadapi masalah yang sama dan metode kedua yang diusulkan dalam jawaban yang diterima, seperti yang disebutkan dalam komentar, bisa bermasalah ketika berhadapan dengan kunci asing.

Solusi saya adalah mengekspor database ke file sql memastikan bahwa pernyataan INSERT menyertakan nama kolom. Saya melakukannya menggunakan DB Browser untuk SQLite yang memiliki fitur praktis untuk itu. Setelah itu Anda hanya perlu mengedit pernyataan buat tabel dan masukkan kolom baru di mana Anda inginkan dan buat ulang db.

Dalam * nix like systems hanyalah sesuatu yang sejalan

cat db.sql | sqlite3 database.db

Saya tidak tahu bagaimana layaknya ini dengan database yang sangat besar, tetapi ini berhasil dalam kasus saya.

Hirabayashi Taro
sumber