添加和更新具有多个条目的Mysql子表

时间:2013-07-11 21:11:13

标签: php mysql arrays parent-child

我在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的内容,但这是一个坏主意,因为多人可能会一次点击该网站并且可能会重叠。任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:1)

我将为这个过程做一些假设,为你工作。

  • 如果是新条目,则表单为空白。
  • 在更新的情况下,表单将从数据库中填充为 它就是。
  • 在更新时,表单将从数据库中重新显示,并带有注释 顶部说更新已经发生。
  • 这不是银行数据或超严重故障不容忍数据。哪一个 对于您的应用程序,我认为不是。这是一种形式 处理行政数据。

我建议的帖子流程如下。 我建议稍微分开你的插入过程。

  1. 插入/更新到主表。如果是插入,请从包装行中获取记录ID,以用作目标表的外部键。

  2. 删除目标表中与外部密钥相关的所有条目。即使没有进入也会运行,并且如果有任何目标将清除所有目标。直接撕掉所有行并做一个新的插入。

  3. 使用主表的记录ID作为插入的外部键循环遍历post数组的目标部分。很难跟踪原始目标记录ID以进行更新。因为您清除了表格,所以您不必担心它,因为该数据也在帖子中。如果该人编辑了目标的措辞,则您无需检测该目标是否需要更新,因为它们都会立即重新进入。

  4. 使用从数据库中提取的数据再次显示表单。如果出现错误并将结果输出回表单,则在从目标表中清除数据后,如果更新过程中出现故障,则用户始终可以再次更新。用户将看到问题,如果数据丢失,请再试一次。
  5. 同样不是我如何处理银行数据,但是对于具有无限目标的表格,这是我发现的最简单的解决方案。
    祝你好运

答案 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();

}
相关问题