【问题标题】:How to prevent duplicate record inserts with PDO如何使用 PDO 防止重复记录插入
【发布时间】:2015-04-14 18:48:06
【问题描述】:

我想尝试设置一些东西,如果用户已经提交了一个部门密钥和当前日期,它将停止插入记录。它会给出一个错误,说重复的记录输入了再试一次。

这是我插入页面的一部分,但它不起作用

$stmt= $db->prepare("INSERT INTO tbl_lighting(Department, 
    areaCode, offtime, gytime, ftime, ini, 
    sat_ob_department, sat_ib_department,
    sat_ob_onTime,sat_ib_onTime,
    sat_ob_offTime, sat_ib_offTime,
    ob_signature,ib_signature, 
    deptkey, comments,ib_comments,ob_comments,Requestdate

 ) Values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)WHERE NOT EXISTS 
(SELECT * FROM tbl_lighting where deptkey = $deptkey AND Requestdate= CAST(GETDATE() AS DATE)");

$stmt->bindParam(1, $_POST["Department"]);
$stmt->bindParam(2, $_POST["areaCode"]);
$stmt->bindParam(3, $_POST["offtime"]);
$stmt->bindParam(4, $_POST["gytime"]);
$stmt->bindParam(5, $_POST["ftime"]);
$stmt->bindParam(6, $_POST["ini"]);
$stmt->bindParam(7, $_POST["sat_ob_department"]);
$stmt->bindParam(8, $_POST["sat_ib_department"]);
$stmt->bindParam(9, $_POST["sat_ob_onTime"]);
$stmt->bindParam(10, $_POST["sat_ib_onTime"]);
$stmt->bindParam(11, $_POST["sat_ob_offTime"]);
$stmt->bindParam(12, $_POST["sat_ib_offTime"]);
$stmt->bindParam(13, $_POST["ob_signature"]);
$stmt->bindParam(14, $_POST["ib_signature"]);
$stmt->bindParam(15, $_POST["deptkey"]);
$stmt->bindParam(16, $_POST["comments"]);
$stmt->bindParam(17, $_POST["ib_comments"]);
$stmt->bindParam(18, $_POST["ob_comments"]);
$stmt->bindParam(19, $_POST["Requestdate"]);


$stmt->execute();

这是我的提交表单

<form action = "insert_process.php" onsubmit="return validateForm()" name="form" id="form" method ="post" class="style1">

<table align="center" id="tfhover" class="tftable" border="1">
<br><br>
<tr>
<td colspan="7"><h1 align="center">Lighting Schedule Form</h1></td>
</tr>

<tr>
<th>Department</th><th style="width: 75px">Area Code</th><th style="width: 144px">Off Time</th><th>Grave Yard On Time</th><th>First Shift OnTime</th><th width="125px">Comments Or Date By</th><th>Initials</th></tr>

<tr>

    <!--First row accross on the table-->
<td><select name="Department" id="Department" >
            <option value ="">Please select ...</option>
            <option value ="Upstairs Hang East">Upstairs Hang East</option>
            <option value ="Upstairs Hang West">Upstairs Hang West</option>
            <option value ="RDR">RDR</option>
            </select></td>
<td style="width: 75px"><input id="areaCode" name="areaCode" onkeydown="return false;" type="text"/></td>
<td style="width: 144px"><input class="offtime" id="offtime" name="offtime"  type="text" /></td>
<td><input id="gytime" name="gytime" type="text"></td>
<td><input id="ftime" name="ftime" type="text" ></td>
<td><input id="comments" name="comments" type="text"></td>
<td><input id="ini" name="ini" type="text" style="width: 68px" /></td>
</tr>


<input id="deptkey" name="deptkey" onkeydown="return false;" type="hidden"/>

    <!--end-->

【问题讨论】:

  • “如何使用 PDO 防止重复记录插入” - 不是检查一大堆代码,而是在给定列上设置唯一约束,不是吗?
  • stackoverflow.com/questions/4596390/… 创建唯一的配对密钥。
  • 旁注:您确实有结束 &lt;/form&gt; 标记,对吗?另外,你也有一些 JS 发生;很难说这是否是问题的一部分。
  • 连接打开后立即添加$db-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);。将错误报告添加到您的打开 PHP 标记(例如 &lt;?php error_reporting(E_ALL); ini_set('display_errors', 1);)之后的文件顶部,然后是其余代码,以查看它是否产生任何结果。这是为了检查您可能遇到的可能错误,因为您可能没有检查它们而没有看到它们。
  • 正确的做法是添加唯一约束,插入和在重复记录的情况下 - 捕获异常并通知用户。 没有其他可能的正确方法。 @Fred-ii- 告诉你的是你是怎么做的。唯一约束 + 异常模式下的 PDO。

标签: php html sql-server pdo


【解决方案1】:

问题的本质是停止重复记录,我将解释为什么使用 PDO 的唯一键和异常是正确的方法。

数据库维护关系并存储数据。数据库的工作之一是处理并发和存储数据。通过创建唯一键来防止数据库中的重复记录,因此根本不允许此类记录出现在数据模型中。数据库处理同时连接的多个用户,这些用户依次插入一些数据。

我看到人们做的是选择一条记录,然后检查它是否存在以及是否返回 0 行 - 他们继续插入。这是一种不好的方法,它不仅会损害性能,而且经常无法防止重复记录。原因是 PHP(或任何语言)和 MySQL 服务器(或任何其他数据库服务器)之间存在轻微延迟。当您选择数据并完成检查时,已经过了一小段时间——比如说 1 毫秒。在此期间,另一个用户可能已经连接并经历了相同的过程(选择,检查是否 0 行,如果 0 插入)。由于两个用户同时做同样的事情,两者都会得到关于结果的信息——因为 PHP 进程和 MySQL 之间的延迟很小。反过来,您最终可能会得到重复的记录。您还花时间选择了一些东西并通过套接字连接发送它。

让数据库处理所有工作要快得多。由于由于唯一约束而不能发生插入,因此您只需插入并让插入失败就容易得多(它比在 PHP 中选择和检查要“便宜”得多)。数据库还负责并发或“同时多个用户”。这意味着您的数据库知道其数据的状态,最好让它继续这样做。您最终也会得到更少的代码。

你的算法应该是这样的:

  • 获取输入
  • 准备声明
  • 执行插入
  • 如果出现异常,则存在重复记录(您可以检查数据库返回的代码,以确保是因为重复键或其他原因)

弗雷德在他的评论中所说的是正确的,也是真正防止重复插入的唯一正确方法。此外,由于您使用的是准备好的语句,因此您无需在语句中指定任何变量。只需绑定所有内容,让 PDO 负责清理用户输入。

【讨论】:

  • 有没有一个例子,你可以给我看一个链接。我不是高级 php 程序员。
【解决方案2】:

也许你必须像这样转义你的 php 变量 $deptkey,并且像这样将 WHERE 条件大写:


$stmt= $db->prepare("INSERT INTO tbl_lighting(Department, 
    areaCode, offtime, gytime, ftime, ini, 
    sat_ob_department, sat_ib_department,
    sat_ob_onTime,sat_ib_onTime,
    sat_ob_offTime, sat_ib_offTime,
    ob_signature,ib_signature, 
    deptkey, comments,ib_comments,ob_comments,Requestdate

) Values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)WHERE NOT EXISTS (SELECT * FROM tbl_lighting WHERE deptkey = '".$deptkey."' AND Requestdate= CAST(GETDATE() AS DATE)");

【讨论】:

    猜你喜欢
    • 2016-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    • 2019-09-28
    • 2012-08-04
    相关资源
    最近更新 更多