0

我有一个愚蠢的问题。问题是我的程序必须具有从数据库中删除数据的功能。是的,不是真正的问题。但是,我怎样才能删除数据而不会有其他人可以看到的危险,即删除了某些内容。

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 时一样。

有什么解决方案可以完成这项工作吗?我知道,如果除了我之外没有人可以访问数据库,那就没问题了。但以防万一,如果有人控制了我的程序,那么修改应该不会很明显。

所以我们开始吧。

4

2 回答 2

1

对于 ID 差距问题,您可以按照@SLaks 的建议使用GUID,但是您不能使用本机 RDBMS auto_increment,这意味着您必须创建 GUID 并在创建时将其与其余记录数据一起插入。当然,您实际上并不需要 ID 是全局唯一的,您可以只存储 20 个字符或其他内容的随机字符串,但是您必须执行数据库读取以查看该 ID 是否被获取并重复(递归)这个过程直到你找到一个未使用的 ID……可能会很费力。

于 2013-01-10T15:01:09.773 回答
1

完全不清楚为什么要“隐藏”执行删除的证据。这听起来真是个坏主意。我不喜欢传播错误信息。

理想主键的两个特征是: - 匿名(没有任何有用的信息,不管它的设置是什么) - 不可变的(一旦分配,就永远不会改变。)

但是,如果我们把整个讨论放在一边……


我可以回答一个稍微不同的问题(您可能会发现对您的特定情况有帮助的答案)

消除具有 AUTO_INCREMENT 的列中的值中的“间隙”的唯一方法是将列值从其当前值更改为连续的新值序列。如果有任何外键引用该列,则这些列中的值也需要更新,以保留关系。这可能会使表的当前 auto_increment 值高于 id 列的最大值,所以我也想重置它,以避免在下一次插入时出现“间隙”。

(我已经在开发和测试环境中对 auto_increment 值进行了重新排序,以“清理”查找表,并将某些表的 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 然后重新启用它。(在并发环境中,其他进程可能正在从其中一个表中插入/更新/删除行,我当然会首先获得所有要更新的表的排他锁。)


再次提起我之前搁置的讨论……这种类型的“管理”功能在测试环境中非常有用,在设置测试用例时。但这不是在生产环境中使用实时数据执行的功能。

于 2013-01-10T15:42:34.367 回答