Perbedaan antara MATCH FULL, MATCH SIMPLE, dan MATCH PARTIAL?

29

Saya perhatikan MATCH SIMPLEdan MATCH FULL, tapi saya tidak mengerti apa yang mereka lakukan. Saya melihat default adalah MATCH SIMPLE; tetapi, bagaimana MATCHklausa lain untuk FOREIGN KEYfungsi kendala?

Evan Carroll
sumber

Jawaban:

38

Periksa CREATE TABLEhalaman manual :

Ada tiga jenis pencocokan: MATCH FULL, MATCH PARTIAL, dan MATCH SIMPLE (yang merupakan default). MATCH FULLtidak akan membiarkan satu kolom kunci asing multicolumn menjadi nol kecuali semua kolom kunci asing nol; jika semuanya nol, baris tidak harus memiliki kecocokan di tabel yang direferensikan. MATCH SIMPLEmemungkinkan salah satu kolom kunci asing menjadi nol; jika ada yang nol, baris tidak harus memiliki kecocokan di tabel yang direferensikan. MATCH PARTIALbelum diimplementasikan. (Tentu saja, NOT NULLkendala dapat diterapkan pada kolom referensi untuk mencegah kasus ini timbul.)

Juga, dalam bab tentang Kunci Asing :

Biasanya, baris referensi tidak perlu memenuhi batasan kunci asing jika ada kolom referensi yang nol. Jika MATCH FULL ditambahkan ke deklarasi kunci asing, baris referensi lolos memenuhi kendala hanya jika semua kolom referensi adalah nol (sehingga campuran nilai-nilai nol dan non-nol dijamin gagalMATCH FULL kendala). Jika Anda tidak ingin referensi baris dapat menghindari memenuhi batasan kunci asing, nyatakan kolom referensi sebagai NOT NULL.

Dan pastikan untuk berkonsultasi dengan manual saat ini atau versi yang cocok dengan instalasi Anda. Jangan jatuh cinta pada tautan Google yang sudah usang ke versi yang sudah ketinggalan zaman.

Erwin Brandstetter
sumber
7

FULL vs. SIMPLE vsPARTIAL

Meskipun jawaban yang dipilih benar, jika ini baru bagi Anda, Anda mungkin ingin melihatnya dengan kode - saya pikir lebih mudah untuk grok seperti itu.

-- one row with (1,1)
CREATE TABLE foo ( a int, b int,
  PRIMARY KEY (a,b)
);
INSERT INTO foo (a,b) VALUES (1,1);

--
-- two child tables to reference it
-- 
CREATE TABLE t_full ( a int, b int,
  FOREIGN KEY (a,b) REFERENCES foo MATCH FULL
);
CREATE TABLE t_simple ( a int, b int,
  FOREIGN KEY (a,b) REFERENCES foo MATCH SIMPLE
);

Secara logis, dengan FULLdan SIMPLE, kita dapat memasukkan kecocokan penuh.

-- works
INSERT INTO t_full (a,b) VALUES (1,1);
INSERT INTO t_simple (a,b) VALUES (1,1);

Masalahnya muncul ketika salah satu kolom NULL.

-- works
INSERT INTO t_simple (a,b) VALUES (1,NULL);

-- fails
INSERT INTO t_full (a,b) VALUES (1,NULL);

Masukkan ke dalam t_fullmenghasilkan kesalahan berikut,

ERROR:  insert or update on table "t_full" violates foreign key constraint "t_full_a_fkey"
DETAIL:  MATCH FULL does not allow mixing of null and nonnull key values.
INSERT 0 1

Ok, jadi bagaimana dengan (42,NULL)- ini adalah bagian yang selalu saya temukan membingungkan MATCH SIMPLE,

-- works
INSERT INTO t_simple (a,b) VALUES (42,NULL);

Perilaku di atas TIDAK akan berfungsi dengan yang tidak diterapkan MATCH PARTIAL, yang kemungkinan melakukan apa yang Anda inginkan untuk indeks gabungan di mana kolom paling kanan NULLdiedit. Namun, beberapa orang melihat itu sebagai metode membuka kotak Pandora dengan desain yang buruk.

Definisi & Mnemonik Sederhana

  • MATCH FULLsemuanya harus sepenuhnya cocok, atau semua kolom harusNULL
  • MATCH SIMPLEjika satu hal yang NULLmenjadi kendala hanya diabaikan.
  • MATCH PARTIALjika satu hal yang NULLfakta bahwa tidak semuanya NULLadalah sebagian diselamatkan dengan melakukan sesuatu yang masuk akal untuk tujuan kendala.

Catatan Spesifikasi SQL

Untuk anak cucu, berikut adalah definisi dari SQL Spec pada <match type>

  • MATCH SIMPLEjika setidaknya satu kolom referensi nol, maka baris tabel referensi melewati cek kendala. Jika semua kolom referensi tidak nol, maka baris melewati pemeriksaan kendala jika dan hanya jika ada baris dari tabel referensi yang cocok dengan semua kolom referensi.
  • MATCH PARTIAL: jika semua kolom referensi nol, maka baris tabel referensi melewati cek kendala. Jika setidaknya satu kolom referensi bukan nol, maka baris melewati pemeriksaan kendala jika dan hanya jika ada baris tabel referensi yang cocok dengan semua kolom referensi non-nol.
  • MATCH FULL: jika semua kolom referensi nol, maka baris tabel referensi melewati cek kendala. Jika semua kolom referensi tidak nol, maka baris melewati pemeriksaan kendala jika dan hanya jika ada baris dari tabel referensi yang cocok dengan semua kolom referensi. Jika beberapa kolom referensi nol dan kolom referensi lain adalah non-nol, maka baris tabel referensi melanggar cek kendala.

Walaupun ini bukan spesifik PostgreSQL contoh-contoh ini diperlihatkan dengan PostgreSQL

Evan Carroll
sumber