我有一个愚蠢的问题。事情是我的程序必须具有从我的数据库中删除数据的功能。是的,不是真正的问题。但是,如何在没有其他人可以看到的危险的情况下删除数据,删除了一些内容。
User Table:
U_ID U_NAME
1 Chris
2 Peter
OTHER TABLE
ID TIMESTAMP FK_U_D
1 2012-12-01 1
2 2012-12-02 1
Sooooo ID是AUTO_INCREMENT,所以如果我删除其中一个就有差距。此外,时间戳也比之前的行大,所以升序。
我想让ID为1的数据从用户的个人资料(U_ID 1)中消失。
如果我删除它,则存在差距。如果我只是将FK_U_ID更改为2(Peter)很明显,因为当我插入数据时,有20或30个数据行具有相同的U_ID ...所以很明显存在修改。
如果我将FK_U_ID设置为NULL - >当我把它改成另一个U_ID时,就像sh **一样。
是否有任何解决方案可以让这项工作?我知道如果除了我之外没有人可以访问数据库,那就没问题了。但是为了以防万一,如果有人控制我的程序,那么就不应该有明显的修改。
所以我们走了。
答案 0 :(得分:1)
对于ID gap问题,您可以使用GUIDs作为@SLaks建议,但是您不能使用本机RDBMS auto_increment,这意味着您必须创建GUID并将其与其余记录一起插入创建时的数据。当然,你真的不需要ID是全局唯一的,你可以只存储一个20个字符或者其他东西的随机字符串,但是你必须进行数据库读取以查看是否采用了该ID并重复(递归)这个过程直到你找到一个未使用的ID ...可能非常费力。
答案 1 :(得分:1)
一点也不清楚为什么你会想要隐藏"证据表明已执行删除。这听起来真的很糟糕。我不是传播错误信息的粉丝。
理想主键的两个特征是: - 匿名(没有任何有用的信息,并不重要的是它设置的内容) - 不可变(一旦分配,它将永远不会被改变。)
但是,如果我们把整个讨论放在一边......
我可以回答一个稍微不同的问题(你可能会发现对你的特定情况有帮助的答案)
消除"差距的唯一方法"在具有AUTO_INCREMENT的列中的值中,将列值从其当前值更改为连续的新值序列。如果有任何引用该列的外键,则还需要更新这些列中的值,以保留关系。这可能会使表格的当前auto_increment值高于id列的最大值,因此我也希望重置该值,以避免出现"间隙"在下一个插页上。
(我已经在开发和测试环境中对auto_increment值进行了重新排序,以及#34; cleanup"查找表,并将某些表的id值移动到与其他表中的范围不同的范围...让我测试SQL,以确保SQL连接谓词不会无意中引用错误的表,并返回看起来不正确的行......这些是我所知道的一些原因如果auto_increment值完成重新分配)
请注意,数据库可以自动地"更改主键值时更新外键值(对于InnnoDB表),只要外键约束定义为ON UPDATE CASCADE
,并且FOREIGN_KEY_CHECKS
未被禁用。
如果没有外键可以处理,并且假设id的所有当前值都是正整数,那么我已经能够做到这样的事情:(有适当的备份,所以我如果事情不能正常工作可以恢复
UPDATE mytable t
JOIN (
SELECT s.id AS old_id
, @i := @i + 1 AS new_id
FROM mytable s
CROSS
JOIN (SELECT @i := 0) i
ORDER BY s.id
) c
ON t.id = c.old_id
SET t.id = c.new_id
WHERE t.id <> c.new_id
将表AUTO_INCREMENT重置为表中最大的id值:
ALTER TABLE mytable AUTO_INCREMENT = 1;
通常,我将创建一个表,并在上面的内联视图(别名为c
)中从该查询填充它。然后,我可以使用该表更新外键列和主键列,首先禁用FOREIGN_KEY_CHECKS,然后重新启用它。 (在并发环境中,其他进程可能正在插入/更新/删除其中一个表中的行,我当然会首先获取所有要更新的表的独占锁。)
再次接受,我之前提出的讨论......这种类型的&#34;行政&#34;在设置测试用例时,函数在测试环境中非常有用。但它不是在生产环境中使用实时数据执行的功能。