(编辑:我在下面添加了示例。我还按照注释中的建议在表中添加了public_ip)
(仅免责声明,我对Web开发仍然是一个新手。与PhP结合使用,我对MySQL的了解特别少。)
我有一个包含数字记录的数据库表。对于此示例,它包含DVD的记录。我的php页面之一收到要删除的DVD的ID,然后继续这样做。($ chosenTable是一个变量,因为我对CD,Vinyls和其他光盘也有不同的表-它们都有相同的列)
$sql = "DELETE FROM $chosenTable WHERE id=$removeID";
$conn->exec($sql);
但是我注意到最近它会删除不存在的记录。例如,我将在数据库中使用它:
ID-标题-评论-文件位置
1-Bones先生-非常新-Folder / Bones.jpg
2-复仇者联盟-二手-Folder / Avengers.jpg
第一次使用删除查询即可。如果我发送“ 2”,它将删除记录二。如预期的那样,我还有一个记录:
ID-标题-评论-文件位置
1-Mr Bones-非常新-Folder / Bones.jpg
然后,我将添加一条新记录。从phpMyAdmin的数据库中,我绝对确定已添加:
ID-标题-注释-文件位置
1-Bones先生-非常新-Folder / Bones.jpg
2-Intersteller-破碎-Folder / Intersteller.jpg
但是,这就是我留下的任何解释。如果我再次删除第二条记录(这次是Intersteller),那么什么也不会发生。当我检查了要删除的记录的标题时,它将返回旧的第二条记录的标题。
获取要删除的记录信息:
$temp = $conn->query("SELECT Title from $chosenTable WHERE ID='$removeID')->fetch()["Title"];
echo $temp;
当我这样做时,它将返回“复仇者联盟”。考虑到上面的示例,返回的标题应该是Intersteller而不是 Avengers。复仇者联盟不再存在于表格中。我对此绝对有把握。所以现在我知道它不会删除第二条记录(Intersteller),因为它正在删除旧的第二条记录“复仇者联盟”。当我删除第三条或第四条记录时,情况也是如此(相反,它删除不存在的旧的第三条和第四条记录)。
出于某种原因,Chrome或服务器似乎在自己使用的伪表而不是我的实际表中存储了自己的伪表。
我整天看了看,找不到这个解决方案。对于任何愚蠢的错误,我再次表示歉意。我只是真的希望我能理解我到底该如何做。
我注意到当我使用其他浏览器(例如Firefox甚至智能手机的浏览器)时,它再次允许我删除一次记录。如果我上载并删除另一个项目,那么我会遇到完全相同的问题。它发生在不同的浏览器上使我认为问题出在我身上。
我正在使用数据库MySQL客户端版本:5.6.43
有什么帮助吗?
编辑:我做了两个PHP页面来模拟问题。发生同样的事情。我不知道如何连接到数据库提琴,所以我希望代码本身就足够了。upload.php提交信息并将其添加到数据库表中。remove.php删除表之一的记录:
upload.php
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST"){
//Get info from POST
$uTitle = $_POST["iTitle"];
$uComment = $_POST["tComment"];
$uPrice = $_POST["iPrice"];
echo "<script>console.log('$uTitel - $uComment - $uPrice);</script>";
//Set a file location for the uploaded picture
$fileName = basename($_FILES["iFile"]["name"]);
echo "<script>console.log('filenaam: $fileName');</script>";
$saveLocation = "uploads/".$fileName;
echo "<script>console.log('Saved locationk: $saveLocation');</script>";
//Upload file
if (move_uploaded_file($_FILES["iFile"]["tmp_name"], $saveLocation))
{
//If file is successfully uploaded
echo "<script>console.log('File uploaded');</script>";
//For connecting to database table - these four variables obviously just for illustration:
$servername = "localhost";
$connectusername = "alyosha";
$connectpassword = "alyoshaPassword";
$dbname = "alyoshaDB";
try { //If connected to database
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $connectusername, $connectpassword);
echo "<script>console.log('Connected to Database');</script>";
//I first see how many records are already in the table so that I can add the appropriate value for my 'public_ip' column
$m = $conn->prepare("SELECT * from testTable");
$m->execute();
$amountRows = $m->rowCount();
echo "<script>console.log('Amount in table before adding record: $amountRows');</script>";
//newIP is the current amount+1 so that it is added below my previous records (if there are 3 records, the new one should obviously be record public_ip 4)
$newIP = $amountRows +1;
//Now for adding a row to the table with the submitted informaton:
$sql = "INSERT INTO testTable (public_ip, Title, Comment, Price, File_Location) VALUES ($newIP, '$uTitle', '$uComment', $uPrice, '$saveLocation')";
$conn->exec($sql);
echo "<script>console.log('New row added');</script>";
//Count again to make sure there is one more record than before
$m = $conn->prepare("SELECT * from testTable");
$m->execute();
$amountRows = $m->rowCount();
echo "<script>console.log('Amount in table after adding record: $amountRows');</script>";
}
catch (PDOException $e){ //if database did not connect
echo "<script>console.log('Failed to connect to database');</script>";
}
}//if move
}//if post
?>
<!DOCTYPE html>
<html>
<head>
<title>Add item</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
</head>
<body>
<header>
<h1>Upload</h1>
</header>
<form action='upload.php' method='post' enctype='multipart/form-data'>
<input type='file' name='iFile' required>
<br/>
<br/>
<label for='iTitle'>Title:</label>
<input type='text' name='iTitle' required>
<br/>
<br/>
<label for='iPrice'>Price:</label>
<input id='iPriceUpload' type='number' name='iPrice' min='1' required>
<br/>
<br/>
<label for='tComment'>Comments (optional):</label>
<br/>
<textarea type='text' name='tComment'></textarea>
<br/>
<br/>
<input type='reset' name='iReset'>
<input type='submit' name='iSubmit'>
<br/>
<a href='remove.php?num=1'>Remove record 1</a>
<!--In practise the user would not be able to choose this by altering the link, but for my example this is easier to change this here -->
</body>
</html>
remove.php:
<?php
if ($_SERVER["REQUEST_METHOD"] == "GET"){
$removeIP = $_GET["num"]; //The public_ip record to be deleted
//Connect to table
servername = "localhost";
$connectusername = "alyosha";
$connectpassword = "alyoshaPassword";
$dbname = "alyoshaDB";
try { //If connected to database
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $connectusername, $connectpassword);
echo "<script>console.log('Connected to Database in Remove.php');</script>";
//All the remaining records should have their public_ips shifted upwards (5->4, 4->3, 3->2, 2->1)
//It is necessary to again count the amount of rows left to achieve this
$m = $conn->prepare("SELECT * from testTable");
$m->execute();
$amountRows = $m->rowCount();
echo "<script>console.log('Amount of rows before deleting: $amountRows');</script>";
//For debugging purposes get the title of removeIP:
$gotTitle = $conn->query("SELECT Title from testTable WHERE public_ip='$removeIP'")->fetch()["Title"];
echo "<script>console.log('Title of record $removeIP to be deleted: $gotTitle');</script>";
//
$sql = "DELETE FROM testTable WHERE public_ip=$removeIP"; //public_ip=1
$conn->exec($sql);
echo "<script>console.log('Record $removeIP deleted');</script>";
//count again to make sure one record is removed:
$m = $conn->prepare("SELECT * from testTable");
$m->execute();
$amountRows = $m->rowCount();
echo "<script>console.log('Amount of rows affter deleting: $amountRows');</script>";
if ($removeIP < ($amountRows+1)){ //in case the removed record is the only one in the table it won't be necessary to change the public_ips of the rest
for ($x = 1; $x < ($amountRows+2); $x++)
{
echo "<script>console.log('Changing record: $x');</script>";
$lowerIP = $x-1; //The record with public_ip 2 should become public_ip 1, and 3->2, etc
$sql = "UPDATE testTable SET public_ip=$lowerIP WHERE public_ip=$x";
$stmt = $conn->prepare($sql);
$stmt->execute();
}
echo "<script>console.log('Loop finished');</script>";
}
}
catch (PDOException $e){
echo "<script>console.log('Failed to connect to database in Remove.php');</script>";
}
}//if GET
//After everything go back to upload page
echo "<script>window.location = 'upload.php';</script>";
?>
更新:从广泛的评论看来,PHP和浏览器之间的某些地方正在缓存页面。@Martin提出了一种变通办法,在我解决此问题之前,这似乎非常有用。这是在页面网址中添加日期字符串,从而迫使浏览器读取新页面而不是缓存页面(如果我正确理解的话)。
但是如果有人仍然可以一开始就解释为什么这是一个问题,我将非常感激。我可以使用页面的旧版本来了解浏览器或任何其他内容,但是无论如何将过时的表保存在某个地方,我都无法理解。
顺便说一句,在删除行时对行进行重新编号的工作真是个坏主意。
为什么?
一方面,这样做的成本增加了您拥有的更多行。SQL的全部目的是允许您有效地处理庞大的表。
另一方面,当您有多个用户这样做时,您会感到困惑。如果一个用户正在查找内容,而另一个用户正在删除它们,则第一个用户将在她下面更改行号。您可以通过明智地使用数据库事务来进行管理,但是它们只会阻止第二个用户,直到第一个用户完成为止。这种情况通常称为“竞赛条件”。
您提到您是MySql的新手。再次重申一下,我建议您坚持使用经过验证的ID编号方法:自动递增。当您从自动递增表中删除一行时,插入的下一行不会重复使用已删除的ID。
每个人都使用自动递增的ID值-从学生到拥有不可思议的庞大表格的信用卡公司。我建议您这样做,至少要等到您对该技术有所了解为止。
编辑如果你想在你插入的顺序来显示你的行,根本就SELECT whatever FROM tbl ORDER BY id
在那里id
是自增ID列。由于删除行而导致ID序列中的空白不是问题。
如果您具有特定的ID值,并且想要下一行,请按照插入它们的顺序进行操作
SELECT whatever
FROM tbl
WHERE id > <<<the value you have>>
ORDER BY id
LIMIT 1;
该id > <<<the value you have>>
过滤器即使在ID值之间存在间隙的情况下也可以工作。
您说只有一个用户。但是,如果该用户碰巧同时打开了两个在数据库上工作的网页,则重新编号设置将失败。壮观地。当您拥有网络界面时,最安全的做法就是假设您可以进行并发访问。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句