考虑以下(假设的)模式。您会在“棋盘”表中添加代理键吗?{xxx,yyy,pc} 的值受“受限”域或 PK+FK 约束的约束。
在哪些情况下添加代理键(对于 {xxx,yyy} 有帮助?
(真正的国际象棋游戏需要额外的约束(例如:每种颜色不超过一个国王......),(但部分)业务规则(如有效移动......)将由“应用程序逻辑”无论如何)
-- this is Postgres-specific:
-- create a schema to play in
DROP SCHEMA chess CASCADE ;
CREATE SCHEMA chess ;
SET search_path='chess' ;
-- Domain with only values A-H to three allowed.
CREATE DOMAIN chess_column
AS CHAR(1) NOT NULL
check (value >= 'A' AND value <= 'H')
;
-- Domain with only values 1-8 allowed.
CREATE DOMAIN chess_row
AS INTEGER NOT NULL
check (value >= 1 AND value <= 8)
;
-- Table with only valid pieces
CREATE TABLE chess_piece
( id INTEGER NOT NULL PRIMARY KEY
, pname varchar
) ;
INSERT INTO chess_piece(id,pname) VALUES
( -6, 'Black King' ) , ( -5, 'Black Queen' ) , ( -4, 'Black Rook' )
, ( -3, 'Black Bishop' ) , ( -2, 'Black Knight' ) , ( -1, 'Black Pawn' )
, ( 6, 'White King' ) , ( 5, 'White Queen' ) , ( 4, 'White Rook' )
, ( 3, 'White Bishop' ) , ( 2, 'White Knight' ) , ( 1, 'White Pawn' )
;
CREATE TABLE chessboard
( xxx chess_column
, yyy chess_row
, pc INTEGER NOT NULL REFERENCES chess_piece(id)
, PRIMARY KEY (xxx,yyy)
);
-- Too lazy to enter the entire board
-- ; only put a White Pawn at E2
INSERT INTO chessboard(xxx,yyy,pc)
SELECT 'E', 2, p.id
FROM chess_piece p
WHERE p.pname = 'White Pawn';
;
-- Shift the pawn
UPDATE chessboard b
SET yyy = 4
FROM chess_piece p
WHERE b.pc = p.id
AND p.pname = 'White Pawn';
AND b.xxx = 'E' AND b.yyy = 2
;
-- Try to put a piece outside the board
\echo Try put a piece outside the board
INSERT INTO chessboard(xxx,yyy,pc)
SELECT 'I', 2, p.id
FROM chess_piece p
WHERE p.pname = 'Black Pawn';
;
-- add a non-existing piece
\echo add a non-existing piece
INSERT INTO chessboard(xxx,yyy,pc)
VALUES( 'H', 1, 42)
;
-- Position is already occupied
\echo Position is already occupied
INSERT INTO chessboard(xxx,yyy,pc)
SELECT 'E', 4, p.id
FROM chess_piece p
WHERE p.pname = 'Black Pawn';
;