ตัวแปร 1
เนื่องจากทั้งหมดที่คุณต้องการคือคอลัมน์เดียวstandard = trueให้ตั้งค่ามาตรฐานเป็น NULL ในแถวอื่นทั้งหมด ดังนั้นUNIQUEข้อ จำกัดธรรมดาทำงานได้เนื่องจากค่า NULL ไม่ได้ละเมิด:
CREATE TABLE taxrate (
taxrate int PRIMARY KEY
, standard bool DEFAULT true
, CONSTRAINT standard_true_or_null CHECK (standard) -- yes, that's the whole constraint
, CONSTRAINT standard_only_1_true UNIQUE (standard)
);
DEFAULTเป็นการแจ้งเตือนเพิ่มเติมว่าแถวแรกที่ป้อนควรเป็นค่าเริ่มต้น มันไม่ได้บังคับอะไร ในขณะที่คุณไม่สามารถตั้งค่ามากกว่าหนึ่งแถวเป็นstandard = trueคุณยังคงสามารถตั้งค่าทุกแถว NULL ไม่มีวิธีที่สะอาดในการป้องกันสิ่งนี้ด้วยข้อ จำกัดเพียงอย่างเดียวในตารางเดียว CHECKข้อ จำกัด ไม่พิจารณาแถวอื่น (โดยไม่มีลูกเล่นสกปรก)
ที่เกี่ยวข้อง:
วิธีอัปเดต:
BEGIN;
UPDATE taxrate SET standard = NULL WHERE standard;
UPDATE taxrate SET standard = TRUE WHERE taxrate = 2;
COMMIT;
ในการอนุญาตให้ใช้คำสั่งเช่น (โดยที่ข้อ จำกัด นั้นเป็นที่พอใจในตอนท้ายของคำสั่ง):
WITH kingdead AS (
UPDATE taxrate
SET standard = NULL
WHERE standard
)
UPDATE taxrate
SET standard = TRUE
WHERE taxrate = 1;
.. UNIQUEจำกัด DEFERRABLEจะต้องมีการ ดู:
dbfiddle ที่นี่
ตัวแปร 2
มีตารางที่สองที่มีแถวเดียวเช่น:
สร้างสิ่งนี้เป็น superuser:
CREATE TABLE taxrate (
taxrate int PRIMARY KEY
);
CREATE TABLE taxrate_standard (
taxrate int PRIMARY KEY REFERENCES taxrate
);
CREATE UNIQUE INDEX taxrate_standard_singleton ON taxrate_standard ((true)); -- singleton
REVOKE DELETE ON TABLE taxrate_standard FROM public; -- can't delete
INSERT INTO taxrate (taxrate) VALUES (42);
INSERT INTO taxrate_standard (taxrate) VALUES (42);
ขณะนี้มีแถวเดียวชี้ไปที่มาตรฐานเสมอ (ในกรณีง่าย ๆ นี้ยังแสดงถึงอัตรามาตรฐานโดยตรงด้วย) มีเพียง superuser เท่านั้นที่สามารถทำลายมันได้ คุณอาจไม่อนุญาตด้วยเช่นBEFORE DELETEกัน
dbfiddle ที่นี่
ที่เกี่ยวข้อง:
คุณอาจเพิ่ม a VIEWเพื่อดูเช่นเดียวกับในตัวแปร 1 :
CREATE VIEW taxrate_combined AS
SELECT t.*, (ts.taxrate = t.taxrate) AS standard
FROM taxrate t
LEFT JOIN taxrate_standard ts USING (taxrate);
ในแบบสอบถามที่ทุกสิ่งที่คุณต้องการคืออัตรามาตรฐานให้ใช้ (เท่านั้น) taxrate_standard.taxrateโดยตรง
คุณเพิ่มในภายหลัง:
มี FK ระหว่างproducts.tax_rate_idและtax_rate.id
การใช้งานตัวแปรที่น่าสงสารของคนจน 2 คือเพียงเพิ่มแถวไปยังproducts(หรือตารางที่คล้ายกัน) ชี้ไปที่อัตราภาษีมาตรฐาน ผลิตภัณฑ์หุ่นที่คุณอาจเรียกว่า "อัตราภาษีมาตรฐาน" - หากการตั้งค่าของคุณอนุญาต
ข้อ จำกัด FK บังคับใช้ความสมบูรณ์ของการอ้างอิง หากต้องการทำให้เสร็จสมบูรณ์ให้บังคับใช้tax_rate_id IS NOT NULLแถว (หากไม่ใช่ในกรณีของคอลัมน์โดยทั่วไป) และไม่อนุญาตให้ลบทิ้ง ทั้งคู่สามารถนำไปใช้เป็นทริกเกอร์ ไม่มีโต๊ะเสริม แต่หรูหราน้อยกว่าและไม่น่าเชื่อถือ