'Delete' 用户但保留记录(外键)
'Delete' user but keep records (foreign keys)
我有一个 table users
和用户帐户(user_id、用户名...)。 user_id 与其他多个 table 相关 - 例如a table 包括他最近的操作、个人资料详细信息、他的产品、他的兴趣等
有时候一个用户要删除,然后我设置一个字段'deleted'为1,大部分table中的记录应该删除,但是2[=]中的记录47=]s(reports
和 messages
)应该保留对用户的引用。原因:比如消息伙伴还想看他最近通话的账号的用户名。最好的方法是什么?
1) 在 PHP 中存储记录的 id 在 reports
和 messages
中应该保存在一个数组中。然后删除用户。与 users
相关的所有 table 都会自动删除他们的记录,并引用已删除的帐户。 reports
和 messages
中的引用应该是: ON UPDATE SET NULL
所以他们的记录在用户删除后仍然存在。现在数据库是干净的,然后重新插入具有相同user_id的用户,字段'deleted'为1。然后将数组中的数据更新为user_id,这样引用就设置好了再次.
2) 删除 reports
和 messages
中对用户的引用(因此没有外键)。
3) ...(有更好的选择吗?)
谢谢!
在 reports
和 messages
table 上使用外键约束的原因是为了强制参照完整性;通常这是一件好事,但在这种情况下,这是问题的根源,因为您实际上想要违反参照完整性,以便在删除 users
记录后维护审计线索。我建议您删除 reports
和 messages
table 中 user_id
列的外键约束。这将允许您在不影响报告或消息 table 中的数据的情况下删除用户。不幸的是,如果没有相应的用户名,user_id
是没有用的,因此与其存储 user_id
,不如将用户名直接存储在报告和消息 table 中。在这种情况下,我建议您按如下方式更改数据库模式(这是伪代码,可能需要针对 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;
请注意,新的 username
列不是 users
table 上的外键。
出于性能原因,您可能还想将索引添加到这些 table 中的 username
列,如果您要 运行 select 包含 username
在 where 子句中。
顺便说一下,根据我的经验,从用户 table 中完全删除 id
列并使用户名成为 users
table,假设 username
值都是唯一的。
1) 我 从不 考虑删除用户记录并留下其他 table 包含用户数据的其他 user_id 在用户中不存在table。正如您所提到的,您必须保留用户帐户的原因有很多。
And you only need 1 simple UPDATE status query.
(所以我会保留外键并且在这个 table 上不会有 DELETE 情况)。
2) 在某些情况下,您必须从数据库中删除此数据(例如法律问题、数百万被删除的用户)。另一种方法是 创建一个 deleted_users table,使用 user_id 和用户名,并创建一个函数来检查用户是否被删除。
但我认为,这种方法在生产级别的环境中容易出错,我根本不推荐它。在这种情况下 外键 不保留
You need 2 queries (INSERT, DELETE) and 1 query (SELECT) every time you have to check whether a user is deleted.
综上所述:选项1(状态:已删除)是最佳选择。这样你也可以在用户改变主意时恢复数据。
PS:如果您处于开发阶段,并且想从很多 table 中删除一些用户,您可以创建一个删除功能,然后带有 table 的循环。像这样:
$tables=array('table1','table2','table40');
function delete_user_from_table($table,$user_id){
//connection db
//delete query
$deleteQuery=$db->query("DELETE FROM {$table} WHERE user_id='{$user_id}");
if($deleteQuery){echo $user_id.' deleted from table '.$table;}
}
//delete loop
foreach ($tables as $table){
delete_user_from_table($table,'23');
}
但是,在这种情况下,我不会仅仅为了开发级别的可用性而创建外键。
如果您希望所有操作都从数据库级别进行处理,那么您可以使用触发器来完成这项工作。
即使删除了用户,也要保留 reports
和 messages
数据中的数据 = 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 ;
我给出了两个选项,第一个是停止从 reports
和 message
table 中删除的行,但我认为这不会解决您的问题,因为如果从中删除行用户 table 您无法获取他的姓名电子邮件或其他任何信息。
解决方案 1
请删除对 reports
和 messages
table 的约束,方法是从用户中删除引用的用户 table 不会对这些执行任何操作 table
解决方案 2
在用户 table 中创建状态列,因此不要删除该行,而是将其设置为 false,此 false 意味着该用户可以进一步执行 activity。
是的,有更好的选择。
如果您出于任何原因需要该用户,请不要删除它,这是基本规则。执行 deleted=1 更新并删除表中需要删除的所有数据。保持您现在拥有的引用完整性,如果您尝试删除的内容超出您的预期,这将提醒您。从 table_name where id_user = XXX 中删除一些,现在和将来都会为您省去很多麻烦。您拥有这些外键是有原因的。相信我。
当然,您需要制定备份策略,以防万一您对 "wont need it anymore" 句子有误。
我有一个 table users
和用户帐户(user_id、用户名...)。 user_id 与其他多个 table 相关 - 例如a table 包括他最近的操作、个人资料详细信息、他的产品、他的兴趣等
有时候一个用户要删除,然后我设置一个字段'deleted'为1,大部分table中的记录应该删除,但是2[=]中的记录47=]s(reports
和 messages
)应该保留对用户的引用。原因:比如消息伙伴还想看他最近通话的账号的用户名。最好的方法是什么?
1) 在 PHP 中存储记录的 id 在 reports
和 messages
中应该保存在一个数组中。然后删除用户。与 users
相关的所有 table 都会自动删除他们的记录,并引用已删除的帐户。 reports
和 messages
中的引用应该是: ON UPDATE SET NULL
所以他们的记录在用户删除后仍然存在。现在数据库是干净的,然后重新插入具有相同user_id的用户,字段'deleted'为1。然后将数组中的数据更新为user_id,这样引用就设置好了再次.
2) 删除 reports
和 messages
中对用户的引用(因此没有外键)。
3) ...(有更好的选择吗?)
谢谢!
在 reports
和 messages
table 上使用外键约束的原因是为了强制参照完整性;通常这是一件好事,但在这种情况下,这是问题的根源,因为您实际上想要违反参照完整性,以便在删除 users
记录后维护审计线索。我建议您删除 reports
和 messages
table 中 user_id
列的外键约束。这将允许您在不影响报告或消息 table 中的数据的情况下删除用户。不幸的是,如果没有相应的用户名,user_id
是没有用的,因此与其存储 user_id
,不如将用户名直接存储在报告和消息 table 中。在这种情况下,我建议您按如下方式更改数据库模式(这是伪代码,可能需要针对 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;
请注意,新的 username
列不是 users
table 上的外键。
出于性能原因,您可能还想将索引添加到这些 table 中的 username
列,如果您要 运行 select 包含 username
在 where 子句中。
顺便说一下,根据我的经验,从用户 table 中完全删除 id
列并使用户名成为 users
table,假设 username
值都是唯一的。
1) 我 从不 考虑删除用户记录并留下其他 table 包含用户数据的其他 user_id 在用户中不存在table。正如您所提到的,您必须保留用户帐户的原因有很多。
And you only need 1 simple UPDATE status query.
(所以我会保留外键并且在这个 table 上不会有 DELETE 情况)。
2) 在某些情况下,您必须从数据库中删除此数据(例如法律问题、数百万被删除的用户)。另一种方法是 创建一个 deleted_users table,使用 user_id 和用户名,并创建一个函数来检查用户是否被删除。
但我认为,这种方法在生产级别的环境中容易出错,我根本不推荐它。在这种情况下 外键 不保留
You need 2 queries (INSERT, DELETE) and 1 query (SELECT) every time you have to check whether a user is deleted.
综上所述:选项1(状态:已删除)是最佳选择。这样你也可以在用户改变主意时恢复数据。
PS:如果您处于开发阶段,并且想从很多 table 中删除一些用户,您可以创建一个删除功能,然后带有 table 的循环。像这样:
$tables=array('table1','table2','table40');
function delete_user_from_table($table,$user_id){
//connection db
//delete query
$deleteQuery=$db->query("DELETE FROM {$table} WHERE user_id='{$user_id}");
if($deleteQuery){echo $user_id.' deleted from table '.$table;}
}
//delete loop
foreach ($tables as $table){
delete_user_from_table($table,'23');
}
但是,在这种情况下,我不会仅仅为了开发级别的可用性而创建外键。
如果您希望所有操作都从数据库级别进行处理,那么您可以使用触发器来完成这项工作。
即使删除了用户,也要保留 reports
和 messages
数据中的数据 = 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 ;
我给出了两个选项,第一个是停止从 reports
和 message
table 中删除的行,但我认为这不会解决您的问题,因为如果从中删除行用户 table 您无法获取他的姓名电子邮件或其他任何信息。
解决方案 1
请删除对 reports
和 messages
table 的约束,方法是从用户中删除引用的用户 table 不会对这些执行任何操作 table
解决方案 2 在用户 table 中创建状态列,因此不要删除该行,而是将其设置为 false,此 false 意味着该用户可以进一步执行 activity。
是的,有更好的选择。
如果您出于任何原因需要该用户,请不要删除它,这是基本规则。执行 deleted=1 更新并删除表中需要删除的所有数据。保持您现在拥有的引用完整性,如果您尝试删除的内容超出您的预期,这将提醒您。从 table_name where id_user = XXX 中删除一些,现在和将来都会为您省去很多麻烦。您拥有这些外键是有原因的。相信我。
当然,您需要制定备份策略,以防万一您对 "wont need it anymore" 句子有误。