简体   繁体   中英

Can this SQL constraint be written more simply?

To clarify - there will be up to 4 distinct players in the table, referenced by their ids. I want to enforce this, ie no two ids are the same.

Also, because it's up to 4 players, some may be null. Is potentially having many nulls like this a bad idea? I don't think it does, but just to be sure, does null == null return false?

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

Thank you!

I'd use a separate table for this:

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

Then you can add

  • a UNIQUE constraint for game_id+player id (to enforce a player doesn't occur more than once per game)
  • a UNIQUE constraint for game_id+player_position (to ensure a position is occupied by at most one player)
  • a CHECK constraint for player_position to enforce it only has the values 1, 2, 3 or 4

This should achieve what you want in a somewhat cleaner (IMHO) way.

Of your seven expressions, you have repeats eg (playerid1 <> playerid2) . The definitive set is limited to six.

I would prefer to have six different constraints, each with a meaningful name, in order to give granular error messages to the user eg

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 )

It may be of interest to reveal I wrote the above using 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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM