用于交叉检查 MySQL 中用户行的外键约束

Foreign key constraint to cross check user rows in MySQL

仅当外键数据实际上属于执行 insert/update.

的用户时,如何才能使用外键强制 insert/update 查询成功

例如,用户 1 创建的类别不能被用户 2 使用,反之亦然,以禁止交叉访问。

Create Table Users(
    user_id int not null AUTO_INCREMENT,
    user_name varchar(50) not null,
    city varchar(50) default null,
    PRIMARY KEY (user_id)
);

-- Insert users
Insert into Users(user_name, city) Values('Nick', 'New york');
Insert into Users(user_name, city) Values('John', 'Seattle');

创建类别

Create Table Categories(
    category_id int not null AUTO_INCREMENT,
    user_id int not null,
    category_name varchar(50) not null,
    PRIMARY KEY (category_id),
  CONSTRAINT FK_CategoryUser FOREIGN KEY (user_id) REFERENCES Users(user_id)  
);

-- Insert category for Nick with user_id = 1
Insert into Categories(user_id, category_name) Values(1, 'Travel');

-- Insert category for John user_id = 2
Insert into Categories(user_id, category_name) Values(2, 'Science');

创建图书

Create Table Books(
    book_id int not null AUTO_INCREMENT,
    user_id int not null,
    category_id int default null,    
    book_name varchar(50) not null,
    book_type varchar(50) not null,
    PRIMARY KEY (book_id),
  CONSTRAINT FK_BookUser FOREIGN KEY (user_id) REFERENCES Users(user_id),
  CONSTRAINT FK_BookCategory FOREIGN KEY (category_id) REFERENCES Categories(category_id)
);

现在 Nick 的插页 必须失败 因为 category_id = 2 行的“科学”类别属于 John user_id = 1

Insert into Books(user_id, category_id, book_name, book_type)
Values(1, 2, 'My science book', 'online')

因为你有 Categories.user_id,你可以将其设为密钥:

ALTER TABLE Categories ADD UNIQUE KEY (user_id, category_id);

然后从书中引用它table:

ALTER TABLE Books ADD FOREIGN KEY (user_id, category_id) 
  REFERENCES Categories (user_id, category_id);

这要求只有当用户被分配到相应的类别时,才向该用户提供一本书。但它允许 Books 中的多行具有相同的用户和类别对。

将 Categories 中的新键设置为 UNIQUE KEY 似乎是多余的,因为单独的 category_id 已经是唯一的。但是在一般的SQL语言中,外键必须引用一个UNIQUE KEY。