2012-03-24 117 views
1

澄清 - 表中最多有4個不同的玩家,由他們的ID引用。我想強制執行,即沒有兩個ID是相同的。這個SQL約束可以被寫得更簡單嗎?

另外,因爲它最多有4名玩家,所以有些可能爲空。可能有許多像這樣的空值是一個壞主意?我不認爲它確實如此,但可以肯定的是,null == null返回false?

... 
CHECK (playerid1 <> playerid2) 
    AND (playerid1 <> playerid3) 
    AND (playerid1 <> playerid4) 
    AND (playerid2 <> playerid3) 
    AND (playerid2 <> playerid4) 
    AND (playerid3 <> playerid4) 
... 

謝謝!

+0

是否有一個共同的列,就像一個遊戲ID或東西嗎?你總是可以使用'player1 NOT IN(SELECT playerid FROM table WHERE gameid = thisgameid)'(或某種傳真) – 2012-03-24 20:25:32

+0

你說'每個表格中最多有4名玩家',但是你想強制檢查約束?當playerid爲null或0時會發生什麼? – dwerner 2012-03-24 20:34:22

+0

@BradChristie,我會試試看,大概'CHECK player1 NOT IN..'會是有效的語法嗎? @dwerner,這就是爲什麼我想澄清關於null == null返回false的情況,在這種情況下,可能會有2名玩家和2個null,並且如果兩名玩家不同,它將通過支票。 – c24w 2012-03-24 20:42:01

回答

10

我會使用一個單獨的表是:

create table game_players (
     game_id number, player_id number, player_position number 
    ); 

然後你就可以添加

  • UNIQUE約束的game_id +玩家ID(強制玩家不會發生超過每場比賽)
  • 一次game_id + player_position(以確保位置的唯一性約束最多由一個播放器)
  • CHECK約束佔用player_position只執行它有值1,2,3或4

這應該實現你想要的更清潔(恕我直言)的方式。

+0

+1。 'player1,player2,player3,player4'-like視圖可以以[VIEW](http://www.h2database.com/html/grammar.html#create_view)的形式實現。 – 2012-03-24 20:49:51

+0

我沒有想過查看複合UNIQUE約束或者任何你可能稱之爲的約束。謝謝! – c24w 2012-03-24 20:52:14

+0

@ c24w:不是合成的,這個答案建議在多對多表之間。 「遊戲」表只有一個「玩家」字段,而不是四個。 – Andomar 2012-03-24 22:34:18

1

在你的七種表情中,你有重複例如(playerid1 <> playerid2)。最終集合限於六個。

我希望有六個不同的約束,每個約束都有一個有意義的名字,以便爲用戶提供精細的錯誤消息。

CONSTRAINT playerid2__duplicates__playerid1 CHECK (playerid1 <> playerid2), 
CONSTRAINT playerid3__duplicates__playerid1 CHECK (playerid1 <> playerid3), 
CONSTRAINT playerid4__duplicates__playerid1 CHECK (playerid1 <> playerid4), 
CONSTRAINT playerid3__duplicates__playerid2 CHECK (playerid2 <> playerid3), 
CONSTRAINT playerid4__duplicates__playerid2 CHECK (playerid2 <> playerid4), 
CONSTRAINT playerid4__duplicates__playerid3 CHECK (playerid3 <> playerid4) 

可能會感興趣的揭示我寫上面使用SQL:

WITH T 
    AS 
    (
     SELECT * 
     FROM (
       VALUES ('playerid1'), 
        ('playerid2'), 
        ('playerid3'), 
        ('playerid4') 
      ) AS T (c) 
    ) 
SELECT 'CONSTRAINT ' 
     + T2.c + '__duplicates__' + T1.c 
     + ' CHECK (' + T1.c + ' <> ' + T2.c + '),' 
    FROM T AS T1, T AS T2 
WHERE T1.c < T2.c; 
+0

感謝您的回覆。省略號僅僅表示它只是整個SQL語句的一部分。我剛剛發現我重複'playerid2 <> playerid3'以及'playerid1 <> playerid2' - 感謝指出這一點。 – c24w 2012-03-26 12:13:52

+0

@ c24w謝謝,我應該更加關注:) – onedaywhen 2012-03-26 14:08:15