2009-09-01 66 views
0

我有3张桌子。如何更新关系表?

用户(ID,邮箱,用户名等)

实践(ID,姓名)

UsersPractices(用户ID,practiceId)

最后一个是关系表是NN 。

我想根据用户的意愿更新这一个。

这意味着,他可能想要添加或删除他的一些做法。

我可以用什么算法来做到这一点?

将数据库引擎的这项工作(如果有的话)应该更好吗? 或者我应该写我自己的算法来处理数据,然后执行我对数据库的请求?

编辑:

要明确:

___________________________ 
| UserId | PracticeId | 
|-----------|-------------| 
| 12  |  21  | 
|-----------|-------------| 
| 12  |  18  | 
|-----------|-------------| 

也许,用户将尝试从21他的做法改为15,但要保持练习18

所以,从请求中,我会得到practice = array(15,18);

,这意味着用户的做法将是这样的:

___________________________ 
| UserId | PracticeId | 
|-----------|-------------| 
| 12  |  15  | 
|-----------|-------------| 
| 12  |  18  | 
|-----------|-------------| 

那么,什么是实现这一目标的最佳方式是什么?

我应该选择&检查每个练习,然后删除,如果需要?

将它们全部删除,然后添加新闻。

+0

我不太确定你到底在问什么? – Amber 2009-09-01 19:44:37

回答

2

假设您有InnoDB表,请将其作为事务处理。

这里的基本思路是擦拭板岩,然后创建/重新创建关联。这比确定每个更新的增量更容易(即,单独检查每行并确定它是否是INSERT,UPDATE或DELETE操作)。

这里的原始SQL你会使用

BEGIN; 

DELETE FROM UsersPractices 
WHERE userId = [User ID]; 

INSERT INTO UsersPractices (
     userId 
    , practiceId) 
VALUES ([User ID], [Practice ID 1]) 
    , ([User ID], [Practice ID 2]) 
    ... 
    , ([User ID], [Practice ID N]); 

COMMIT; 
+0

这就是我想的,除了交易,这确实可以在这里引起兴趣。 – 2009-09-01 20:00:57

+0

交易对于这种模式起作用非常重要。它把这个多步骤的过程变成了一个原子单位 - 如果一个部分失败了,整个事务就会失败,从而阻止你不可避免地抹去某人的忠诚。但是你不能用MyISAM表格来完成。 – 2009-09-01 20:07:34

1

检出原则(http://www.doctrine-project.org/)。这是一个用于PHP的对象关系映射器(ORM)框架。它可以轻松处理你想要完成的任务。

+0

我没有使用Doctrine,而是Zend Framework,它有不同的实现。 – 2009-09-01 19:52:34

+1

您不必使用'Zend_Db_Table'组件。您甚至可以在Zend Framework应用程序中使用Doctrine。 – 2009-09-01 19:57:21

+0

学说*应该*与ZF一起玩,如果您尝试将其添加到您的项目中。据我所知,ZF缺乏ORM。所以你可以推出你自己的解决方案,或者使用预制的解决方案。这里有一篇关于如何结合两者的文章:http://ruben.savanne.be/articles/integrating-zend-framework-and-doctrine – 2009-09-01 19:58:43

0

嗯 - 我能想到的最简单的方法来处理这样的事情是建立一个<select>元素是这样的:

function getUserPractices($userId) { 
    $data = array(); 
    $result = mysql_query("SELECT Practices.* FROM UsersPractices LEFT JOIN Practices on UsersPractices.practiceId = Practices.id WHERE userId = '".mysql_real_escape($userId)."'"); 
    while ($row = mysql_fetch_array($result)) { 
    $data[$row['id']] = $row['name']; 
    } 
    return $data; 
} 

// assuming $user is your user row... 
$user_practices = getUserPractices($user['id']); 
$result = mysql_query("SELECT * FROM Practices ORDER BY name"); 
echo "<select multiple='multiple' name='practices[]'>"; 
while ($row = mysql_fetch_assoc($result)) { 
    echo "<option value='".$row['id']."'"; 
    if (isset($user_practices[$row["id"]])) echo " selected='selected'"; 
    echo ">".htmlentities($row['name'])."</option>"; 
} 
echo "</select>"; 

// This should result in an array $_POST['practices'] that contains practiceId's 
// will come back to write more about actually inserting the change into the db 
// but simplest way is to delete all of them based on userId then insert the new ones 
1

如果您直接使用Zend_Db适配器执行SQL语句,则可以根据用户想要进行的选择构建一个UPDATE查询。例如:

$db->query('UPDATE UsersPractices 
    SET practiceId = 
     CASE practiceId 
     WHEN 21 THEN 15 
     ELSE practiceId 
     END 
    WHERE userId = ?', 
    array($userId)); 

这将改变practiceId 15只排在那里practiceId是21.其他行,它将使不改变practiceId列。

+0

这很有趣,但它看起来很难处理,因为我需要做一个选择,检索现有的做法,然后,使用您的请求,更新和检查。 无论如何,它可能会在不久的将来有用。 – 2009-09-02 09:33:34

+0

无论您使用哪种解决方案,您都需要进行选择以获取当前数据。 – 2009-09-02 14:49:33