强制将记录插入多个表
Enforce inserting records into multiple tables
我有两个表 parent
和 child
。只有当两个表的查询都成功时,我才想在两个表中插入一条记录。理想情况下,完整性将由数据库强制执行,但是,如果需要,使用应用程序这样做是可以接受的。潜在地,我可以做类似下面的事情,但是,似乎会有更优雅的方法来做到这一点。这应该如何实现?
<?php
//parent must be inserted first as child has a FK constraint to it
$stmt1=$conn->prepare('INSERT INTO parent(id,data) VALUES(?,?)');
if($stmt1->execute(array(123,"foo"))) {
$stmt2=$conn->prepare('INSERT INTO child(parent_id,data) VALUES(?,?)');
if(!$stmt2->execute(array(123,"bar"))) {
$stmt3=$conn->prepare('DELETE FROM parent WHERE id=?');
$stmt3->execute(array(123));
}
}
?>
编辑。像下面这样的东西会起作用吗?
<?php
$queries=array(
array('sql'=>'INSERT INTO parent(id,data) VALUES(?,?)',$data=>array(123,"foo")),
array('sql'=>'INSERT INTO child(parent_id,data) VALUES(?,?)',$data=>array(123,"bar")),
//More if necessary array('sql'=>'',$data=>array()),
);
doMultipleQueries($queries);
function doMultipleQueries($queries) {
try {
$conn->beginTransaction();
foreach($queries as $query) {
$stmt=$conn->prepare($query['sql']);
$stmt->execute($query['data']);
}
$conn->commit();
return true;
} catch (Exception $e) {
$conn->rollBack();
return false;
}
}
?>
架构
CREATE TABLE IF NOT EXISTS `parent` (
`id` INT NOT NULL,
`data` VARCHAR(45) NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `child` (
`parent_id` INT NOT NULL,
`data` VARCHAR(45) NULL,
PRIMARY KEY (`parent_id`),
CONSTRAINT `fk_child_parent`
FOREIGN KEY (`parent_id`)
REFERENCES `parent` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
您应该查看数据库事务,如果其中一个操作失败,它们将恢复所有操作
使用交易:
http://dev.mysql.com/doc/refman/5.0/en/commit.html
您还可以设置约束以在删除和更新时级联更改,而不是不执行任何操作。
http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
当然事务是最好的解决方案但是如果不喜欢用它,可以用PDO做多查询,see this page
我有两个表 parent
和 child
。只有当两个表的查询都成功时,我才想在两个表中插入一条记录。理想情况下,完整性将由数据库强制执行,但是,如果需要,使用应用程序这样做是可以接受的。潜在地,我可以做类似下面的事情,但是,似乎会有更优雅的方法来做到这一点。这应该如何实现?
<?php
//parent must be inserted first as child has a FK constraint to it
$stmt1=$conn->prepare('INSERT INTO parent(id,data) VALUES(?,?)');
if($stmt1->execute(array(123,"foo"))) {
$stmt2=$conn->prepare('INSERT INTO child(parent_id,data) VALUES(?,?)');
if(!$stmt2->execute(array(123,"bar"))) {
$stmt3=$conn->prepare('DELETE FROM parent WHERE id=?');
$stmt3->execute(array(123));
}
}
?>
编辑。像下面这样的东西会起作用吗?
<?php
$queries=array(
array('sql'=>'INSERT INTO parent(id,data) VALUES(?,?)',$data=>array(123,"foo")),
array('sql'=>'INSERT INTO child(parent_id,data) VALUES(?,?)',$data=>array(123,"bar")),
//More if necessary array('sql'=>'',$data=>array()),
);
doMultipleQueries($queries);
function doMultipleQueries($queries) {
try {
$conn->beginTransaction();
foreach($queries as $query) {
$stmt=$conn->prepare($query['sql']);
$stmt->execute($query['data']);
}
$conn->commit();
return true;
} catch (Exception $e) {
$conn->rollBack();
return false;
}
}
?>
架构
CREATE TABLE IF NOT EXISTS `parent` (
`id` INT NOT NULL,
`data` VARCHAR(45) NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `child` (
`parent_id` INT NOT NULL,
`data` VARCHAR(45) NULL,
PRIMARY KEY (`parent_id`),
CONSTRAINT `fk_child_parent`
FOREIGN KEY (`parent_id`)
REFERENCES `parent` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
您应该查看数据库事务,如果其中一个操作失败,它们将恢复所有操作
使用交易: http://dev.mysql.com/doc/refman/5.0/en/commit.html
您还可以设置约束以在删除和更新时级联更改,而不是不执行任何操作。 http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
当然事务是最好的解决方案但是如果不喜欢用它,可以用PDO做多查询,see this page