繁体   English   中英

多个INSERTS分为一个表和多个表

[英]Multiple INSERTS into one table and many to many table

我正在尝试使用PostgreSQL数据库在PHP中开发一个Q&A网站。 我有一个动作来创建一个页面,其中包含标题,正文,类别和标签。 我设法插入所有这些字段,但是我在插入多个标记值时遇到了一些问题。

我使用这个函数将逗号分隔的值放到一个数组中,现在我想要一些东西将每个数组元素插入到数据库中(避免重复)在表tags ,然后插入我的多对多关系表questiontags tags

$tags = explode(',', $_POST['tags']); //Comma separated values to an array

打印这样的东西:

Array ( [0] => hello [1] => there [2] => this [3] => is [4] => a [5] => test )

动作/ create_question.php

$category = get_categoryID_by_name($_POST['category']);

$question = [
    'userid' => auth_user('userid'),
    'body' => $_POST['editor1'],
    'title' => $_POST['title'],
    'categoryid' => $category
];

create_question($question, $tags);

然后我的create_question我应该插入标签。

function create_question($question, $tags) {

    global $conn;
    $query_publications=$conn->prepare("SELECT * FROM insert_into_questions(:body, :userid, :title, :categoryid);
");
    $query_publications->execute($question);
}

我在考虑做这样的事情:

全球$ conn;

foreach ($tags as $tag) {

    $query_publications=$conn->prepare("INSERT INTO tags(name) VALUES($tag);
");
    $query_publications->execute($question);    
}

但后来我需要在我的多对多表中插入标签id。 我是否需要创建另一个过程get_tags_id然后获取tag_id数组并在我尝试标记时插入它们? 我什么时候执行查询? 插入后或彼此结束?

对于任何误用的术语或我的新手问题,我们深表歉意。 我是PHP的新手,我正在努力解决一些新概念。

您可以使用CTE在一个 SQL命令中完成所有操作。

假设Postgres 9.6和这个经典的多对多模式(因为你没有提供它):

CREATE TABLE questions (
  question_id serial PRIMARY KEY
, title text NOT NULL
, body text
, userid int
, categoryid int
);

CREATE TABLE tags (
  tag_id serial PRIMARY KEY
, tag text NOT NULL UNIQUE);

CREATE TABLE questiontags (
  question_id int REFERENCES questions
, tag_id      int REFERENCES tags
, PRIMARY KEY(question_id, tag_id)
);

要使用标记数组插入单个问题

WITH input_data(body, userid, title, categoryid, tags) AS (
   VALUES (:title, :body, :userid, :tags)
   )
 , input_tags AS (                         -- fold duplicates
      SELECT DISTINCT tag
      FROM   input_data, unnest(tags::text[]) tag
      )
 , q AS (                                  -- insert question
   INSERT INTO questions
         (body, userid, title, categoryid)
   SELECT body, userid, title, categoryid
   FROM   input_data
   RETURNING question_id
   )
 , t AS (                                  -- insert tags
   INSERT INTO tags (tag)
   TABLE  input_tags  -- short for: SELECT * FROM input_tags
   ON     CONFLICT (tag) DO NOTHING        -- only new tags
   RETURNING tag_id
   )
INSERT INTO questiontags (question_id, tag_id)
SELECT q.question_id, t.tag_id
FROM   q, (
   SELECT tag_id
   FROM   t                                -- newly inserted
   UNION  ALL
   SELECT tag_id
   FROM   input_tags JOIN tags USING (tag) -- pre-existing
   ) t;

dbfiddle 在这里

这会创建任何尚未存在的标记。

Postgres数组的文本表示如下所示: {tag1, tag2, tag3}

如果保证输入数组具有不同的标记,则可以从CTE input_tags删除DISTINCT

详细说明

如果您有并发写入 ,则可能需要执行更多操作。 特别考虑第二个链接。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM