PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

KUNCI UTAMA Gabungan memberlakukan batasan NOT NULL pada kolom yang terlibat

Jika Anda membutuhkan untuk mengizinkan nilai NULL, gunakan UNIQUE kendala alih-alih PRIMARY KEY (dan tambahkan kolom PK pengganti, saya sarankan serial ). Ini memungkinkan kolom menjadi NULL:

CREATE TABLE distributor (
   distributor_id serial PRIMARY KEY
 , m_id integer
 , x_id integer
 , UNIQUE(m_id, x_id)
);

Catatan , namun (per dokumentasi):

Untuk tujuan batasan unik, nilai nol tidak dianggap sama.

Dalam kasus Anda, Anda dapat memasukkan sesuatu seperti (1, NULL) untuk (m_id, x_id) beberapa kali tanpa melanggar batasan. Postgres tidak pernah menganggap dua nilai NULL sama - sesuai definisi dalam standar SQL.

Jika Anda perlu memperlakukan NULL nilai sama dengan melarang "duplikat" tersebut, Saya melihat dua opsi :

1. Dua indeks parsial

Selain itu ke UNIQUE batasan di atas:

CREATE UNIQUE INDEX dist_m_uni_idx ON distributor (m_id) WHERE x_id IS NULL;
CREATE UNIQUE INDEX dist_x_uni_idx ON distributor (x_id) WHERE m_id IS NULL;

Tapi ini keluar dari tangan dengan cepat dengan lebih dari dua kolom yang bisa NULL. Lihat:

  • Buat batasan unik dengan kolom nol

2. Sebuah UNIQUE multi-kolom indeks pada ekspresi

Alih-alih kendala UNIK. Kami membutuhkan nilai default gratis yang tidak pernah ada di kolom yang terlibat, seperti -1 . Tambahkan CHECK batasan untuk melarangnya:

CREATE TABLE distributor (
   distributor serial PRIMARY KEY
 , m_id integer
 , x_id integer
 , CHECK (m_id &lt> -1)
 , CHECK (x_id &lt> -1)
);
CREATE UNIQUE INDEX distributor_uni_idx ON distributor (COALESCE(m_id, -1)
                                                      , COALESCE(x_id, -1))

Bagaimana RDBMS tertentu menangani berbagai hal tidak selalu merupakan indikator yang berguna untuk perilaku yang tepat. Petunjuk Postgres mengisyaratkan hal ini:

Itu berarti bahkan dengan adanya batasan unik, dimungkinkan untuk menyimpan baris duplikat yang berisi nilai nol di setidaknya salah satu kolom yang dibatasi. Perilaku ini sesuai dengan standar SQL, tetapi kami telah mendengar bahwa database SQL lain mungkin tidak mengikuti aturan ini .Jadi berhati-hatilah saat mengembangkan aplikasi yang dimaksudkan untuk portabel.

Penekanan saya yang berani.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Antara klausa dengan kolom string

  2. Di mana saya mendapatkan sumber libpq?

  3. Masalah untuk penyisipan menggunakan psycopg

  4. Tanggal PostgreSQL() dengan zona waktu

  5. Apa cara yang paling direkomendasikan untuk menyimpan waktu di PostgreSQL menggunakan Java?