7

我有一个 mysql 表,其中每一行在“序列”列中都有自己的序列号。但是,当一行被删除时,它会留下一个空白。所以...

1
2
3
4

……变成……

1
2
4

有没有一种巧妙的方法来“重置”排序,所以它在一个 SQL 查询中再次变得连续?

顺便说一句,我确信这个过程有一个技术术语。任何人?

更新:“序列”列不是主键。它仅用于确定记录在应用程序中的显示顺序。

4

5 回答 5

7

如果该字段是您的主键...

...那么,正如这个问题的其他地方所述,您不应该更改 ID。ID 已经是唯一的,您既不需要也不想重复使用它们。

现在,这说...


除此以外...

对于某些应用程序定义的排序,您很可能有不同的字段(即,以及 PK)。只要这种顺序不是其他领域固有的(例如,如果它是用户定义的),那么这没有任何问题。

您可以使用(临时)auto_increment字段重新创建表,然后将其删除auto_increment

我很想UPDATE按升序并应用递增变量。

SET @i = 0;
UPDATE `table`
   SET `myOrderCol` = @i:=@i+1
 ORDER BY `myOrderCol` ASC;

(查询未测试。)

每次删除项目时都这样做似乎很浪费,但不幸的是,使用这种手动排序方法,如果您想保持列的完整性,您无能为力。

您可能会减少负载,这样在删除myOrderCol等于的条目后,例如5

SET @i = 5;
UPDATE `table`
   SET `myOrderCol` = @i:=@i+1
 WHERE `myOrderCol` > 5
 ORDER BY `myOrderCol` ASC;

(查询未测试。)

这会将以下所有值“洗牌”一。

于 2011-08-14T14:06:31.137 回答
1

我会说不要打扰。重新分配顺序值是一项相对昂贵的操作,如果列值仅用于排序目的,则没有充分的理由这样做。您可能唯一担心的是,例如,您的列是 UNSIGNED INT,并且您怀疑在应用程序的生命周期中,您可能有超过 4,294,967,296 行(包括已删除的行)并且超出范围,即使您担心的是当这种情况发生时,可以在 10 年后将重新分配作为一次性任务进行。

于 2011-08-14T14:52:19.633 回答
0

这是我经常在这里和其他论坛上阅读的一个问题。正如 zerkms 已经写的那样,这是一个错误的问题。此外,如果您的表与其他表相关,您将失去关系。

仅出于学习目的,一种简单的方法是将数据存储在临时表中,截断原始表(此重置 auto_increment),然后重新填充它。

愚蠢的例子:

create table seq (
id int not null auto_increment primary key,
col char(1)
) engine = myisam;

insert into seq (col) values ('a'),('b'),('c'),('d');

delete from seq where id = 3;

create temporary table tmp select col from seq order by id;

truncate seq;

insert into seq (col) select * from tmp;

但这完全没用。;)

于 2011-08-14T14:03:27.430 回答
0

如果这是你的PK,那么你不应该改变它。PK 应该(大部分)是不变的列。如果您要更改它们,那么您不仅需要在该表中更改它,而且还需要在存在的任何外键中进行更改。

如果您确实需要顺序序列,请问问自己为什么。在表中没有固有的或保证的顺序(即使在 PK 中,尽管由于大多数 RDBMS 存储和检索数据的方式可能会出现这种情况)。这就是我们ORDER BY在 SQL 中有子句的原因。如果您希望能够根据其他内容(添加到数据库中的时间等)生成序列号,请考虑在查询中或使用前端生成序列号。

于 2011-08-14T14:04:31.990 回答
0

假设这是一个 ID 字段,您可以在插入时执行此操作:

INSERT INTO yourTable (ID)
SELECT MIN(ID)
FROM yourTable
WHERE ID > 1

正如其他人提到的,我不建议这样做。在评估下一个 ID 时,它将持有一个表锁。

于 2011-08-14T14:07:02.170 回答