2012-03-24 116 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