Bagaimana cara mengganti nama kolom dalam tabel database SQLite?

296

Saya perlu mengganti nama beberapa kolom di beberapa tabel dalam database SQLite. Saya tahu bahwa pertanyaan serupa telah ditanyakan pada stackoverflow sebelumnya, tapi itu untuk SQL secara umum, dan kasus SQLite tidak disebutkan.

Dari dokumentasi SQLite untuk ALTER TABLE , saya berpendapat bahwa tidak mungkin melakukan hal seperti itu "dengan mudah" (yaitu pernyataan ALTER TABLE tunggal).

Saya bertanya-tanya seseorang tahu tentang cara SQL generik melakukan hal seperti itu dengan SQLite.

joce
sumber
Anda dapat melakukannya dengan menggunakan peramban db untuk sqlite cukup mudah
Matt G
1
Silakan pertimbangkan menandai jawaban ini sebagai stackoverflow.com/a/52346199/124486 yang
Evan Carroll

Jawaban:

66

Ini baru saja diperbaiki dengan 2018-09-15 (3.25.0)

Perangkat tambahan yang ALTER TABLEperintah:

  • Tambahkan dukungan untuk mengganti nama kolom dalam tabel menggunakan ALTER TABLEtabel RENAME COLUMN oldname TO newname.
  • Perbaiki fitur ganti nama tabel sehingga juga memperbarui referensi ke tabel yang diubah namanya di pemicu dan tampilan.

Anda dapat menemukan sintaks baru yang didokumentasikan di bawah ALTER TABLE

The RENAME COLUMN TOsintaks mengubah kolom-nama tabel tabel-nama ke yang baru-kolom-nama. Nama kolom diubah baik dalam definisi tabel itu sendiri dan juga dalam semua indeks, pemicu, dan tampilan yang merujuk kolom. Jika perubahan nama kolom akan menghasilkan ambiguitas semantik pada pemicu atau tampilan, maka RENAME COLUMNgagal dengan kesalahan dan tidak ada perubahan yang diterapkan.

masukkan deskripsi gambar di sini Sumber gambar: https://www.sqlite.org/images/syntax/alter-table-stmt.gif

Contoh:

CREATE TABLE tab AS SELECT 1 AS c;

SELECT * FROM tab;

ALTER TABLE tab RENAME COLUMN c to c_new;

SELECT * FROM tab;

demo db-fiddle.com


Dukungan Android

Pada saat penulisan, Android 27 API menggunakan paket SQLite versi 3.19 .

Berdasarkan versi saat ini bahwa Android menggunakan dan bahwa pembaruan ini datang dalam versi 3.25.0 dari SQLite, saya akan mengatakan Anda memiliki sedikit menunggu (sekitar API 33) sebelum dukungan untuk ini ditambahkan ke Android.

Dan, bahkan kemudian, jika Anda perlu mendukung versi yang lebih lama dari API 33, Anda tidak akan dapat menggunakan ini.

Lukasz Szozda
sumber
8
Saya menerapkan migrasi Android dan sayangnya IntelliJ menunjukkan peringatan bahwa itu bukan perintah SQL yang valid. database.execSQL("ALTER TABLE content RENAME COLUMN archiveCount TO dismissCount"). COLUM berwarna merah dan dikatakan UNTUK diharapkan, mendapat 'COLUMN' . Sayangnya Android masih menggunakan SQLite versi 3.19, itulah mengapa ini tidak berhasil untuk saya.
Adam Hurwitz
1
diedit: Saya temukan pada system.data.sqlite.org/index.html/doc/trunk/www/faq.wiki#q1 , bahwa 1.0.109.x) sebenarnya menggunakan SQLite 3.24 dan System.Data.SQLite menggunakan SQLite 3.25 dijadwalkan dirilis bulan ini.
rychlmoj
1
FYI, sayangnya ini belum diimplementasikan oleh perpustakaan SQLite Android . Semoga mereka segera memperbarui.
Adam Hurwitz
3
Saya menambahkan bagian untuk Dukungan Android untuk mencegah orang lain menaikkan harapan mereka. Berdasarkan Android 27 saat ini menggunakan SQLite 3.19, kita harus menunggu hingga API 33 sebelum fitur ini ditambahkan ke Android, dan itupun hanya akan didukung pada versi terbaru. Mendesah.
Joshua Pinter
1
@ JoshuaPinter Terima kasih telah memperluas jawaban saya.
Lukasz Szozda
448

Katakanlah Anda memiliki tabel dan perlu mengganti nama "colb" menjadi "col_b":

Pertama Anda mengganti nama tabel lama:

ALTER TABLE orig_table_name RENAME TO tmp_table_name;

Kemudian buat tabel baru, berdasarkan tabel lama tetapi dengan nama kolom yang diperbarui:

CREATE TABLE orig_table_name (
  col_a INT
, col_b INT
);

Kemudian salin konten di seberang tabel asli.

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

Terakhir, jatuhkan meja lama.

DROP TABLE tmp_table_name;

Membungkus semua ini dalam BEGIN TRANSACTION;dan COMMIT;mungkin juga merupakan ide yang bagus.

Evan
sumber
51
Dan jangan lupa indeks Anda.
Tom Mayfield
11
Sangat penting kode contoh di atas tidak ada transaksi. Anda harus membungkus semuanya dalam BEGIN / END (atau ROLLBACK) untuk memastikan bahwa penggantian nama berhasil atau tidak sama sekali.
Roger Binns
4
Siapa pun yang ingin melakukan ini di android dapat menerapkan transaksi menggunakan SQLiteDatabase.beginTransaction ()
bmaupin
7
Tidak ada dalam kode dalam jawaban yang menyalin indeks. Membuat tabel kosong dan memasukkan data ke dalamnya hanya menyalin struktur dan data. Jika Anda menginginkan metadata (indeks, kunci asing, batasan, dll.), Maka Anda juga harus mengeluarkan pernyataan untuk membuatnya di tabel yang diganti.
Tom Mayfield
17
.schemaPerintah SQLite berguna untuk menampilkan CREATE TABLEpernyataan yang membuat tabel yang ada. Anda dapat mengambil outputnya, memodifikasi seperlunya, dan menjalankannya untuk membuat tabel baru. Perintah ini juga menunjukkan CREATE INDEXperintah yang diperlukan untuk membuat indeks, yang harus mencakup keprihatinan Thomas. Tentu saja, pastikan untuk menjalankan perintah ini sebelum mengubah apa pun.
Mike DeSimone
56

Menggali, saya menemukan alat grafis multiplatform (Linux | Mac | Windows) yang disebut DB Browser untuk SQLite yang sebenarnya memungkinkan seseorang untuk mengubah nama kolom dengan cara yang sangat ramah pengguna!

Edit | Ubah Tabel | Pilih Tabel | Edit Field. Klik klik! Voila!

Namun, jika seseorang ingin berbagi cara terprogram untuk melakukan ini, saya akan senang mengetahui!

joce
sumber
1
Ada juga add-on Firefox yang melakukan hal yang sama , Klik kanan kolom yang ingin Anda ganti namanya dan pilih "Edit Kolom".
Jacob Hacker
1
Bahkan di openSUSE, tersedia dalam satu paket: software.opensuse.org/package/sqlitebrowser
Aneh karena memiliki begitu banyak suara. Kita berbicara tentang pemrograman di sini (kode). Mengapa Anda mengirim jawaban ini di sini?
user25
2
Tidak disebutkan bagaimana melakukan ini dengan kode dalam pertanyaan saya. Saya hanya ingin tahu cara mengganti nama kolom dalam DB SQLite.
bergabung
@ Joce, aku mencintaimu !!! (seperti saudara laki-laki) mengubah saya di ladang, voila. Saya telah mengekspor tabel MS Access ke SQLite dan salah satu bidang memiliki angka di depan: 3YearLetterSent. Visual Studio membuat kelas dari tabel tetapi tersendat pada angka "3" di depan nama bidang. Saya sudah tahu ini, hanya tidak menonton.
JustJohn
53

Meskipun benar bahwa tidak ada ALTER COLUMN, jika Anda hanya ingin mengubah nama kolom, jatuhkan batasan NOT NULL, atau ubah tipe data, Anda dapat menggunakan serangkaian perintah berikut:

Catatan: Perintah-perintah ini berpotensi merusak database Anda, jadi pastikan Anda memiliki cadangan

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;

Anda harus menutup dan membuka kembali koneksi Anda atau menyedot database untuk memuat ulang perubahan ke dalam skema.

Sebagai contoh:

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  

DAFTAR PUSTAKA BERIKUT:


pragma writable_schema
Ketika pragma ini aktif, tabel SQLITE_MASTER di mana database dapat diubah menggunakan pernyataan UPDATE, INSERT, dan DELETE biasa. Peringatan: penyalahgunaan pragma ini dapat dengan mudah menghasilkan file basis data yang rusak.

alter table
SQLite mendukung subset terbatas dari ALTER TABLE. Perintah ALTER TABLE dalam SQLite memungkinkan pengguna untuk mengubah nama tabel atau menambahkan kolom baru ke tabel yang sudah ada. Tidak mungkin untuk mengganti nama kolom, menghapus kolom, atau menambah atau menghapus batasan dari tabel.

SINTETIA TABEL ALTER

Nuh
sumber
3
Berbahaya, tetapi mungkin masih merupakan jawaban imo yang paling mudah.
Tek
2
Ya sangat cepat - Berbahaya hanya berarti "Pastikan Anda memiliki cadangan pertama"
Noah
6
Format file sqlite sangat sederhana dan itulah mengapa operasi ini valid. Format file hanya memiliki dua set informasi tentang tabel: Perintah CREATE TABLE yang sebenarnya sebagai teks biasa, dan baris, yang nilainya muncul dalam urutan bidang dari perintah CREATE. Yang berarti bahwa kode sqlite membuka database, ia mem-parsing setiap perintah BUAT dan secara dinamis membangun informasi kolomnya dalam memori. Jadi, perintah apa pun yang mengubah perintah BUAT dengan cara yang berakhir dengan jumlah kolom yang sama akan berfungsi, bahkan jika Anda mengubah jenis atau batasannya.
Thomas Tempelmann
3
@ThomasTempelmann Namun, menambahkan kendala yang tidak dipenuhi oleh dataset akan menghasilkan masalah karena perencana permintaan mengasumsikan bahwa kendala terus.
fuz
2
@ThomasTempelmann Menghapus kendala selalu baik-baik saja. Menambahkan batasan tidak apa-apa jika kendala dipenuhi oleh semua baris tetapi Anda tentu perlu memeriksa.
fuz
18

Baru-baru ini saya harus melakukan itu di SQLite3 dengan tabel bernama poin dengan colunms id, lon, lat . Secara keliru, ketika tabel diimpor, nilai-nilai untuk lintang tempat disimpan dalam kolom lon dan sebaliknya, jadi perbaikan yang jelas akan mengubah nama kolom tersebut. Jadi triknya adalah:

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;

Saya harap ini bermanfaat bagi Anda!

aizquier
sumber
Metode ini tidak menyalin nilai PK dengan tepat dan secara otomatis membuat kolom rowid tersembunyi. Belum tentu masalah tetapi ingin menunjukkan itu karena itu menjadi masalah bagi saya.
TPoschel
4
Bukankah lebih mudah untuk melakukan "SET UPDATE poin lon = lat, lat = lon;"?
kstep
1
Jawaban ini memang melakukan proses dalam PESANAN yang benar. Pertama buat tabel temp dan populasikan lalu hancurkan yang asli .
Xeoncross
14

Mengutip dokumentasi sqlite :

SQLite mendukung subset terbatas dari ALTER TABLE. Perintah ALTER TABLE dalam SQLite memungkinkan pengguna untuk mengubah nama tabel atau menambahkan kolom baru ke tabel yang sudah ada. Tidak mungkin untuk mengubah nama colum, menghapus kolom, atau menambah atau menghapus batasan dari tabel.

Yang bisa Anda lakukan tentu saja adalah, buat tabel baru dengan tata letak baru SELECT * FROM old_table,, dan isi tabel baru dengan nilai-nilai yang akan Anda terima.

Elazar Leibovich
sumber
7

Pertama, ini adalah salah satu hal yang mengejutkan saya: mengganti nama kolom membutuhkan membuat tabel yang sama sekali baru dan menyalin data dari tabel lama ke tabel baru ...

GUI yang saya gunakan untuk melakukan operasi SQLite adalah Base . Itu punya jendela Log bagus yang menunjukkan semua perintah yang telah dieksekusi. Melakukan penggantian nama kolom melalui Base mengisi jendela log dengan perintah yang diperlukan:

Jendela log dasar

Ini kemudian dapat dengan mudah disalin dan ditempel di mana Anda mungkin membutuhkannya. Bagi saya, itu menjadi file migrasi ActiveAndroid . Sentuhan yang bagus, juga, adalah bahwa data yang disalin hanya mencakup perintah SQLite, bukan cap waktu, dll.

Semoga itu menghemat waktu beberapa orang.

Joshua Pinter
sumber
FYI, jika Anda sedang menggunakan ActiveAndroid , Anda dapat menghilangkan BEGIN TRANSACTION;dan COMMIT;garis, sebagai ActiveAndroid pegangan yang dengan sendirinya.
Joshua Pinter
6

KASUS 1: SQLite 3.25.0+

Hanya Versi 3.25.0 dari SQLite yang mendukung penggantian nama kolom. Jika perangkat Anda memenuhi persyaratan ini, semuanya cukup sederhana. Kueri di bawah ini akan menyelesaikan masalah Anda:

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

KASUS 2: SQLite Versi Lama

Anda harus mengikuti Pendekatan yang berbeda untuk mendapatkan hasil yang mungkin sedikit rumit

Misalnya, jika Anda memiliki tabel seperti ini:

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

Dan jika Anda ingin mengubah nama kolom Location

Langkah 1: Ganti nama tabel asli:

ALTER TABLE student RENAME TO student_temp;

Langkah 2: Sekarang buat tabel baru studentdengan nama kolom yang benar:

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

Langkah 3: Salin data dari tabel asli ke tabel baru:

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

Catatan: Perintah di atas harus semuanya satu baris.

Langkah 4: Jatuhkan tabel asli:

DROP TABLE student_temp;

Dengan empat langkah ini, Anda dapat mengubah tabel SQLite secara manual. Ingatlah bahwa Anda juga harus membuat ulang indeks, pemirsa, atau pemicu di tabel baru juga.

Febin Mathew
sumber
1
Bagaimana cara meng-upgrade versi database sqllite ke 3.29.0 di studio android Saya menggunakan api level 28.
Nathani Software
Versi SQLite didefinisikan oleh perangkat tempat App bekerja. Ini tergantung perangkat.
Febin Mathew
1
Bagi orang yang menggunakan sqlite lama, empat langkah di atas tidak disarankan. Lihat bagian "Perhatian" di sqlite.org/lang_altertable.html .
Jeff
3

ubah kolom tabel <id> menjadi <_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");
Vahe Gharibyan
sumber
3

Buat kolom baru dengan nama kolom yang diinginkan: COLNew.

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

Salin konten kolom lama COLOld ke kolom baru COLNew.

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

Catatan: tanda kurung diperlukan pada baris di atas.

Anthony Ebert
sumber
2

Seperti disebutkan sebelumnya, ada alat Database Browser SQLite, yang melakukan ini. Untungnya, alat ini menyimpan log dari semua operasi yang dilakukan oleh pengguna atau aplikasi. Lakukan ini sekali dan melihat log aplikasi, Anda akan melihat kode yang terlibat. Salin kueri dan rekatkan sesuai kebutuhan. Bekerja untukku. Semoga ini membantu

Chris Lytridis
sumber
2

Dari dokumentasi resmi

Prosedur yang lebih sederhana dan lebih cepat secara opsional dapat digunakan untuk beberapa perubahan yang tidak mempengaruhi konten pada disk dengan cara apa pun. Prosedur sederhana berikut ini sesuai untuk menghapus PERIKSA atau KUNCI ASING atau BUKAN NULL kendala, mengganti nama kolom , atau menambah atau menghapus atau mengubah nilai default pada kolom.

  1. Mulai transaksi.

  2. Jalankan PRAGMA schema_version untuk menentukan nomor versi skema saat ini. Nomor ini akan diperlukan untuk langkah 6 di bawah ini.

  3. Aktifkan pengeditan skema menggunakan PRAGMA writable_schema = ON.

  4. Jalankan pernyataan UPDATE untuk mengubah definisi tabel X di tabel sqlite_master: UPDATE sqlite_master SET sql = ... WHERE type = 'table' AND name = 'X';

    Perhatian: Membuat perubahan ke tabel sqlite_master seperti ini akan membuat database rusak dan tidak dapat dibaca jika perubahan tersebut mengandung kesalahan sintaksis. Disarankan bahwa pengujian yang cermat atas pernyataan UPDATE dilakukan pada database kosong terpisah sebelum menggunakannya pada database yang berisi data penting.

  5. Jika perubahan ke tabel X juga memengaruhi tabel atau indeks lain atau pemicu adalah tampilan dalam skema, maka jalankan pernyataan UPDATE untuk mengubah indeks dan tampilan tabel lainnya juga. Misalnya, jika nama kolom berubah, semua kendala, pemicu, indeks, dan tampilan ASE KUNCI LUAR NEGERI harus diubah.

    Perhatian: Sekali lagi, membuat perubahan pada tabel sqlite_master seperti ini akan membuat database menjadi rusak dan tidak dapat dibaca jika perubahan tersebut mengandung kesalahan. Hati-hati menguji seluruh prosedur ini pada basis data pengujian terpisah sebelum menggunakannya pada database yang berisi data penting dan / atau membuat salinan cadangan dari basis data penting sebelum menjalankan prosedur ini.

  6. Tambahkan nomor versi skema menggunakan PRAGMA schema_version = X di mana X adalah satu lebih dari jumlah versi skema yang ditemukan pada langkah 2 di atas.

  7. Nonaktifkan pengeditan skema menggunakan PRAGMA writable_schema = OFF.

  8. (Opsional) Jalankan PRAGMA integrity_check untuk memverifikasi bahwa perubahan skema tidak merusak database.

  9. Komit transaksi dimulai pada langkah 1 di atas.

Mohammad Yahia
sumber
PRAGMA integrity_check tidak mengambil kesalahan dengan skema.
Graymatter
dan apa masalahnya dengan itu?
Mohammad Yahia
1

Salah satu opsi, jika Anda perlu melakukannya dalam keadaan darurat, dan jika kolom awal Anda dibuat dengan default, adalah membuat kolom baru yang Anda inginkan, menyalin konten ke sana, dan pada dasarnya "meninggalkan" kolom lama (tetap ada hadir, tetapi Anda tidak menggunakan / memperbaruinya, dll.)

ex:

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

Ini meninggalkan kolom (dan jika itu dibuat dengan TIDAK NULL tetapi tanpa default, maka sisipan di masa depan yang mengabaikannya mungkin gagal), tetapi jika itu hanya tabel sekali pakai, pengorbanan mungkin dapat diterima. Kalau tidak, gunakan salah satu jawaban lain yang disebutkan di sini, atau database lain yang memungkinkan penggantian nama kolom.

rogerdpack
sumber
-3

sqlite3 yourdb .dump> /tmp/db.txt
sunting /tmp/db.txt ubah nama kolom di Buat baris
sqlite2 yourdb2 </tmp/db.txt
mv / pindahkan yourdb2 yourdb

H Bosch
sumber
3
jawaban Anda tidak memberikan informasi apa pun, banyak kode / instruksi yang dikeluarkan tanpa informasi tambahan tentang mengapa Anda pikir itu akan berhasil atau apa yang seharusnya terjadi jika Anda menjalankannya
RGLSV