Можно ли написать это ограничение SQL проще? - PullRequest
1 голос
/ 25 марта 2012

Чтобы уточнить - в таблице будет до 4 разных игроков, на которые ссылаются их идентификаторы.Я хочу применить это, т. Е. Нет двух одинаковых идентификаторов.

Кроме того, поскольку в нем могут участвовать до 4 игроков, некоторые из них могут быть нулевыми.Потенциально иметь много нулей, подобных этой, плохая идея?Я не думаю, что это так, но просто чтобы быть уверенным, null == null возвращает ложь?

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

Спасибо!

Ответы [ 2 ]

10 голосов
/ 25 марта 2012

Я бы использовал для этого отдельную таблицу:

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

Тогда вы можете добавить

  • УНИКАЛЬНОЕ ограничение для game_id + идентификатор игрока (чтобы заставить игрока появляться не более одного раза за игру)
  • УНИКАЛЬНОЕ ограничение для game_id + player_position (чтобы гарантировать, что позиция занята не более чем одним игроком)
  • ограничение CHECK для player_position для принудительного применения имеет только значения 1, 2, 3 или 4

Это должно достичь того, что вы хотите, более чистым (ИМХО) способом.

1 голос
/ 26 марта 2012

Из ваших семи выражений у вас есть повторения, например, (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;
...