我在mysql中有两个表:一个名为“grants”的主表和一个名为“goals”的子表。 Grants有一个id字段以及一堆其他字符,目标有一个目标名称和一个grant_id,用于将其链接到授权表。
在html表单上,用户可以根据需要添加或编辑任意数量的目标(我使用Javascript添加新输入)。表单还会添加任何先前的目标并将其添加到表单中。
<div id="goals">
<?php
$goals = getGoalsById($_GET['id']);
if (empty($goals)) echo "<p>Goal 1: <input type='text' size='40' name='goals[]' /></p>";
else {
$i = 1;
foreach($goals as $goal) {
echo "<p>Goal {$i}: <input type='text' size='40' name=\"goals[{$goal['id']}]\" value=\"{$goal['goal']}\" /></p>";
$i++;
}
}
?>
</div>
<input type="button" value="Add goal" onClick="addInput('goals')" />
当我提交表单时,我有以下声明来插入或更新目标:
foreach($goals as $key=>$goal) {
$sql_goals_add[] = "INSERT INTO goals (id, goal, grant_id) VALUES ($key,:goalnew,$grant_id) ON DUPLICATE KEY UPDATE goal = :goalupdate";
foreach ($sql_goals_add AS $sql_goal) {
$stmt_goal = $DBH->prepare($sql_goal);
$stmt_goal->bindValue(':goalnew', $goal, PDO::PARAM_STR);
$stmt_goal->bindValue(':goalupdate', $goal, PDO::PARAM_STR);
}
$stmt_goal->execute();
}
这适用于更新现有目标,因为传递的键是目标表中的id。但是,我遇到的问题是当他们有新的目标时,从表单传递的$ goals数组总是从0开始,因此插入查询尝试使用0,1,2等作为插入ID。我宁愿让它自动选择目标表中的下一个可用ID。
我试图自动填充我认为可能是新目标ID的内容,但这是一个坏主意,因为多人可能会一次点击该网站并且可能会重叠。任何帮助表示赞赏!
答案 0 :(得分:1)
我将为这个过程做一些假设,为你工作。
我建议的帖子流程如下。 我建议稍微分开你的插入过程。
插入/更新到主表。如果是插入,请从包装行中获取记录ID,以用作目标表的外部键。
删除目标表中与外部密钥相关的所有条目。即使没有进入也会运行,并且如果有任何目标将清除所有目标。直接撕掉所有行并做一个新的插入。
使用主表的记录ID作为插入的外部键循环遍历post数组的目标部分。很难跟踪原始目标记录ID以进行更新。因为您清除了表格,所以您不必担心它,因为该数据也在帖子中。如果该人编辑了目标的措辞,则您无需检测该目标是否需要更新,因为它们都会立即重新进入。
同样不是我如何处理银行数据,但是对于具有无限目标的表格,这是我发现的最简单的解决方案。
祝你好运
答案 1 :(得分:0)
所以,在G +中进行讨论之后,我最终解决了问题:
1)重命名传递给goalsNew和goalsExisting的数组 2)更改函数以分别解析每个数组,以便它对新条目执行插入,但对现有条目进行更新。以下是完整的代码,以防有人关心。 :)
<div id="goals">
<?php
$goals = getGoalsById($_GET['id']);
if (empty($goals)) echo "<p>Goal 1: <input type='text' size='40' name='goalsNew[]' /></p>";
else {
$i = 1;
foreach($goals as $goal) {
echo "<p>Goal {$i}: <input type='text' size='40' name=\"goalsExisting[{$goal['id']}]\" value=\"{$goal['goal']}\" /></p>";
$i++;
}
}
?>
</div>
这是完成所有操作的函数(我将其更名为来自dealWithGoals的DealWithChildren,因为这将用于多个子表,但也因为新父应该有一个名为dealingWithChildren的函数!
function dealWithChildren($childType, $childNew, $childExisting, $grant_id) {
$fieldName = substr($childType, 0, -1);
dbConnect();
global $DBH;
try {
// If there are no children at all, delete them all
if(empty($childNew) && empty($childExisting)) {
$sql_child_delete = "DELETE FROM $childType WHERE grant_id = $grant_id";
$stmt_child = $DBH->prepare($sql_child_delete);
$stmt_child->execute();
}
// If the user removed a child, delete those children
if(!empty($childExisting)) {
$sql_child_delete = "DELETE FROM $childType WHERE grant_id = $grant_id AND id NOT IN (";
$i = 0;
$len = sizeof($childExisting);
foreach($childExisting as $key=>$child) {
$sql_child_delete .= $key;
if ($len > 1 && $i < $len-1) $sql_child_delete .= ",";
$i++;
}
$sql_child_delete .= ")";
$stmt_del_child = $DBH->prepare($sql_child_delete);
$stmt_del_child->execute();
}
// If a user added any children
if(!empty($childNew)) {
foreach($childNew as $key=>$child) {
$sql_child_add[] = "INSERT INTO $childType ($fieldName, grant_id) VALUES (:childnew,$grant_id)";
foreach ($sql_child_add AS $sql_child) {
$stmt_child = $DBH->prepare($sql_child);
$stmt_child->bindValue(':childnew', $child, PDO::PARAM_STR);
}
$stmt_child->execute();
}
}
// If a user updated any children
if(!empty($childExisting)) {
foreach($childExisting as $key=>$child) {
$sql_child_update[] = "UPDATE $childType SET $fieldName = :childupdate WHERE id = $key";
foreach ($sql_child_update AS $sql_child) {
$stmt_child = $DBH->prepare($sql_child);
$stmt_child->bindValue(':childupdate', $child, PDO::PARAM_STR);
}
$stmt_child->execute();
}
}
} catch (PDOException $f) {
echo 'Database query failure: ' . $f->getMessage();
//exit;
}
dbDisconnect();
}