MySQL Вставка в несколько таблиц? (Нормализация базы данных?)

Я пробовал искать способ вставки информации в несколько таблиц в том же запросе, но выяснил, что это невозможно? Поэтому я хочу вставить его, просто используя mutliple queries i.e;

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

Но как я могу дать идентификатор автоинкремента от пользователя к "ручному" идентификатору пользователя для таблицы профилей?

Ответ 1

Нет, вы не можете вставлять несколько таблиц в одну команду 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(), чтобы повторно использовать значения автоинкремента.

Edit: вы сказали: "После всего этого времени, пытаясь понять это, он все равно не работает. Не могу ли я просто поместить только сгенерированный идентификатор в $var и поместить этот $var во все команды MySQL?"

Позвольте мне уточнить: здесь есть три возможных способа:

  • В коде, который вы видите выше. Эта делает все это в MySQL, а LAST_INSERT_ID() во втором утверждение будет автоматически значение автоинкрементной колонки который был вставлен в первый утверждение.

    К сожалению, когда второй оператор сам вставляет строки в таблицу с столбцом с автоматическим приращением, LAST_INSERT_ID() будет обновляться до значения, указанного в таблице 2, а не таблицы 1. Если вам по-прежнему понадобится таблица 1 после этого, мы должны будем хранить его в переменной. Это приводит нас к путям 2 и 3:

  • Будет запасать 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, ...);
    
  • Будет запасать LAST_INSERT_ID() в php (или любой язык, который может подключаться к базе данных, вашей выбор):

    • INSERT ...
    • Используйте свой язык для извлечения LAST_INSERT_ID(), выполнив этот оператор literal в MySQL или используя, например, php mysql_insert_id(), который делает это для вас
    • INSERT [use your php variable here]

ПРЕДУПРЕЖДЕНИЕ

Каким бы способом вы это ни выбрали, вы должны решить, что должно произойти , если выполнение прерывается между запросами (например, сбой вашего сервера базы данных). Если вы можете жить с "некоторые закончили, другие нет", не читайте дальше.

Если вы решите, что "либо все запросы заканчиваются, либо не завершены, я не хочу, чтобы строки в некоторых таблицах, но не соответствующие строки в других, я всегда хочу, чтобы мои таблицы базы данных были согласованными", вам нужно обернуть все утверждения в транзакции. Вот почему я использовал BEGIN и COMMIT здесь.

Комментарий снова, если вам нужна дополнительная информация:)

Ответ 2

довольно просто, если вы используете хранимые процедуры:

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

полный script:

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;

Ответ 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

Ответ 5

Что произойдет, если вы хотите создать много таких записей (зарегистрировать 10 пользователей, а не только один)? Я нахожу следующее решение (всего 5 запросов):

Шаг I: Создайте временную таблицу для хранения новых данных.

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

Шаг II: Отправляйте данные в таблицу пользователя.

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

Здесь может использоваться "IGNORE", если вы разрешите некоторым пользователям уже находиться внутри. Необязательно вы можете использовать UPDATE, аналогичный шагу III, перед этим шагом, чтобы найти пользователей, которые уже находятся внутри (и пометить их в таблице tmp). Здесь мы подтверждаем, что имя пользователя объявляется как PRIMARY в таблице users.

Шаг III: Применить обновление, чтобы прочитать идентификатор всех пользователей от пользователей в таблице tmp. ЭТО ЭЗОТИЧЕСКИЙ ШАГ.

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

Шаг IV: Создайте другую таблицу, используя идентификатор чтения для пользователей

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

Ответ 6

Просто замечание о твоем высказывании

Привет, я попытался найти способ вставки информации в несколько таблиц в том же запросе

Вы едите все обеденные блюда, смешанные с напитками в одной чаше?

Я полагаю - нет.

То же самое здесь. Есть вещи, которые мы делаем отдельно.
2 вставки запросов - 2 запроса вставки. Все в порядке. Ничего плохого в этом нет. Не нужно затормозить его в одном.
То же самое для выбора. Запрос должен быть разумным и выполнять эту работу. Это единственные причины. Количество запросов отсутствует.

Что касается транзакций - вы можете их использовать, но это не так важно для среднего веб-сайта. Если это случается раз в год (если когда-либо), что одна регистрация пользователя нарушается, вы можете исправить, без сомнения.
существуют сотни тысяч сайтов, на которых запущена mysql, без драйверов поддержки транзакций. Слышали ли вы о страшных катастрофах, разрушающих эти сайты? Я тоже.

И mysql_insert_id() имеет отношение к транзакциям. вы можете включить в транзакцию все в порядке. это просто разные вопросы. Кто-то поднял этот вопрос из ниоткуда.

Ответ 7

Так я сделал это для проекта uni, отлично работает, не безопасно 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);
}

}

Ответ 8

это способ, которым вы можете вставлять одновременно несколько таблиц

<?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);


?>

Ответ 9

Для 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;