我有一个用户表
CREATE TABLE User (
UserID int AUTO_INCREMENT NOT NULL,
UserName varchar(50) NOT NULL,
UNIQUE INDEX UNIQ_USERNAME (UserName),
PRIMARY KEY(UserID)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
和内容表
CREATE TABLE Content (
ContentID int NOT NULL AUTO_INCREMENT,
ContentCreated datetime NOT NULL,
PRIMARY KEY(ContentID)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
用户和内容之间存在多对多的关系。用户可以创建多个Content对象,并且可以由多个用户创建Content对象。
当删除Content对象时,User对象不再需要对它的引用,但是当删除User时,我希望Content对象仍然记录用户(或多个用户)在某个时刻处理它。
我尝试使用一些外键进行连接表
CREATE TABLE CONTENT_AUTHOR (
UserID int,
ContentID int NOT NULL,
PRIMARY KEY(UserID, ContentID)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
ALTER TABLE CONTENT_AUTHOR ADD CONSTRAINT FK_User_To_CONTENT_AUTHOR FOREIGN KEY (UserID) REFERENCES User (UserID) ON DELETE SET NULL;
ALTER TABLE CONTENT_AUTHOR ADD CONSTRAINT FK_Content_To_CONTENT_AUTHOR FOREIGN KEY (ContentID) REFERENCES Content (ContentID) ON DELETE CASCADE;
但这不起作用,因为主键不能设置为null。我怎样才能代表这种关系呢?
答案 0 :(得分:0)
当我解决这种关系时,我创建了一个具有自己id的关系表(我认为很多框架都提出了同样的建议)。
CREATE TABLE CONTENT_AUTHOR (
id int NOT NULL AUTO_INCREMENET,
UserID int,
ContentID int NOT NULL,
deleted tinyint NOT NULL DEFAULT 0,
PRIMARY KEY(ID)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
如果您想在某处使用内容历史记录,我建议您在实际上不删除记录但将记录状态设置为“已删除”时。(不要进行物理删除而是删除逻辑。)
CREATE TABLE User (
UserID int AUTO_INCREMENT NOT NULL,
UserName varchar(50) NOT NULL,
deleted tinyint NOT NULL DEFAULT 0,
UNIQUE INDEX UNIQ_USERNAME (UserName),
PRIMARY KEY(UserID)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
答案 1 :(得分:0)
您可以继续将FK_User_To_CONTENT_AUTHOR设置为ON DELETE CASCADE,然后将CONTENT_AUTHOR和User表连接到Content表吗?由于您拥有内容记录,您仍然会知道用户正在处理它:
select
ifnull(u.UserID,0) UserID,
ifnull(u.UserName,'Expired User') UserName,
c.ContentCreated
from Content c
left join CONTENT_AUTHOR ca
on ca.ContentID = c.ContentID
left join User u
on u.UserID = ca.UserID
如果与内容相关的用户记录数量很大,我建议创建某种过期用户记录,并将其作为用户删除过程的一部分插入CONTENT_AUTHOR表中:
insert into CONTENT_AUTHOR(UserID,ContentID)
select u.UserID,c.ContentID
from User u
inner join CONTENT_AUTHOR c
on c.UserID = 2
where u.UserName = 'Expired User';
delete from User where UserID = 2;
如果我们可以在FK_User_To_CONTENT_AUTHOR键上设置DEFAULT会很棒,但我认为我们不能。