簡體   English   中英

REFERENCES 兩個不同表中的兩個不同列

[英]REFERENCES two different columns in two different tables

在 Postgresql 數據庫中,我們有一個如下表:

=# SELECT * FROM toy_cars;
  serial_no |     name
------------+---------------
 199ER276FN | Snow Doctor
 8BE0F79A3R | Flatbed Truck
 D76185CE8G | Sand Speeder

=# SELECT * FROM toy_trains;
    serial_no    |    name
-----------------+-------------
 BMXH5R4T8K7KELD | Howler T140
 B1Q1JJDQW9LQN0G | Quakester
 8HO9240TO6RNNQ9 | Medusa 90

=# SELECT * FROM items_for_sale;
    serial_no    |   in_stock
-----------------+---------------
      199ER276FN | t
 BMXH5R4T8K7KELD | t
 B1Q1JJDQW9LQN0G | f
      8BE0F79A3R | f
 8HO9240TO6RNNQ9 | t
      D76185CE8G | f

筆記:

  • 每個serial_no列都是該表的主鍵,而in_stock是 boolean。

  • toy_cars表中的serial_no有一個正則表達式CHECK限制,只允許 10 個字符。

  • toy_trains表中的serial_no有一個正則表達式CHECK限制,只允許 15 個字符。

  • items_for_sale表中的serial_no是玩具汽車或火車的序列號,並且具有正則表達式CHECK限制,僅允許 10 或 15 個字符。

  • 所有serial_no列都有UNIQUE約束。

我們想在items_for_sale表中為serial_no添加一個REFERENCES檢查,以確保輸入的序列號存在於toy_cars表或toy_trains表中。

所以,如果我要嘗試INSERT INTO items_for_sale VALUES('KYVGK0DBYXPMWW8','f'); 這將失敗,因為該序列不存在於toy_carstoy_trains中。

如何才能做到這一點? 我們更喜歡使用一張表(就像它現在的結構一樣)。

這里的問題是您想檢查兩個(其他)表中是否存在鍵,並且您無法在單個列上使用外鍵約束來強制執行該操作。 Postgres 允許您為自定義檢查創建CHECK表達式,但正如手冊所述

PostgreSQL 不支持引用表數據的 CHECK 約束,而不是正在檢查的新行或更新行。 (...) 如果可能,請使用 UNIQUE、EXCLUDE 或 FOREIGN KEY 約束來表示跨行和跨表限制。

如果您想要的是在插入行時對其他行進行一次性檢查,而不是持續保持一致性保證,則可以使用自定義觸發器來實現它。

有關不同的解決方案,請參閱這個非常相關的問題

某些數據庫(MS SQL 服務器)允許您CHECK表達式中使用 function 那將是最佳的,但 Postgres 不允許這種語法。

對於 PostgreSQL,您需要創建一個TRIGGER ,該觸發器將在將某些內容插入items_for_sale時執行。 另一方面,這確實允許函數或跨表檢查。

它看起來像這樣:

CREATE TRIGGER check_serial_present
    BEFORE INSERT ON items_for_sale
    FOR EACH ROW
    EXECUTE FUNCTION assert_presence_of_serial(); -- implement this function

另一個鏈接的問題還提到了一種非常優雅的方式來實現這一點而無需觸發器:

沒有觸發器的干凈解決方案:添加冗余列並將它們包含在 FOREIGN KEY 約束中

我非常喜歡這個,因為它在概念上非常簡單且易於掌握。 認為它只涉及以下步驟:

  1. ALTER TABLE添加兩列: toy_car_serialtoy_trains_serial ,都是 NULLABLE,但在提到的表上有FOREIGN KEY約束。
  2. 確保任何INSERT都會將序列插入serial_notoy_car_serialserial_notoy_car_serial
  3. 添加CHECK( toy_car_serial = serial_no OR toy_trains_serial = serial_no)

我認為兩個冗余行和對插入的輕微修改比替代方案少得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM