'删除'用户但保留记录(外键)

时间:2015-04-30 19:11:03

标签: php mysql database database-design foreign-keys

我有一个表var text = $("#" + attName + " pre:first").text(); ,其中包含用户帐户(user_id,username,...)。 user_id与多个其他表相关 - 例如一张桌子上有他最后的动作,个人资料,他的产品,他的兴趣等等。

有时用户想要删除,然后我将字段'已删除'设置为1.应删除大多数表中的记录,但记录在2个表中(users和{{1应该保留对用户的引用。原因:例如,消息合作伙伴仍希望查看他最近与之交谈的帐户的用户名。这样做的最佳方式是什么?

1)在PHP中,存储reportsmessages中应保存在数组中的记录的ID。然后删除用户。自动与reports相关的所有表都会删除其记录并引用已删除的帐户。 messagesusers中的引用应为:reports,因此用户删除后其记录仍然存在。数据库现在是干净的,然后将具有相同user_id的用户重新插入,并将字段'deleted'重新插入1.然后将数组中的数据更新为user_id,以便再次设置引用。

2)删除messagesON UPDATE SET NULL中对用户的引用(因此没有外键)。

3) ......(有更好的选择吗?)

谢谢!

4 个答案:

答案 0 :(得分:3)

在报告和消息表上使用外键约束的原因是强制引用完整性;通常这是一件好事,但在这种情况下,它是您问题的根源,因为您实际上想要违反参照完整性以便在删除用户记录后维护审计跟踪。我建议您删除报告和消息表中user_id列的外键约束。这将允许您删除用户而不会影响报表或消息表中的数据。不幸的是,如果没有相应的用户名,user_id就无用了,所以不用存储user_id,最好直接在报表和消息表中存储用户名。在这种情况下,我建议你改变数据库模式如下(这是伪代码,可能需要适应MySQL语法):

ALTER TABLE reports ADD COLUMN username VARCHAR;
UPDATE reports FROM users SET reports.username = users.username
    WHERE reports.user_id = users.user_id;
ALTER TABLE reports DROP COLUMN user_id;

ALTER TABLE messages ADD COLUMN username VARCHAR;
UPDATE messages FROM users SET messages.username = users.username 
    WHERE messages.user_id = users.user_id;
ALTER TABLE messages DROP COLUMN user_id;

请注意,新用户名列不是用户表上的外键。

出于性能原因,如果要在where子句中运行包含用户名的select语句,您可能还需要在这些表中的用户名列中添加索引。

顺便说一下,根据我的经验,通常有意义的是从用户表中删除“id”列并使用户名成为users表上的主键,假设用户名值都是唯一的。

答案 1 :(得分:1)

是的,还有更好的选择。

如果您因任何原因需要用户,请不要删除它,基本规则。删除= 1更新并删除需要删除的表中的所有数据。保持现在的参照完整性,如果您尝试删除超出预期的数量,这将提醒您。从table_name删除一些id_user = XXX将为您现在和将来节省很多麻烦。你有这些外键是有原因的。相信我。

当然,您需要制定备用政策,以防万一“你不再需要它”的错误。

答案 2 :(得分:0)

如果您希望从数据库级别处理所有内容,则可以使用触发器来完成工作。 用于在reportsmessages数据中加密数据,即使用户被删除= 1表示这些数据 将用于其他参考,当您添加具有相同user id的新用户详细信息时,一切都会 被重置。该过程看起来更像是一个CRM应用程序,即使用户也不会删除数据,只将其设置为deleted=1 当为该删除的记录引入新用户时,其他可能的数据将自动分配给该用户。

但是在您的情况下,您仍然想要删除一些数据。因此,使用以下触发器可以完成。 请注意,您不是要删除正在更新用户的用户。

delimiter //

create trigger user_update after update on user
for each row
begin
  if old.deleted <> new.deleted then 
    if new.deleted = 1 then
      delete from last_actions where user_id = new.user_id ;
      delete from profile_details where user_id = new.user_id ;
      -- all the delete queries where you want to delete
    elseif  new.deleted = 0 then
      delete from reports where user_id = new.user_id ;
      delete from messages where user_id = new.user_id ;
    end if ;
  end if;
end;//

delimiter ;

答案 3 :(得分:0)

我给出两个选项,第一个是停止从reportsmessage表中删除的行,但我认为这不会解决您的问题,因为如果从用户表中删除该行,您可以&#39 ;得到他的名字电子邮件或其他任何东西。

解决方案1 ​​ 请删除reportsmessages表上的约束,方法是从用户表中删除引用的用户,不会对这些表执行任何操作

解决方案2 在用户表中创建状态列,而不是删除行设置为false,这个false表示此用户可以执行进一步的活动。