【发布时间】:2017-08-23 17:46:49
【问题描述】:
我正在使用三表结构来处理多对多关系。我有一个包含人员列表的表和另一个包含项目列表的表。有时多人拥有同一个项目,有时多个项目链接到同一个人,所以我设置了以下表结构:
CREATE TABLE people (
id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
fname varchar(128) NOT NULL,
lname varchar(128) NOT NULL,
);
CREATE TABLE items (
id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
name varchar(128) NOT NULL UNIQUE,
);
UNIQUE 防止项目名称重复。
CREATE TABLE people_items (
pid int(11) NOT NULL,
iid int(11) NOT NULL,
FOREIGN KEY (pid) REFERENCES people(id)
ON UPDATE CASCADE
ON DELETE CASCADE
FOREIGN KEY (iid) REFERENCES items(id)
ON UPDATE CASCADE
ON DELETE CASCADE
);
这允许我将多个项目链接到多个人,反之亦然。它还允许我从中间表中删除不必要的记录。
只要输入一个新项目,一切都可以正常工作,但如果输入一个现有项目,则不会更新中间表,即使人员表是。我也没有收到任何错误。
项目是一个逗号分隔的文本条目,它被分解并小写为$items。
首先我插入任何新项目并检索 id:
for ($i=0;$i<count($items);$i++){
$sql="INSERT IGNORE INTO items (name) VALUES (?);";
$stmt=$conn->prepare($sql);
$stmt->bind_param('s',$items[$i]);
$stmt->execute();
$itemid=$stmt->insert_id;
如果返回新的 id,则执行以下操作:
if ($itemid){
$sql="INSERT INTO people_items (pid,iid) VALUES (?,?);";
$stmt=$conn->prepare($sql);
$stmt->bind_param('ii',$peopleid,$itemid);//the $peopleid is acquired the same way that the $itemid is acquired above
$stmt->execute();
}
到这里为止,一切正常。此时,如果项目表中已经存在现有项目,则我的中间表不会更新。但是 people 表更新得很好,而 items 表不需要更新,因为它已经包含了项目。
在这里我尝试了两种不同的方法来更新中间表。
首先我将选择和插入查询分开。
elseif(!$itemid){
$sql="SELECT id,name FROM items WHERE name=?;";
$stmt=$conn->prepare($sql);
$stmt->bind_param('s',$items[$i]);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($iid,$name);
$stmt->fetch();
$sql="INSERT INTO people_items (pid,iid) VALUES (?,?);";
$stmt=$conn->prepare($sql);
$stmt->bind_param('ii',$pid,$iid);
$stmt->execute();
}
这是我的替代方法,它也不会更新中间表:
elseif(!$itemid){
$sql="INSERT INTO people_items (pid, iid) SELECT id,name FROM items WHERE name IN (?);";
$stmt=$conn->prepare($sql);
$stmt->bind_param('s',$items[$i]);
$stmt->execute();
}
我做错了什么?
【问题讨论】:
标签: php mysql mysqli many-to-many prepared-statement