MySQL Insert into multiple tables? (Database normalization?)

前端 未结 8 2254
庸人自扰
庸人自扰 2020-11-22 01:56

I tried searching a way to insert information in multiple tables in the same query, but found out it\'s impossible? So I want to insert it by simpl

相关标签:
8条回答
  • 2020-11-22 02:12

    Just a remark about your saying

    Hi, I tried searching a way to insert information in multiple tables in the same query

    Do you eat all your lunch dishes mixed with drinks in the same bowl?
    I suppose - no.

    Same here.
    There are things we do separately.
    2 insert queries are 2 insert queries. It's all right. Nothing wrong with it. No need to mash it in one.
    Same for select. Query must be sensible and do it's job. That's the only reasons. Number of queries is not.

    As for the transactions - you may use them, but it's not THAT big deal for the average web-site. If it happened once a year (if ever) that one user registration being broken you'll be able to fix, no doubt.
    there are hundreds of thousands sites running mysql with no transaction support driver. Have you heard of terrible disasters breaking these sites apart? Me neither.

    And mysql_insert_id() has noting to do with transactions. you may include in into transaction all right. it's just different matters. Someone raised this question out of nowhere.

    0 讨论(0)
  • 2020-11-22 02:18

    What would happen, if you want to create many such records ones (to register 10 users, not just one)? I find the following solution (just 5 queryes):

    Step I: Create temporary table to store new data.

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

    Next, fill this table with values.

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

    Here, instead of $ALL_VAL you place list of values: ('test1','test1','bio1','home1'),...,('testn','testn','bion','homen')

    Step II: Send data to 'user' table.

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

    Here, "IGNORE" can be used, if you allow some users already to be inside. Optionaly you can use UPDATE similar to step III, before this step, to find whom users are already inside (and mark them in tmp table). Here we suppouse, that username is declared as PRIMARY in users table.

    Step III: Apply update to read all users id from users to tmp table. THIS IS ESSENTIAL STEP.

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

    Step IV: Create another table, useing read id for users

    INSERT INTO profiles (userid, bio, homepage) 
    SELECT id, bio, homepage FROM tmp
    
    0 讨论(0)
  • 2020-11-22 02:19

    try this

    $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);
    };
    

    References
    PHP
    MYSQL

    0 讨论(0)
  • 2020-11-22 02:21

    This is the way that I did it for a uni project, works fine, prob not safe tho

    $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);
    }
    

    }

    0 讨论(0)
  • 2020-11-22 02:25

    For PDO You may do this

    $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;
    
    0 讨论(0)
  • 2020-11-22 02:28

    No, you can't insert into multiple tables in one MySQL command. You can however use transactions.

    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;
    

    Have a look at LAST_INSERT_ID() to reuse autoincrement values.

    Edit: you said "After all this time trying to figure it out, it still doesn't work. Can't I simply put the just generated ID in a $var and put that $var in all the MySQL commands?"

    Let me elaborate: there are 3 possible ways here:

    1. In the code you see above. This does it all in MySQL, and the LAST_INSERT_ID() in the second statement will automatically be the value of the autoincrement-column that was inserted in the first statement.

      Unfortunately, when the second statement itself inserts rows in a table with an auto-increment column, the LAST_INSERT_ID() will be updated to that of table 2, and not table 1. If you still need that of table 1 afterwards, we will have to store it in a variable. This leads us to ways 2 and 3:

    2. Will stock the LAST_INSERT_ID() in a MySQL variable:

      INSERT ...
      SELECT LAST_INSERT_ID() INTO @mysql_variable_here;
      INSERT INTO table2 (@mysql_variable_here, ...);
      INSERT INTO table3 (@mysql_variable_here, ...);
      
    3. Will stock the LAST_INSERT_ID() in a php variable (or any language that can connect to a database, of your choice):

      • INSERT ...
      • Use your language to retrieve the LAST_INSERT_ID(), either by executing that literal statement in MySQL, or using for example php's mysql_insert_id() which does that for you
      • INSERT [use your php variable here]

    WARNING

    Whatever way of solving this you choose, you must decide what should happen should the execution be interrupted between queries (for example, your database-server crashes). If you can live with "some have finished, others not", don't read on.

    If however you decide "either all queries finish, or none finish - I do not want rows in some tables but no matching rows in others, I always want my database tables to be consistent", you need to wrap all statements in a transaction. That's why I used the BEGIN and COMMIT here.

    Comment again if you need more info :)

    0 讨论(0)
提交回复
热议问题