日期:2014-05-17  浏览次数:20508 次

数据库完整性约束的疑问
现在有三个实体,用户、房间、图片;每个用户对应有多张图片,每个房间也对应有多张图片。但是一张图片只能对应一个用户或者一个房间。数据表设计User(UserID,……)、Room(RoomID,……)、Picture(PictureID,SourceID,……);其中SourceID作为UserID或者RoomID的外键。使用这种方式添加用户图片或房间图片的时候都会报错,外键SourceID在另外一张表上找不到,不符合外键约束。有什么可以实现这样的表结构吗?难道只能在Picture表中添加UserID、RoomID,另一个作为冗余字段?
数据库设计 外键约束 一个字段对应多个外键 数据库

------解决方案--------------------
引用:
现在有三个实体,用户、房间、图片;每个用户对应有多张图片,每个房间也对应有多张图片。但是一张图片只能对应一个用户或者一个房间。数据表设计User(UserID,……)、Room(RoomID,……)、Picture(PictureID,SourceID,……);其中SourceID作为UserID或者RoomID的外键。使用这种方式添加用户图片或房间图片的时候都会报错,外键SourceID在另外一张表上找不到,不符合外键约束。有什么可以实现这样的表结构吗?难道只能在Picture表中添加UserID、RoomID,另一个作为冗余字段?


按照lz的描述
一张图片(p)只能对应一个用户(U) 或者 一个房间(R)

P--U or P--R

P--U--R  --应该是这样的设计。
------解决方案--------------------
1:设计两个字字段,foreignID,bit()--表示是否用户图片
2:不创建外键,但是用户id和房间ID必须唯一,不能出现重复。
使用触发器,进行判断是否存在一个图片属于用户或者房间
------解决方案--------------------
创建unique约束即可
------解决方案--------------------
我见过一个系统
数据表里都没有什么约束不约束的
全部靠业务数据来自我实现约束(即业务操作时对业务进行精细化的设计,不符合要求的会在业务端就被限制)
------解决方案--------------------
是user和room引用picture吧?

那么picture是主表了,先插入主表picture,然后从表来引用就可以。 
------解决方案--------------------
不行的话,建一个额外的关系表
------解决方案--------------------
你可以变通来实现,在SourceId上添加一个check检查
示例如下:
CREATE FUNCTION Fn_s(@urid INT )
RETURNS TINYINT
AS
BEGIN
DECLARE @s TINYINT

IF EXISTS(SELECT 1 FROM [User] WHERE Userid=@urid)
SET @s=1
ELSE IF EXISTS(SELECT 1 FROM [Room] WHERE Roomid=@urid)
SET @s=1
ELSE 
SET @s=0

RETURN @s  
END
go 
CREATE TABLE picture (PId INT,PName VARCHAR(20),URid INT CONSTRAINT chk_ check (dbo.fn_s(urid) =1))