将值放在升序数据库列之间
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!!。
希望我的小技巧能帮你解决问题:)
附:这只是一个示例,您可以对其进行修改以提高其性能。
【讨论】:
以上是关于将值放在升序数据库列之间的主要内容,如果未能解决你的问题,请参考以下文章