MySQL插入到多个表中? (数据库正常化?)

我试图寻找一种方法在同一个查询中的多个表中插入信息,但发现这是不可能的? 所以我想通过使用多重查询即插入它;

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') 

但是,我怎样才能从用户的自动递增ID到configuration文件表的“手动”用户ID?

不,你不能在一个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()将自动成为插入到第一个语句中的autoincrement列的值。

    不幸的是,当第二个语句本身在一个带有自动增量列的表中插入行时, LAST_INSERT_ID()将被更新为表2的表,而不是表1.如果你之后仍然需要表1的话,将其存储在一个variables中。 这导致我们的方式2和3:

  2. LAST_INSERT_ID()在一个MySQLvariables中:

     INSERT ... SELECT LAST_INSERT_ID() INTO @mysql_variable_here; INSERT INTO table2 (@mysql_variable_here, ...); INSERT INTO table3 (@mysql_variable_here, ...); 
  3. LAST_INSERT_ID()在一个phpvariables(或任何可以连接到您select的数据库的语言)中:

    • INSERT ...
    • 使用你的语言来检索LAST_INSERT_ID() ,或者通过在MySQL中执行该文字语句,或者使用例如php的mysql_insert_id()来为你做这个
    • INSERT [use your php variable here]

警告

无论select什么方式来解决这个问题,你都必须决定在查询之间执行被中断 (例如,你的数据库服务器崩溃)应该发生什么。 如果你能忍受“一些已经完成,另一些没有”,不要继续阅读。

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

再次评论,如果你需要更多的信息:)

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

 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; 

尝试这个

 $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

如果你想创build许多这样的logging(如果要注册10个用户,而不是一个),会发生什么? 我find以下解决scheme(只有5个查询):

第一步:创build临时表来存储新的数据。

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

接下来,填充这个值。

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

在这里,不是$ALL_VAL ,而是放置值列表:('test1','test1','bio1','home1'),…,('testn','testn','bion','homen' )

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

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

在这里,“IGNORE”可以使用,如果你允许一些用户已经在里面。 可选的,你可以使用类似于第三步的UPDATE,在这一步之前,找出哪些用户已经在里面(并且把它们标记在tmp表中)。 在这里,我们认为,用户名在用户表中声明为PRIMARY

第三步:应用更新从用户读取所有用户id到tmp表。 这是必不可less的步骤。

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

第四步:创build另一个表,为用户使用读取ID

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

只是说一下你的话

嗨,我试图寻找一种方法来在同一个查询中的多个表中插入信息

你在同一个碗里把你所有的混合饮料的午餐都吃了吗?
我想 – 不。

同样在这里。
有些事情我们分开做。
2个插入查询是2个插入查询。 没关系。 没有错。 没有必要在一个捣烂它。
相同的select。 查询必须明智,并做好工作。 这是唯一的原因。 查询数量不是。

至于交易 – 你可以使用它们,但对于一般的网站来说并不是什么大事。 如果每年发生一次(如果曾经发生)一个用户注册被破坏,那么您将无疑可以修复。
有数十万个运行mysql的站点没有事务支持驱动程序。 你听说过把这些网站分开的可怕的灾难吗? 我也不。

和mysql_insert_id()有关的交易。 你可以包括在交易中。 这只是不同的事情。 有人提出这个问题的地方。

这是我为一个uni项目做的,工作正常,可能不安全

 $dbhost = 'localhost'; $dbuser = 'root'; $dbpass = ''; $conn = mysql_connect($dbhost, $dbuser, $dbpass); $title = $_POST['title']; $name = $_POST['name']; $surname = $_POST['surname']; $email = $_POST['email']; $pass = $_POST['password']; $cpass = $_POST['cpassword']; $check = 1; if (){ } else{ $check = 1; } if ($check == 1){ require_once('website_data_collecting/db.php'); $sel_user = "SELECT * FROM users WHERE user_email='$email'"; $run_user = mysqli_query($con, $sel_user); $check_user = mysqli_num_rows($run_user); if ($check_user > 0){ echo '<div style="margin: 0 0 10px 20px;">Email already exists!</br> <a href="recover.php">Recover Password</a></div>'; } else{ $users_tb = "INSERT INTO users ". "(user_name, user_email, user_password) ". "VALUES('$name','$email','$pass')"; $users_info_tb = "INSERT INTO users_info". "(user_title, user_surname)". "VALUES('$title', '$surname')"; mysql_select_db('dropbox'); $run_users_tb = mysql_query( $users_tb, $conn ); $run_users_info_tb = mysql_query( $users_info_tb, $conn ); if(!$run_users_tb || !$run_users_info_tb){ die('Could not enter data: ' . mysql_error()); } else{ echo "Entered data successfully\n"; } mysql_close($conn); } 

}

这是一种可以同时插入多个表的方法

 <?php require 'Connection.php'; $sql = "insert into `disease`(`diseasename`,`statusofgiving`) values('pentamina','no');"; $sql2 = "insert into `location`(`state`,`city`) values('pentamina','no');"; $res = mysqli_query($con,$sql); $res = mysqli_query($con,$sql2); ?> 

对于PDO你可以这样做

 $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); BEGIN; $sth1->execute (array ('test','test')); $sth2->execute (array ('Hello world!','http://www.stackoverflow.com')); COMMIT;