Foreign-Key

兩個主列都指向同一個外部列的類似 EAV 的表

  • May 28, 2018

背景:我是一名程序員,雖然不得不多次使用簡單的數據庫,但從未使用過複雜的數據庫。即我精通基本的東西,但對高級功能和設計一無所知。

我需要創建一個包含兩個使用者之間匹配結果的表,即:

  • table_A: user_id (primary int), 其他東西
  • table_B:user1(指向table_A user_id的主外鍵),user2(指向table_A user_id的主外鍵),其他東西

我可以強制執行user2<user1嗎?這是為了防止行具有user1==user2防止在這對夫婦被倒置的情況下創建行,即我不需要同時擁有(alice,bob)(bob,alice)

-或者- 我一開始就做錯了,還有另一種完全不同的方法來做到這一點?

顯然我可以(並且將)在添加它們之前檢查這些值,但據我所知,如果我可以在 SQL 中添加一個約束,我最好添加它,以確保它是一致的。

數據庫目前是sqlite,但如果這不能在 sqlite 中完成但可以用其他引擎完成(特別是如果 InnoDB),它也可能是一個有用的答案。

PS:我不確定這是否仍算作 EAV,因為 AFAIK EAV 意味著來自不同表的兩個主要元素和一個額外的列,而我將擁有多個列。

一個簡單的 CHECK 約束就可以了:

$ sqlite
SQLite version 3.8.4.1 2014-03-11 15:27:36
...
sqlite> CREATE TABLE table_B(
  ...>     user1,
  ...>     user2,
  ...>     [other stuff],
  ...>     CHECK (user2 < user1)
  ...> );
sqlite> INSERT INTO table_B VALUES (1, 0);
sqlite> INSERT INTO table_B VALUES (2, 3);
Error: CHECK constraint failed: table_B

(這與 EAV 無關。)

此問題與 EAV(實體屬性值)無關 - 使用您選擇的搜尋引擎查找“Celko EAV”

不確定確切的語法,但是

CREATE TABLE table_b
(
 user1 VARCHAR(25),  -- or INTEGER, ideally of same types, otherwise comparisons are difficult
 user2 VARCHAR(25),  -- or INTEGER
 --  
 -- other fields,
 --
 CONSTRAINT table_b_pk PRIMARY KEY (user_1, ...), 
 -- maybe other fields in the PK - not clear from question
 CONSTRAINT table_b_uq UNIQUE (user_1, user2), 
 -- so that the combination (user_1, user_2) can't be duplicated 
 CONSTRAINT user_1_ne_user_2  CHECK (user1 != user2)  
 -- this will enforce user_1 not equal to user_2 regardless of the sorting of the strings 
 -- you could have CHECK (user1 < user2) if that is key to your requirements
 -- it doesn't appear to be critical from the question.
);

應該工作 - 它在 Firebird 嵌入。

AIUI(據我了解),SQLite 不支持CHECK約束中的子查詢(* 紅鯡魚 - 見下文 - 我的原句模棱兩可且令人困惑)。這種情況不需要CHECK約束中的子查詢,無論如何只有 Firebird 支持。

約束將處理您的 ( alice, bob) - ( bob, alice) 問題。

引用自:https://dba.stackexchange.com/questions/62389