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

时间:2011-03-03 09:15:27

标签: 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')

但是如何为id表格的users自动增加userid到“{1}}手册”?

8 个答案:

答案 0 :(得分:212)

不,您无法在一个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命令?

让我详细说明:这里有3种可能的方式:

  1. 在上面的代码中。这个 在MySQL,以及 第二个LAST_INSERT_ID() 声明将自动成为 autoincrement-column的值 插入第一个 言。

    不幸的是,当第二个语句本身在带有自动增量列的表中插入行时,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. LAST_INSERT_ID()存入a php变量(或任何语言 可以连接到您的数据库 选择):

    • INSERT ...
    • 使用您的语言检索LAST_INSERT_ID(),或者通过在MySQL中执行该文字语句,或者使用例如为您执行此操作的php mysql_insert_id()
    • INSERT [use your php variable here]
  4. 警告

    无论您选择哪种解决方案,都必须决定应该发生什么如果查询之间的执行中断(例如,您的数据库服务器崩溃)。如果你可以忍受“有些已经完成,有些则没有”,请不要继续阅读。

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

    如果您需要更多信息,请再次评论:)

答案 1 :(得分:16)

如果你使用存储过程,那么

非常简单:

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 :(得分:4)

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

第一步:创建临时表以存储新数据。

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','生物个体”, 'homen')

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

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

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

第三步:应用更新以读取用户对tmp表的所有用户ID。 这是必要的步骤。

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

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

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

答案 3 :(得分:3)

试试这个

$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

答案 4 :(得分:2)

看看mysql_insert_id()

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

答案 5 :(得分:0)

这就是我为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);
}

}

答案 6 :(得分:-1)

关于你的说法的评论

  

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

你是否在同一个碗里吃了所有的混合饮料的午餐菜肴? 我想 - 不。

同样在这里 我们分开做的事情 2个插入查询是2个插入查询。没关系。它没有错。无需将其混合在一起。
选择相同。查询必须是明智的并且做它的工作。这是唯一的原因。查询数量不是。

至于交易 - 您可以使用它们,但这对普通网站来说并不重要。如果它每年发生一次(如果有的话),一个用户注册被破坏,你将能够解决,毫无疑问 有数十万个运行mysql但没有事务支持驱动程序的站点。您是否听说过可怕的灾难将这些网站分开?我也不是。

mysql_insert_id()与事务有关。您可以在交易中包含所有权利。这只是不同的事情。有人提出这个问题。

答案 7 :(得分:-2)

对于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;