2013-07-11 61 views
0

我在mysql中有两个表:称为“授予”的主表和称为“目标”的子表。赠款有一个id字段以及其他一些目标,目标有一个目标名称和一个grant_id以将其链接到授予表。添加和更新具有多个条目数的Mysql子表

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

回答

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> 

这里是它所有的功能(我给它改名dealingWithChildren从dealingWithGoals,因为这将被用于多个子表,也因为新的父亲应该有一个函数调用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(); 

} 
1

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

  • 新条目中的表单为空。
  • 在更新的情况下,表单从数据库中填充为 。
  • 更新时,表格从数据库重新显示,并在 的顶部说明更新已发生。
  • 这不是银行数据或超严重故障不容忍的数据。哪个 为您的应用程序我不认为这是。这是一个处理管理数据的表格。

我建议的Post过程如下。 我建议分割一下你的插入过程。

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

  2. 删除目标表中与外键相关的所有条目。即使没有进入,这也会运行,并且如果有任何进入,将会清除所有目标。从字面上撕掉所有行并重新插入。

  3. 使用主表的记录ID作为插入的外键来循环访问数组的目标部分。要跟踪原始目标记录ID以便更新是非常困难的。因为您清除了表格,所以您不用担心,因为该数据也在帖子中。如果该人编辑目标的措词,则无需检测该目标是否需要更新,因为它们都是同时重新进入的。

  4. 用从数据库中提取的数据再次显示表单。如果出现错误,并且将结果输出回表单,则在从目标表中清除数据后,如果更新过程中出现故障,则用户可以始终再次更新结果。如果数据丢失,用户将看到该问题并再次尝试。

再次不是我如何处理银行数据,但对于无限数量的目标可以加以解决的形式是我找到的最简单的解决方案。
最好的运气