2表交互:插入,获取结果,插入

时间:2012-12-16 20:53:56

标签: php mysql stored-procedures multiple-tables

我需要对我的数据库/网络互动作出基本决定,我甚至错过了找到合适搜索字词的知识。

背景

我正在建立一个家庭网站,它支持一个论坛,家谱,带有排名和更多细节的PVP游戏,所有这些都来自数据模型。现在的技术:面向对象的Php,MySQL,javascript。

要求:

在论坛数据模型中,处理书面帖子作为新论坛主题(线程)的添加。

目前的做法:

在我当前的数据模型中,这将暗示并更新两个表:Post和Topic。 我需要在主题表中插入一行,然后获取新生成的topicId(序列),然后在插入表格中使用它

问题:

对于需要发生的事情,过多的互动,我觉得这是太多的工作。 但如果我坚持当前的做法,它将成为一个典型的要求。

问题:

  1. 我无论如何都在正确的轨道上,或者我应该
  2. 重组数据模型或
  3. 选择另一种数据库交互方式(例如存储过程)
  4. 我面对一个典型的例子,你将使用方法/框架xyz。
  5. 目前表格有以下结构(松散地基于erdiagrams.com的this one

    TOPIC :('thread')

    id
    Forum_ID (FK)
    Person_ID (FK)(threadcreator)
    IsLocked
    IsSticky
    Subject
    ViewCount
    DateCreated
    Tc_post_id  - trigger to last post_id in this thread
    

    发表

    id
    topic_id(FK)
    person_id(FK)
    subject
    message
    timestamp
    replyto
    

    然后我有一个视图,收集每个主题的最后一篇文章,并在触发器Tc_post_id上显示一些信息(例如最后一张海报图片)。

3 个答案:

答案 0 :(得分:1)

广告1和2:您的数据模型很好。在这里使用外键至关重要。您需要注意的另一件事是数据库应该确保每个POST都有一个TOPIC记录。这是通过设置POST.topic_id NOT NULL 属性来完成的。这是DB端的足够安全机制,因为它确保没有TOPIC就不会留下POST。无论你现在使用POST做什么,你都有义务提供一个主题。

广告3:此处不建议使用存储过程的触发器,因为您在TOPIC表(IsSticky,IsLocked等)中有其他数据,您可能希望在创建TOPIC记录时提供这些数据。此外,如果这样的触发器适用,数据库设计将成为非规范化的主题。

广告4:在业务逻辑方面,您现在可以通过编写自动机制来创建TOPIC记录,以便在没有指定topic_id的情况下创建新的POST记录。我建议使用一些ORM或利用任何MVC框架中提供的数据模型。这些模型的蓝图如下所示:

abstract class AModel // this class should be provided by ORM or framework
{
    /**
     * @var PDO
     */
    protected $_db_driver;

    public function getLastInsertId()
    {
        $stmt = $this->_db_driver->prepare('SELECT LAST_INSERT_ID() AS id');
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_OBJ)->id;
    }

    public abstract function getFieldList();
}

class ForumTopicModel extends AModel
{
    public function insert(array $data)
    {
        $sql = 'INSERT INTO topic VALUES (:id, :forum_id, :person_id, :is_locked, ...)';
        $stmt = $this->_db_driver->prepare($sql);
        return $stmt->execute($data);
    }

    public function getFieldList()
    {
        return array('id', 'forum_id', 'person_id', 'is_locked', /*...*/);
    }

    // ...
}

class ForumPostModel extends AModel
{
    public function insert(array $data)
    {
        $sql = 'INSERT INTO post VALUES (:id, :topic_id, :person_id, :subject, ...)';
        $stmt = $this->_db_driver->prepare($sql);
        return $stmt->execute($data);
    }

    public function getFieldList()
    {
        return array('id', 'topic_id', 'person_id', 'subject', /*...*/);
    }

    public function insertInitialTopicPost(array $form_data)
    {
        $this->_db_driver->beginTransaction();

        $result = true;

        if ( empty($form_data['topic_id']) ) {
            // no topic_id provided, so create new one:
            $topic = new ForumTopicModel();
            $topic_data = array_intersect_key(
                $form_data, array_flip($topic->getFieldList())
            );
            $result = $topic->insert($topic_data);
            $form_data['topic_id'] = $topic->getLastInsertId();
        }

        if ( $result ) {
            $forum_post_data = array_intersect_key(
                $form_data, array_flip($this->getFieldList())
            );
            $result = $this->insert($forum_post_data);
        }

        if ( $result ) {
            $this->_db_driver->commit();
        }
        else {
            $this->_db_driver->rollBack();
        }

        return $result;
    }

    // ...
}

注意:作为一个好的MVC实践,这些模型应该是直接操作表行的唯一地方。否则你最终会得到SQL错误(但数据模型将保持连贯,所以你不必担心某些事情会破坏)。

最后利用 controller 层中的模型:

class ForumPostController extends AController
{
    public function createInitialTopicPostAction()
    {
        $form_data = $this->getRequest()->getPost(); /* wrapper for getting
            the $_POST array */

        // (...) validate and filter $form_data here

        $forumPost = new ForumPostModel();
        $result = $forumPost->insertInitialTopicPost($form_data);

        if ( $result ) {
            // display success message
        }
        else {
            // display failure message
        }
    }
}

答案 1 :(得分:0)

我理解它的方式:主题是帖子的容器。

主题表格相当简洁,可能只包含topic id (PK)topic title

帖子本身将包含post id (PK)topic id (FK)timestampsauthor idtext

我会使用InnoDB和外键,因此删除的主题可能会删除所有子帖子。

答案 2 :(得分:0)

(编辑:) 在这个答案中,我发布了一种使用 mysql_insert_id()的方法,这仍然是技术上正确的解决方案(如果错误,请纠正我)。

然而我现在会选择PDO包装器。而且,这不是一般建模/方法问题的答案。

不过,以下是一种方法:

$sql = "INSERT INTO topic VALUES (NULL,'$forumId',<more parameters>)";
$result = mysql_query($sql);

#  get the generated id  
$topicId = mysql_insert_id();

#  and insert into the post table
$sql = "INSERT INTO post VALUES (NULL,'$topicId',<more parameters>)";
$result = mysql_query($sql);
mysql_free_result($result);

来源:http://www.desilva.biz/mysql/insertid.html