Kunci asing di sqlite3 python

SQLite mendukung batasan kunci asing sejak 3.6.19 (14 Oktober 2009) - tetapi mereka tidak diberlakukan secara default (tetapi SQLite dapat menangani pernyataan create table dengan kunci asing bahkan sebelum itu)

Bahkan setelah 3.6.19, SQLite harus dikompilasi tanpa SQLITE_OMIT_FOREIGN_KEY dan tanpa SQLITE_OMIT_TRIGGER

Jika perintah ini tidak menghasilkan apa-apa (bukan 0 atau 1), kunci asing tidak didukung dengan eksekusi SQLIte saat ini

Contoh ular piton

Skrip Python sederhana berikut memberlakukan hubungan kunci asing dengan menyetel pragma foreign_keys = on

Mencoba menyisipkan record ke dalam tabel anak yang tidak memiliki record induk menyebabkan skrip membuang pengecualian sqlite3. IntegrityError. Batasan FOREIGN KEY gagal

Dokumen ini menjelaskan dukungan untuk kendala kunci asing SQL yang diperkenalkan di SQLite versi 3. 6. 19 (2009-10-14)

Bagian pertama memperkenalkan konsep kunci asing SQL dengan contoh dan mendefinisikan terminologi yang digunakan untuk sisa dokumen. Bagian 2 menjelaskan langkah-langkah yang harus diambil aplikasi untuk mengaktifkan batasan kunci asing di SQLite (dinonaktifkan secara default). Bagian selanjutnya, bagian 3, menjelaskan indeks yang harus dibuat pengguna untuk menggunakan batasan kunci asing, dan indeks yang harus dibuat agar batasan kunci asing berfungsi secara efisien. Bagian 4 menjelaskan fitur terkait kunci asing lanjutan yang didukung oleh SQLite dan bagian 5 menjelaskan cara perintah ALTER dan DROP TABLE ditingkatkan untuk mendukung batasan kunci asing. Terakhir, bagian 6 menyebutkan fitur yang hilang dan batasan implementasi saat ini

Dokumen ini tidak berisi deskripsi lengkap tentang sintaks yang digunakan untuk membuat batasan kunci asing di SQLite. Ini dapat ditemukan sebagai bagian dari dokumentasi untuk pernyataan CREATE TABLE

Batasan kunci asing SQL digunakan untuk menegakkan hubungan "ada" antar tabel. Misalnya, pertimbangkan skema database yang dibuat menggunakan perintah SQL berikut

CREATE TABLE artist(
  artistid    INTEGER PRIMARY KEY, 
  artistname  TEXT
);
CREATE TABLE track(
  trackid     INTEGER,
  trackname   TEXT, 
  trackartist INTEGER     -- Must map to an artist.artistid!
);

Aplikasi yang menggunakan database ini berhak untuk mengasumsikan bahwa untuk setiap baris dalam tabel lagu terdapat baris yang sesuai dalam tabel artis. Bagaimanapun, komentar dalam deklarasi mengatakan demikian. Sayangnya, jika pengguna mengedit database menggunakan alat eksternal atau jika ada bug dalam aplikasi, baris mungkin dimasukkan ke dalam tabel trek yang tidak sesuai dengan baris mana pun di tabel artis. Atau baris mungkin dihapus dari tabel artis, meninggalkan baris tanpa induk di tabel trek yang tidak sesuai dengan baris yang tersisa di artis. Ini dapat menyebabkan aplikasi atau aplikasi tidak berfungsi di kemudian hari, atau setidaknya membuat pengkodean aplikasi menjadi lebih sulit

Salah satu solusinya adalah menambahkan batasan kunci asing SQL ke skema database untuk menegakkan hubungan antara tabel artis dan track. Untuk melakukannya, definisi kunci asing dapat ditambahkan dengan memodifikasi deklarasi tabel track sebagai berikut

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
_

Dengan cara ini, kendala diberlakukan oleh SQLite. Upaya untuk menyisipkan baris ke dalam tabel trek yang tidak sesuai dengan baris mana pun di tabel artis akan gagal, seperti halnya mencoba menghapus baris dari tabel artis saat ada baris yang bergantung di tabel trek. Ada satu pengecualian. jika kolom kunci asing di tabel trek adalah NULL, maka tidak diperlukan entri yang sesuai di tabel artis. Dinyatakan dalam SQL, ini berarti bahwa untuk setiap baris dalam tabel track, ekspresi berikut dievaluasi menjadi true

trackartist IS NULL OR EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist)

Tip. Jika aplikasi memerlukan hubungan yang lebih ketat antara artis dan trek, di mana nilai NULL tidak diizinkan di kolom trackartist, cukup tambahkan batasan "NOT NULL" yang sesuai ke skema

Ada beberapa cara lain untuk menambahkan deklarasi kunci asing yang setara ke pernyataan CREATE TABLE. Lihat dokumentasi CREATE TABLE untuk detailnya

Sesi baris perintah SQLite berikut mengilustrasikan efek batasan kunci asing yang ditambahkan ke tabel trek

sqlite> SELECT * FROM artist;
artistid  artistname       
--------  -----------------
1         Dean Martin      
2         Frank Sinatra    

sqlite> SELECT * FROM track;
trackid  trackname          trackartist
-------  -----------------  -----------
11       That's Amore       1  
12       Christmas Blues    1  
13       My Way             2  

sqlite> -- This fails because the value inserted into the trackartist column (3)
sqlite> -- does not correspond to row in the artist table.
sqlite> INSERT INTO track VALUES(14, 'Mr. Bojangles', 3);
SQL error: foreign key constraint failed

sqlite> -- This succeeds because a NULL is inserted into trackartist. A
sqlite> -- corresponding row in the artist table is not required in this case.
sqlite> INSERT INTO track VALUES(14, 'Mr. Bojangles', NULL);

sqlite> -- Trying to modify the trackartist field of the record after it has 
sqlite> -- been inserted does not work either, since the new value of trackartist (3)
sqlite> -- Still does not correspond to any row in the artist table.
sqlite> UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles';
SQL error: foreign key constraint failed

sqlite> -- Insert the required row into the artist table. It is then possible to
sqlite> -- update the inserted row to set trackartist to 3 (since a corresponding
sqlite> -- row in the artist table now exists).
sqlite> INSERT INTO artist VALUES(3, 'Sammy Davis Jr.');
sqlite> UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles';

sqlite> -- Now that "Sammy Davis Jr." (artistid = 3) has been added to the database,
sqlite> -- it is possible to INSERT new tracks using this artist without violating
sqlite> -- the foreign key constraint:
sqlite> INSERT INTO track VALUES(15, 'Boogie Woogie', 3);

Seperti yang Anda harapkan, tidak mungkin untuk memanipulasi database ke keadaan yang melanggar batasan kunci asing dengan menghapus atau memperbarui baris dalam tabel artis.

sqlite> -- Attempting to delete the artist record for "Frank Sinatra" fails, since
sqlite> -- the track table contains a row that refer to it.
sqlite> DELETE FROM artist WHERE artistname = 'Frank Sinatra';
SQL error: foreign key constraint failed

sqlite> -- Delete all the records from the track table that refer to the artist
sqlite> -- "Frank Sinatra". Only then is it possible to delete the artist.
sqlite> DELETE FROM track WHERE trackname = 'My Way';
sqlite> DELETE FROM artist WHERE artistname = 'Frank Sinatra';

sqlite> -- Try to update the artistid of a row in the artist table while there
sqlite> -- exists records in the track table that refer to it. 
sqlite> UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin';
SQL error: foreign key constraint failed

sqlite> -- Once all the records that refer to a row in the artist table have
sqlite> -- been deleted, it is possible to modify the artistid of the row.
sqlite> DELETE FROM track WHERE trackname IN('That''s Amore', 'Christmas Blues');
sqlite> UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin';
_

SQLite menggunakan terminologi berikut

  • Tabel induk adalah tabel yang dirujuk oleh batasan kunci asing. Tabel induk pada contoh di bagian ini adalah tabel artis. Beberapa buku dan artikel menyebut ini sebagai tabel referensi, yang bisa dibilang lebih tepat, tetapi cenderung menimbulkan kebingungan

  • Tabel anak adalah tabel yang diterapkan batasan kunci asing dan tabel yang berisi klausa REFERENSI. Contoh di bagian ini menggunakan tabel track sebagai tabel anak. Buku dan artikel lain menyebut ini sebagai tabel referensi

  • Kunci induk adalah kolom atau sekumpulan kolom dalam tabel induk yang dirujuk oleh batasan kunci asing. Ini biasanya, tetapi tidak selalu, kunci utama dari tabel induk. Kunci induk harus berupa kolom atau kolom bernama di tabel induk, bukan

  • Kunci anak adalah kolom atau kumpulan kolom dalam tabel anak yang dibatasi oleh batasan kunci asing dan yang menyimpan klausa REFERENSI

Batasan kunci asing terpenuhi jika untuk setiap baris dalam tabel anak salah satu atau lebih kolom kunci anak adalah NULL, atau ada baris dalam tabel induk yang setiap kolom kunci induk berisi nilai yang sama dengan nilai di dalamnya

Pada paragraf di atas, istilah "sama" berarti sama ketika nilainya dibandingkan menggunakan aturan. Klarifikasi berikut berlaku

  • Saat membandingkan nilai teks, kolom yang terkait dengan kunci induk selalu digunakan

  • Saat membandingkan nilai, jika kolom kunci induk memiliki , afinitas tersebut diterapkan ke nilai kunci anak sebelum perbandingan dilakukan

Untuk menggunakan batasan kunci asing di SQLite, perpustakaan harus dikompilasi dengan atau tidak ditentukan. Jika SQLITE_OMIT_TRIGGER ditentukan tetapi SQLITE_OMIT_FOREIGN_KEY tidak, maka SQLite berperilaku seperti sebelum versi 3. 6. 19 (2009-10-14) - definisi kunci asing diuraikan dan dapat ditanyakan menggunakan , tetapi batasan kunci asing tidak diberlakukan. Perintahnya adalah no-op dalam konfigurasi ini. Jika OMIT_FOREIGN_KEY didefinisikan, maka definisi kunci asing bahkan tidak dapat diuraikan (mencoba menentukan definisi kunci asing adalah kesalahan sintaksis)

Dengan asumsi perpustakaan dikompilasi dengan batasan kunci asing yang diaktifkan, itu masih harus diaktifkan oleh aplikasi saat runtime, menggunakan perintah. Sebagai contoh

sqlite> PRAGMA foreign_keys = ON;

Batasan kunci asing dinonaktifkan secara default (untuk kompatibilitas mundur), jadi harus diaktifkan secara terpisah untuk setiap koneksi database. (Perhatikan, bagaimanapun, bahwa rilis SQLite di masa mendatang mungkin berubah sehingga batasan kunci asing diaktifkan secara default. Pengembang yang berhati-hati tidak akan membuat asumsi tentang apakah kunci asing diaktifkan secara default atau tidak, melainkan akan mengaktifkan atau menonaktifkannya seperlunya. ) Aplikasi juga dapat menggunakan pernyataan untuk menentukan apakah kunci asing saat ini diaktifkan. Sesi baris perintah berikut menunjukkan hal ini

sqlite> PRAGMA foreign_keys;
0
sqlite> PRAGMA foreign_keys = ON;
sqlite> PRAGMA foreign_keys;
1
sqlite> PRAGMA foreign_keys = OFF;
sqlite> PRAGMA foreign_keys;
0
_

Tip. Jika perintah "PRAGMA foreign_keys" tidak mengembalikan data alih-alih satu baris yang berisi "0" atau "1", maka versi SQLite yang Anda gunakan tidak mendukung kunci asing (baik karena lebih lama dari 3. 6. 19 atau karena dikompilasi dengan atau didefinisikan)

Tidak mungkin untuk mengaktifkan atau menonaktifkan batasan kunci asing di tengah transaksi multi-pernyataan (ketika SQLite tidak dalam mode autocommit). Mencoba melakukannya tidak menghasilkan kesalahan;

Biasanya, kunci induk dari batasan kunci asing adalah kunci utama dari tabel induk. Jika mereka bukan kunci utama, maka kolom kunci induk harus secara kolektif tunduk pada batasan UNIK atau memiliki indeks UNIK. Jika kolom kunci induk memiliki indeks UNIK, maka indeks tersebut harus menggunakan urutan susunan yang ditentukan dalam pernyataan CREATE TABLE untuk tabel induk. Sebagai contoh,

CREATE TABLE parent(a PRIMARY KEY, b UNIQUE, c, d, e, f);
CREATE UNIQUE INDEX i1 ON parent(c, d);
CREATE INDEX i2 ON parent(e);
CREATE UNIQUE INDEX i3 ON parent(f COLLATE nocase);

CREATE TABLE child1(f, g REFERENCES parent(a));                        -- Ok
CREATE TABLE child2(h, i REFERENCES parent(b));                        -- Ok
CREATE TABLE child3(j, k, FOREIGN KEY(j, k) REFERENCES parent(c, d));  -- Ok
CREATE TABLE child4(l, m REFERENCES parent(e));                        -- Error!
CREATE TABLE child5(n, o REFERENCES parent(f));                        -- Error!
CREATE TABLE child6(p, q, FOREIGN KEY(p, q) REFERENCES parent(b, c));  -- Error!
CREATE TABLE child7(r REFERENCES parent(c));                           -- Error!

Batasan kunci asing yang dibuat sebagai bagian dari tabel child1, child2 dan child3 semuanya baik-baik saja. Kunci asing yang dideklarasikan sebagai bagian dari tabel anak4 adalah kesalahan karena meskipun kolom kunci induk diindeks, indeksnya tidak UNIK. Kunci asing untuk tabel anak5 merupakan kesalahan karena meskipun kolom kunci induk memiliki indeks unik, indeks menggunakan urutan susunan yang berbeda. Tabel child6 dan child7 salah karena meskipun keduanya memiliki indeks UNIK pada kunci induknya, kunci tersebut tidak sama persis dengan kolom indeks UNIK tunggal

Jika skema database berisi kesalahan kunci asing yang memerlukan melihat lebih dari satu definisi tabel untuk mengidentifikasi, maka kesalahan tersebut tidak terdeteksi saat tabel dibuat. Sebaliknya, kesalahan seperti itu mencegah aplikasi menyiapkan pernyataan SQL yang mengubah konten tabel anak atau induk dengan cara yang menggunakan kunci asing. Kesalahan yang dilaporkan saat konten diubah adalah "kesalahan DML" dan kesalahan yang dilaporkan saat skema diubah adalah "kesalahan DDL". Jadi, dengan kata lain, kendala kunci asing yang salah konfigurasi yang mengharuskan melihat anak dan orang tua adalah kesalahan DML. Pesan kesalahan bahasa Inggris untuk kesalahan DML kunci asing biasanya "ketidakcocokan kunci asing" tetapi bisa juga "tidak ada tabel seperti itu" jika tabel induk tidak ada. Kesalahan DML kunci asing dilaporkan jika

  • Tabel induk tidak ada, atau
  • Kolom kunci induk yang disebutkan dalam batasan kunci asing tidak ada, atau
  • Kolom kunci induk yang disebutkan dalam batasan kunci asing bukan kunci utama dari tabel induk dan tidak tunduk pada batasan unik menggunakan urutan susunan yang ditentukan dalam CREATE TABLE, atau
  • Tabel anak mereferensikan kunci utama induk tanpa menentukan kolom kunci utama dan jumlah kolom kunci utama pada induk tidak cocok dengan jumlah kolom kunci anak

Peluru terakhir di atas diilustrasikan sebagai berikut

CREATE TABLE parent2(a, b, PRIMARY KEY(a,b));

CREATE TABLE child8(x, y, FOREIGN KEY(x,y) REFERENCES parent2);        -- Ok
CREATE TABLE child9(x REFERENCES parent2);                             -- Error!
CREATE TABLE child10(x,y,z, FOREIGN KEY(x,y,z) REFERENCES parent2);    -- Error!
_

Sebaliknya, jika kesalahan kunci asing dapat dikenali hanya dengan melihat definisi tabel anak dan tanpa harus berkonsultasi dengan definisi tabel induk, maka pernyataan CREATE TABLE untuk tabel anak gagal. Karena kesalahan terjadi selama perubahan skema, ini adalah kesalahan DDL. Kesalahan DDL kunci asing dilaporkan terlepas dari apakah batasan kunci asing diaktifkan atau tidak saat tabel dibuat

Indeks tidak diperlukan untuk kolom kunci anak tetapi hampir selalu bermanfaat. Kembali ke contoh di , setiap kali aplikasi menghapus satu baris dari tabel artis (tabel induk), aplikasi melakukan hal yang sama dengan pernyataan SELECT berikut untuk mencari baris referensi di tabel trek (tabel anak)

SELECT rowid FROM track WHERE trackartist = ?
_

di mana ? . Atau, lebih umum

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
_0

Jika SELECT ini mengembalikan baris apa pun, maka SQLite menyimpulkan bahwa menghapus baris dari tabel induk akan melanggar batasan kunci asing dan mengembalikan kesalahan. Kueri serupa dapat dijalankan jika konten kunci induk diubah atau baris baru dimasukkan ke dalam tabel induk. Jika kueri ini tidak dapat menggunakan indeks, kueri ini terpaksa melakukan pemindaian linier terhadap seluruh tabel anak. Dalam database non-sepele, ini mungkin sangat mahal

Jadi, di sebagian besar sistem nyata, indeks harus dibuat pada kolom kunci anak dari setiap batasan kunci asing. Indeks kunci anak tidak harus (dan biasanya tidak akan) indeks UNIK. Kembali lagi ke contoh di bagian 1, skema database lengkap untuk implementasi yang efisien dari batasan kunci asing mungkin

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
_1

Blok di atas menggunakan bentuk steno untuk membuat batasan kunci asing. Melampirkan klausa "REFERENSI " ke definisi kolom menciptakan batasan kunci asing yang memetakan kolom ke kunci utama dari. Lihat dokumentasi CREATE TABLE untuk detail lebih lanjut

4. 1. Batasan Kunci Asing Komposit

Batasan kunci asing komposit adalah batasan di mana kunci anak dan kunci induk keduanya adalah kunci komposit. Sebagai contoh, pertimbangkan skema database berikut

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
_2

Dalam sistem ini, setiap entri pada tabel lagu diharuskan untuk memetakan entri pada tabel album dengan kombinasi artis dan album yang sama.

Kunci orang tua dan anak harus memiliki kardinalitas yang sama. Dalam SQLite, jika salah satu kolom kunci anak (dalam hal ini penyanyi lagu dan album lagu) adalah NULL, maka tidak ada persyaratan untuk baris yang sesuai di tabel induk

4. 2. Batasan Kunci Asing yang Ditangguhkan

Setiap batasan kunci asing di SQLite diklasifikasikan sebagai langsung atau ditangguhkan. Kendala kunci asing langsung secara default. Semua contoh kunci asing yang disajikan sejauh ini merupakan kendala kunci asing langsung

Jika pernyataan memodifikasi isi database sehingga batasan kunci asing langsung melanggar kesimpulan pernyataan, pengecualian dilemparkan dan efek pernyataan dikembalikan. Sebaliknya, jika sebuah pernyataan mengubah isi database sedemikian rupa sehingga batasan kunci asing yang ditangguhkan dilanggar, pelanggaran tersebut tidak segera dilaporkan. Kendala kunci asing yang ditangguhkan tidak diperiksa sampai transaksi mencoba COMMIT. Selama pengguna memiliki transaksi terbuka, database dibiarkan ada dalam keadaan yang melanggar sejumlah batasan kunci asing yang ditangguhkan. Namun, COMMIT akan gagal selama batasan kunci asing tetap dilanggar

Jika pernyataan saat ini tidak di dalam transaksi eksplisit (blok BEGIN/COMMIT/ROLLBACK), maka transaksi implisit dilakukan segera setelah pernyataan selesai dijalankan. Dalam hal ini kendala yang ditangguhkan berperilaku sama dengan kendala langsung

Untuk menandai batasan kunci asing sebagai ditangguhkan, deklarasinya harus menyertakan klausa berikut

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
_3

Sintaks lengkap untuk menentukan batasan kunci asing tersedia sebagai bagian dari dokumentasi CREATE TABLE. Mengganti frase di atas dengan salah satu dari berikut menciptakan batasan kunci asing langsung

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
_4

The dapat digunakan untuk sementara mengubah semua batasan kunci asing menjadi ditangguhkan terlepas dari bagaimana mereka dideklarasikan

Contoh berikut mengilustrasikan efek penggunaan batasan kunci asing yang ditangguhkan

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
_5

Transaksi savepoint bersarang dapat RELEASE sementara database dalam keadaan yang tidak memenuhi batasan kunci asing yang ditangguhkan. Sebuah savepoint transaksi (savepoint non-nested yang dibuka sementara saat ini tidak ada transaksi terbuka), di sisi lain, tunduk pada batasan yang sama dengan COMMIT - mencoba untuk RELEASE saat database dalam keadaan seperti itu akan

Jika pernyataan COMMIT (atau RELEASE transaksi SAVEPOINT) gagal karena database saat ini dalam keadaan yang melanggar batasan kunci asing yang ditangguhkan dan saat ini ada titik penyimpanan bersarang, titik penyimpanan bersarang tetap terbuka

4. 3. Tindakan ON DELETE dan ON UPDATE

Klausa kunci asing ON DELETE dan ON UPDATE digunakan untuk mengonfigurasi tindakan yang terjadi saat menghapus baris dari tabel induk (ON DELETE), atau memodifikasi nilai kunci induk dari baris yang ada (ON UPDATE). Batasan kunci asing tunggal mungkin memiliki tindakan berbeda yang dikonfigurasikan untuk ON DELETE dan ON UPDATE. Tindakan kunci asing mirip dengan pemicu dalam banyak hal

Tindakan ON DELETE dan ON UPDATE yang terkait dengan setiap kunci asing dalam database SQLite adalah salah satu dari "NO ACTION", "RESTRICT", "SET NULL", "SET DEFAULT" atau "CASCADE". Jika suatu tindakan tidak ditentukan secara eksplisit, defaultnya adalah "TIDAK ADA TINDAKAN"

  • TIDAK ADA TINDAKAN. Mengkonfigurasi "TIDAK ADA TINDAKAN" berarti hanya itu. ketika kunci induk diubah atau dihapus dari database, tidak ada tindakan khusus yang dilakukan

  • MEMBATASI. Tindakan "RESTRICT" berarti bahwa aplikasi dilarang menghapus (untuk ON DELETE RESTRICT) atau memodifikasi (untuk ON UPDATE RESTRICT) kunci induk ketika ada satu atau lebih kunci anak yang dipetakan ke dalamnya. Perbedaan antara efek tindakan RESTRICT dan pemberlakuan batasan kunci asing normal adalah bahwa pemrosesan tindakan RESTRICT terjadi segera setelah bidang diperbarui - bukan di akhir pernyataan saat ini seperti halnya dengan batasan langsung, atau di akhir . Bahkan jika batasan kunci asing yang dilampirkan ditangguhkan, mengonfigurasi tindakan RESTRICT menyebabkan SQLite segera mengembalikan kesalahan jika kunci induk dengan kunci anak dependen dihapus atau dimodifikasi

  • SET NULL. Jika tindakan yang dikonfigurasi adalah "SET NULL", maka saat kunci induk dihapus (untuk ON DELETE SET NULL) atau diubah (untuk ON UPDATE SET NULL), kolom kunci anak dari semua baris dalam tabel anak yang dipetakan ke induk

  • SET STANDAR. Tindakan "SET DEFAULT" mirip dengan "SET NULL", kecuali bahwa setiap kolom kunci anak diatur untuk berisi nilai default kolom, bukan NULL. Lihat dokumentasi CREATE TABLE untuk detail tentang bagaimana nilai default ditetapkan ke kolom tabel

  • RIAM. Tindakan "CASCADE" menyebarkan operasi hapus atau perbarui pada kunci induk ke setiap kunci anak dependen. Untuk tindakan "ON DELETE CASCADE", ini berarti bahwa setiap baris dalam tabel anak yang dikaitkan dengan baris induk yang dihapus juga dihapus. Untuk tindakan "ON UPDATE CASCADE", ini berarti bahwa nilai yang disimpan di setiap kunci anak dependen dimodifikasi agar sesuai dengan nilai kunci induk yang baru

Misalnya, menambahkan klausa "ON UPDATE CASCADE" ke kunci asing seperti yang ditunjukkan di bawah meningkatkan skema contoh dari bagian 1 untuk memungkinkan pengguna memperbarui kolom artisid (kunci induk dari batasan kunci asing) tanpa merusak integritas referensial

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
_6

Mengonfigurasi tindakan ON UPDATE atau ON DELETE tidak berarti bahwa batasan kunci asing tidak perlu dipenuhi. Misalnya, jika tindakan "ON DELETE SET DEFAULT" dikonfigurasi, tetapi tidak ada baris di tabel induk yang sesuai dengan nilai default kolom kunci anak, menghapus kunci induk sementara kunci anak dependen masih ada menyebabkan kunci asing . Sebagai contoh

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
_7

Mereka yang akrab dengan pemicu SQLite akan memperhatikan bahwa tindakan "ON DELETE SET DEFAULT" yang ditunjukkan dalam contoh di atas memiliki efek yang serupa dengan pemicu AFTER DELETE berikut

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
_8

Setiap kali baris dalam tabel induk dari batasan kunci asing dihapus, atau ketika nilai yang disimpan dalam kolom atau kolom kunci induk diubah, urutan logis dari kejadian adalah

  1. Jalankan program pemicu SEBELUM yang berlaku,
  2. Periksa batasan lokal (bukan kunci asing),
  3. Perbarui atau hapus baris di tabel induk,
  4. Lakukan tindakan kunci asing yang diperlukan,
  5. Jalankan program pemicu SETELAH yang berlaku

Ada satu perbedaan penting antara tindakan kunci asing ON UPDATE dan pemicu SQL. Tindakan ON UPDATE hanya diambil jika nilai kunci induk diubah sehingga nilai kunci induk baru tidak sama dengan yang lama. Sebagai contoh

CREATE TABLE track(
  trackid     INTEGER, 
  trackname   TEXT, 
  trackartist INTEGER,
  FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
_9

Bagian ini menjelaskan cara perintah CREATE TABLE, ALTER TABLE, dan DROP TABLE berinteraksi dengan kunci asing SQLite

Perintah CREATE TABLE beroperasi sama atau tidak. Definisi kunci induk dari batasan kunci asing tidak diperiksa saat tabel dibuat. Tidak ada yang menghentikan pengguna untuk membuat definisi kunci asing yang merujuk ke tabel induk yang tidak ada, atau ke kolom kunci induk yang tidak ada atau tidak terikat secara kolektif oleh batasan PRIMARY KEY atau UNIQUE

Perintah ALTER TABLE bekerja secara berbeda dalam dua hal ketika batasan kunci asing diaktifkan

  • Tidak mungkin menggunakan "ALTER TABLE. Sintaks ADD COLUMN" untuk menambahkan kolom yang menyertakan klausa REFERENSI, kecuali jika nilai default kolom baru adalah NULL. Mencoba melakukannya mengembalikan kesalahan

  • Jika "ALTER TABLE. Perintah RENAME TO" digunakan untuk mengganti nama tabel yang merupakan tabel induk dari satu atau lebih batasan kunci asing, definisi batasan kunci asing dimodifikasi untuk merujuk ke tabel induk dengan nama barunya. Teks pernyataan CREATE TABLE anak atau pernyataan yang disimpan dalam tabel sqlite_schema dimodifikasi untuk mencerminkan nama tabel induk baru

Jika batasan kunci asing diaktifkan saat disiapkan, perintah DROP TABLE melakukan DELETE implisit untuk menghapus semua baris dari tabel sebelum menjatuhkannya. DELETE implisit tidak menyebabkan pemicu SQL apa pun untuk diaktifkan, tetapi dapat memicu tindakan kunci asing atau pelanggaran batasan. Jika batasan kunci asing langsung dilanggar, pernyataan DROP TABLE gagal dan tabel tidak dihapus. Jika batasan kunci asing yang ditangguhkan dilanggar, maka kesalahan dilaporkan saat pengguna mencoba melakukan transaksi jika pelanggaran batasan kunci asing masih ada pada saat itu. Setiap kesalahan "ketidakcocokan kunci asing" yang ditemui sebagai bagian dari DELETE implisit akan diabaikan

Maksud dari penyempurnaan perintah ALTER TABLE dan DROP TABLE ini adalah untuk memastikan bahwa keduanya tidak dapat digunakan untuk membuat database yang berisi pelanggaran kunci asing, setidaknya saat batasan kunci asing diaktifkan. Ada satu pengecualian untuk aturan ini. Jika kunci induk tidak tunduk pada batasan PRIMARY KEY atau UNIQUE yang dibuat sebagai bagian dari definisi tabel induk, tetapi tunduk pada batasan UNIQUE berdasarkan indeks yang dibuat menggunakan perintah CREATE INDEX, maka tabel anak dapat diisi tanpa . Jika indeks UNIK dihapus dari skema database, maka tabel induknya sendiri dihapus, tidak ada kesalahan yang akan dilaporkan. Namun database mungkin dibiarkan dalam keadaan di mana tabel anak dari batasan kunci asing berisi baris yang tidak merujuk ke baris tabel induk mana pun. Kasus ini dapat dihindari jika semua kunci induk dalam skema database dibatasi oleh kendala PRIMARY KEY atau UNIQUE yang ditambahkan sebagai bagian dari definisi tabel induk, bukan oleh indeks UNIQUE eksternal

Properti dari perintah DROP TABLE dan ALTER TABLE yang dijelaskan di atas hanya berlaku jika kunci asing diaktifkan. Jika pengguna menganggapnya tidak diinginkan, maka solusinya adalah menggunakan untuk menonaktifkan batasan kunci asing sebelum menjalankan perintah DROP atau ALTER TABLE. Tentu saja, sementara batasan kunci asing dinonaktifkan, tidak ada yang menghentikan pengguna untuk melanggar batasan kunci asing dan dengan demikian menciptakan database yang tidak konsisten secara internal.

Bagian ini mencantumkan beberapa batasan dan fitur yang dihilangkan yang tidak disebutkan di tempat lain

  1. Tidak ada dukungan untuk klausa MATCH. Menurut SQL92, klausa MATCH dapat dilampirkan ke definisi kunci asing gabungan untuk mengubah cara penanganan nilai NULL yang terjadi pada kunci anak. Jika "MATCH SIMPLE" ditentukan, maka kunci anak tidak harus sesuai dengan baris mana pun dari tabel induk jika satu atau lebih nilai kunci anak adalah NULL. Jika "MATCH FULL" ditentukan, maka jika salah satu nilai kunci anak adalah NULL, tidak ada baris terkait dalam tabel induk yang diperlukan, tetapi semua nilai kunci anak harus NULL. Akhirnya, jika batasan kunci asing dideklarasikan sebagai "MATCH PARTIAL" dan salah satu nilai kunci anak adalah NULL, harus ada setidaknya satu baris di tabel induk yang nilai kunci anak non-NULL cocok dengan nilai kunci induk

    SQLite mem-parsing klausa MATCH (mis. e. tidak melaporkan kesalahan sintaksis jika Anda menentukannya), tetapi tidak menerapkannya. Semua batasan kunci asing di SQLite ditangani seolah-olah MATCH SIMPLE ditentukan

  2. Tidak ada dukungan untuk mengalihkan batasan antara mode tertunda dan langsung. Banyak sistem memungkinkan pengguna untuk mengaktifkan batasan kunci asing individu antara dan mode langsung saat runtime (misalnya menggunakan perintah Oracle "SET CONSTRAINT"). SQLite tidak mendukung ini. Di SQLite, batasan kunci asing secara permanen ditandai sebagai ditangguhkan atau langsung saat dibuat

  3. Batas rekursi pada tindakan kunci asing. Pengaturan dan menentukan kedalaman maksimum yang diperbolehkan dari rekursi program pemicu. Untuk keperluan batasan ini, dianggap sebagai program pemicu. Pengaturan tidak mempengaruhi pengoperasian tindakan kunci asing. Tindakan kunci asing rekursif tidak dapat dinonaktifkan

    Bagaimana cara menggunakan kunci asing di sqlite3 Python?

    Perhatikan bahwa batasan kunci Asing tidak diaktifkan secara default di SQLite, Anda harus mengaktifkannya terlebih dahulu dengan menjalankan perintah berikut. PRAGMA foreign_keys = ON; Batasan kunci asing diperkenalkan di SQLite mulai dari versi 3. 6. 19.

    Bagaimana cara membuat sqlite3 kunci asing?

    Cara Menambahkan Kunci Asing ke Tabel yang Ada. Anda tidak dapat menggunakan pernyataan ALTER TABLE untuk menambahkan kunci asing di SQLite. Sebagai gantinya, Anda perlu mengganti nama tabel, membuat tabel baru dengan kunci asing, lalu menyalin data ke dalam tabel baru .

    Apa perbedaan antara referensi dan SQLite kunci asing?

    Kunci Referensi adalah kunci utama yang direferensikan di tabel lain. Di sisi lain, Foreign Key adalah cara Anda menautkan tabel kedua ke tabel utama Primary Key (atau Reference Key) .

    Apa itu kunci asing PRAGMA?

    pragma foreign_keys = on menerapkan kunci asing . Ini biasanya diperlukan karena secara default, SQLite tidak menerapkan kunci asing. Secara eksplisit mematikan validasi kunci asing mungkin berguna saat mengimpor a.