将 MySQL 插入多个表? (数据库规范化?)

我尝试在同一个查询中在多个表中搜索 insert信息的方法,但是发现这是不可能的? 因此,我想通过简单地使用多个查询即 insert它;

INSERT INTO users (username, password) VALUES('test', 'test')
INSERT INTO profiles (userid, bio, homepage) VALUES('[id of the user here?]','Hello world!', 'http://www.stackoverflow.com')

但是,我怎样才能让 idusers自动递增到 profile表的“手动”userid呢?

391449 次浏览

不,您不能在一个 MySQL 命令中插入多个表。但是您可以使用事务。

BEGIN;
INSERT INTO users (username, password)
VALUES('test', 'test');
INSERT INTO profiles (userid, bio, homepage)
VALUES(LAST_INSERT_ID(),'Hello world!', 'http://www.stackoverflow.com');
COMMIT;

查看 LAST_INSERT_ID()以重用自动增量值。

你说“ 想了这么久,还是没用。我不能简单地将刚刚生成的 ID 放在 $var 中,然后将 $var 放在所有 MySQL 命令中吗?

让我详细说明一下: 这里有三种可能的方法:

  1. 在上面的代码中 都是在 MySQL 中完成的,而 第二节 LAST_INSERT_ID() 语句将自动成为 自增量列的值 插在第一个 声明。

    不幸的是,当第二个语句本身在具有自动递增列的表中插入行时,LAST_INSERT_ID()将更新为表2的行,而不是表1的行。如果之后您仍然需要表1的值,那么我们必须将它存储在一个变量中。这将我们引向方法2和方法3:

  2. 将库存的 LAST_INSERT_ID() 一个 MySQL 变量:

    INSERT ...
    SELECT LAST_INSERT_ID() INTO @mysql_variable_here;
    INSERT INTO table2 (@mysql_variable_here, ...);
    INSERT INTO table3 (@mysql_variable_here, ...);
    
  3. 将在一个 Php 变量(或任何语言 可以连接到数据库 选择) :

    • INSERT ...
    • 使用您的语言来检索 LAST_INSERT_ID(),可以通过在 MySQL 中执行该文本语句,或者使用例如 php 的 mysql_insert_id(),它为您完成这项工作
    • INSERT [use your php variable here]

警告

无论您选择哪种方法来解决这个问题,您都必须决定应该发生什么 应该在查询之间中断执行(例如,您的数据库-服务器崩溃)。如果你能接受“有些已经完成了,有些还没有”,那就不要继续读下去了。

然而,如果您决定“要么所有查询都完成,要么没有完成——我不希望在某些表中有行,但在其他表中没有匹配的行,我总是希望我的数据库表保持一致”,那么您需要在一个事务中包装所有语句。这就是为什么我在这里使用 BEGINCOMMIT

试试这个

$sql= " INSERT INTO users (username, password) VALUES('test', 'test') ";
mysql_query($sql);
$user_id= mysql_insert_id();
if(!empty($user_id) {


$sql=INSERT INTO profiles (userid, bio, homepage) VALUES($user_id,'Hello world!', 'http://www.stackoverflow.com');
/* or
$sql=INSERT INTO profiles (userid, bio, homepage) VALUES(LAST_INSERT_ID(),'Hello   world!', 'http://www.stackoverflow.com'); */
mysql_query($sql);
};

参考文献
PHP
MYSQL

看一下 mysql _ insert _ id ()

这里的文档: http://in.php.net/manual/en/function.mysql-insert-id.php

如果使用存储过程,则相当简单:

call insert_user_and_profile('f00','http://www.f00.com');

剧本全文:

drop table if exists users;
create table users
(
user_id int unsigned not null auto_increment primary key,
username varchar(32) unique not null
)
engine=innodb;


drop table if exists user_profile;
create table user_profile
(
profile_id int unsigned not null auto_increment primary key,
user_id int unsigned not null,
homepage varchar(255) not null,
key (user_id)
)
engine=innodb;


drop procedure if exists insert_user_and_profile;


delimiter #


create procedure insert_user_and_profile
(
in p_username varchar(32),
in p_homepage varchar(255)
)
begin
declare v_user_id int unsigned default 0;


insert into users (username) values (p_username);
set v_user_id = last_insert_id(); -- save the newly created user_id


insert into user_profile (user_id, homepage) values (v_user_id, p_homepage);


end#


delimiter ;


call insert_user_and_profile('f00','http://www.f00.com');


select * from users;
select * from user_profile;

只是对你说的一句话的评论

嗨,我尝试搜索在同一查询中在多个表中插入信息的方法

你是不是把所有的午餐和饮料都放在同一个碗里?
我想是的。

我也是。
有些事情我们是分开做的。
2个插入查询是2个插入查询。没关系。没什么问题。没必要把它压碎。
精选也一样。查询必须是合理的并且能够完成其工作。这是唯一的原因。查询数量不是。

没有必要寻找在一次调用中填充不同查询的方法。

如果您想创建许多这样的记录(注册10个用户,而不仅仅是一个用户) ,会发生什么? 我找到了以下解决方案(只有5个查询) :

步骤 I: 创建临时表来存储新数据。

CREATE TEMPORARY TABLE tmp (id bigint(20) NOT NULL, ...)...;

接下来,用值填充该表。

INSERT INTO tmp (username, password, bio, homepage) VALUES $ALL_VAL

在这里,您将放置值列表: (‘ test1’,‘ test1’,‘ bio1’,‘ home1’) ,... ,(‘ testn’,‘ testn’,‘ bion’,‘ homen’) ,而不是 $ALL_VAL

第二步: 将数据发送到“ user”表。

INSERT IGNORE INTO users (username, password)
SELECT username, password FROM tmp;

在这里,“ IGNORE”可以使用,如果你允许一些用户已经在里面。可选地,您可以使用类似于步骤 III 的 UPDATE,在此步骤之前,查找用户已经在里面(并在 tmp 表中标记它们)。这里我们假设,用户名在用户表中声明为 PRIMARY

第三步: 应用更新将所有用户的 id 读取到 tmp 表。 < strong > 这是必要的一步。

UPDATE tmp JOIN users ON tmp.username=users.username SET tmp.id=users.id

步骤四: 创建另一个表,为用户使用 read id

INSERT INTO profiles (userid, bio, homepage)
SELECT id, bio, homepage FROM tmp

对于 PDO 你可以这样做

$dbh->beginTransaction();


$stmt1 = "INSERT INTO users (username, password) VALUES('test', 'test')";
$stmt2 = "INSERT INTO profiles (userid, bio, homepage) VALUES('LAST_INSERT_ID(),'Hello world!', 'http://www.stackoverflow.com')";


$sth1 = $dbh->prepare($stmt1);
$sth2 = $dbh->prepare($stmt2);


$sth1->execute (array ('test','test'));
$sth2->execute (array ('Hello world!','http://www.stackoverflow.com'));


$dbh->commit();