将值放在升序数据库列之间

Posted

技术标签:

【中文标题】将值放在升序数据库列之间【英文标题】:putting values in between the ascending database column 【发布时间】:2016-05-23 07:27:03 【问题描述】:

以下是我在mysql中的数据库:

Id  Username    Password
1   admin       admin
2   jay         jay1
3   suman       xyza
4   chintan     abcde

这是我在 php 中的代码:

$fetchid = mysql_query(" SELECT MAX(Id) As max From user;");
$row = mysql_fetch_array($fetchid);
$largest = $row['max'];
$largest++;

$user= $_POST['username'];
$pass= $_POST['password'];

$result = mysql_query(" INSERT INTO `proshell`.`user` (
`Id` ,
`Username` ,
`Password`
)"."
VALUES (
'".$largest."', '".$user."', '".$pass."'
);");

问题: 现在,如果我删除 Id=1 的行,然后重新输入数据,那么它应该使用 ID=1,然后我再次重新插入它使用 ID=5 的数据

它的工作原理是这样的: 如果我删除 Id=1 的行,然后重新输入 Id 为 5 的数据,但随后 1 是免费的,

我应该写什么来完成这项任务。

【问题讨论】:

***.com/questions/12325132/… 不,它不应该使用 ID 1,它应该简单地使用一个新的和唯一的 ID.....AUTOINCREMENT 是关于获取唯一的 ID,而不是连续的 ID......如果你需要一个连续值,那么您需要自己操作它,或者(更有可能)重新考虑为什么您认为您需要从 1 开始编号且没有间隙的连续 id 如果您需要更改 ID 1 处的记录,您为什么要尝试删除并重新插入而不是简单地更新 @MarkBaker 我说这个数据库有两个用户好吗?因此,如果一个人离开,它将删除他的 ID。好的。如果新人来了,那么它必须创建一个新的 ID,然后就会出现问题。在这里,我有一个小应用程序。但在未来,当超过预期的人加入然后永久离开应用程序时,这可能会成为问题。 如果您关心 id,那么您的数据可能会遇到更大的问题。见规范化。 【参考方案1】:

首先,据我了解,您选择的是最高的列 ID,它应该始终是最后一个(因为您在 ID 列上设置了自动增量)。

但您实际上是在删除查询后填补漏洞,对吗?

如果您真的在寻找这种方法,请尝试通过创建新的布尔列来绕过删除操作,您可以在其中标记记录是否处于活动状态(真/假)。

SQL 表变化:

    Id  Username    Password Active
1   admin       admin       false
2   jay         jay1        true
3   suman       xyza        false
4   chintan     abcde       true

PHP 请求:

$fetchid = mysql_query(" SELECT MIN(Id) As min FROM user WHERE active = false;");

$result = mysql_query(" INSERT INTO `proshell`.`user` (
`Id` ,
`Username` ,
`Password`
`Active`
)"."
VALUES (
'".$largest."', '".$user."', '".$pass."', 'true'
);");

【讨论】:

这不是可行的解决方案。因为如果我有一百万个条目,那么我已经遍历了每个值。如果情况是我的空 ID 只比 max(100 万) 少一个,那么我必须先通过 999998 行。真是太棒了。【参考方案2】:

首先,如果您将Id 列设置为AUTO_INCREMENT,则您的代码中根本不需要以下部分:

$fetchid = mysql_query(" SELECT MAX(Id) As max From user;");
$row = mysql_fetch_array($fetchid);
$largest = $row['max'];
$largest++;

因为AUTO_INCREMENT 会自动为您的 ID 列添加新值。

但是如果你不设置它为AUTO_INCREMENT,上面的代码会获取到MAXIMUM ID值(本例中为4)。

删除第 1 行后再次重新输入数据时,MAXIMUM ID 仍为 4,因此您的新 ID 值为 5(来自$largest++;)。

.....

如果你真的需要在PK时使用连续的ID,你需要重写你的代码,但我建议你使用UUID作为你的ID列。

您可以使用uuid()轻松生成UUID。

UUID 性能如何?请参阅 Dancrumb 对此的回答:

UUID 是通用唯一 ID。这是您应该在这里考虑的普遍部分。

您真的需要 ID 是普遍唯一的吗?如果是这样,那么 UUID 可能是你唯一的选择。

我强烈建议,如果您确实使用 UUID,请将它们存储为 数字而不是字符串。如果您有 50M+ 记录,那么保存 在存储空间中会提高你的表现(虽然我不能 说多少)。

如果您的 ID 不需要是普遍唯一的,那么我认为不需要 你可以做得比只使用 auto_increment 更好, 保证 ID 在表中是唯一的(因为值 每次都会增加)

看。 UUID performance in MySQL?


编辑:我不建议您在每次插入新值之前对整个表运行查询只是为了找到 MAX ID 值,因为它会给您带来性能损失(想象一下,如果您有一百万行并且必须查询他们每次只是为了插入一个新行,对您的服务器造成多少工作负载)。

最好像 INSERT 一样进行 INSERT,仅此而已。


EDIT2:

如果你真的想使用连续的id,那么这个解决方案怎么样?

创建新 TABLE 仅用于存储插入的 id(新 id 和您删除的 id)。

例如:

CREATE TABLE cons_ids (
  ids INT PRIMARY KEY,
  is_marker TINYINT DEFAULT 0
);

然后是值从 1-100 的初始 id,并在某个位置将标记设置为“1”,例如全桌的第 80 位。此“标记”用于在几乎为空时填充您的 id。

当您需要在第一个表中插入新 ID 时,请使用:

$result = mysql_query("SELECT ids, marker FROM cons_ids ORDER BY ids ASC LIMIT 1;");
$row = mysql_fetch_row($result);

并将 $row[0] 用于以下代码:

INSERT INTO yourtable (Id, Username, Password)
VALUES ($row[0], $username, $password);

DELETE FROM cons_ids
WHERE ids = $row[0];

此代码将自动插入 cons_ids 中的最小数字作为您的 ID,并将其从 cons_ids 表中删除。 (所以下次插入时,它将是下一个最小的数字)

然后使用以下代码:

if ($row[1] == 1) 
  //add new 100 ids start from the highest ids number in cons_ids table
  //and set new marker to 80th position again

现在每次从第一个表中删除一行时,只需将删除行中的 Id 添加到 cons_ids 中,当您再次执行 INSERT 时,它将使用您刚刚删除的 Id 号。

例如:您当前在 cons_ids 中的 id 为 46-150,您从第一个表中删除 Id = 14 的行,这 14 将添加到您的 cons_ids 中,值将变为 14 和 46-150。因此,下次您对第一个表执行 INSERT 时,您的 ID 将是 14!!。

希望我的小技巧能帮你解决问题:)

附:这只是一个示例,您可以对其进行修改以提高其性能。

【讨论】:

以上是关于将值放在升序数据库列之间的主要内容,如果未能解决你的问题,请参考以下文章

在升序和降序之间切换对列进行排序

冒泡排序

无法将值 NULL 插入列“EmpId”[关闭]

如何将值从一列映射到另一列数据框? [复制]

php四排序-冒泡排序

如何将值列表附加到数据框中的列表列