我尝试在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')
Run Code Online (Sandbox Code Playgroud)
但我怎么可以给自动增量id从users"手动" userid为profile表?
Kon*_*rak 222
不,您不能在一个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;
Run Code Online (Sandbox Code Playgroud)
看看LAST_INSERT_ID()重用自动增量值.
让我详细说明:这里有3种可能的方法:
在上面的代码中.这在MySQL中完成所有操作,
LAST_INSERT_ID()第二个语句中的所有内容将自动成为第一个语句中插入的autoincrement-column的值.
不幸的是,当第二个语句本身在带有自动增量列的表中插入行时,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, ...);
Run Code Online (Sandbox Code Playgroud)将存储LAST_INSERT_ID()在php变量(或任何可以连接到您选择的数据库的语言):
INSERT ...LAST_INSERT_ID(),或者通过在MySQL中执行该文字语句,或者使用例如mysql_insert_id()为您执行此操作的phpINSERT [use your php variable here]无论您选择哪种解决方案,都必须决定在查询之间执行中断应该发生什么(例如,数据库服务器崩溃).如果你可以忍受"有些已经完成,有些则没有",请不要继续阅读.
但是,如果您决定"要么所有查询都完成,要么没有完成 - 我不希望某些表中的行但其他表中没有匹配的行,我总是希望我的数据库表保持一致",您需要将所有语句包装在事务中.这就是为什么我用了BEGIN和COMMIT这里.
如果您需要更多信息,请再次评论:)
Jon*_*ack 16
如果你使用存储过程相当简单:
call insert_user_and_profile('f00','http://www.f00.com');
Run Code Online (Sandbox Code Playgroud)
完整脚本:
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;
Run Code Online (Sandbox Code Playgroud)
小智 7
如果您想创建许多这样的记录(注册 10 个用户,而不仅仅是一个),会发生什么?我找到了以下解决方案(只有 5 个查询):
第一步:创建临时表来存储新数据。
CREATE TEMPORARY TABLE tmp (id bigint(20) NOT NULL, ...)...;
Run Code Online (Sandbox Code Playgroud)
接下来,用值填充此表。
INSERT INTO tmp (username, password, bio, homepage) VALUES $ALL_VAL
Run Code Online (Sandbox Code Playgroud)
在这里,而不是$ALL_VAL放置值列表:('test1','test1','bio1','home1'),...,('testn','testn','bion','homen')
第二步:将数据发送到'user'表。
INSERT IGNORE INTO users (username, password)
SELECT username, password FROM tmp;
Run Code Online (Sandbox Code Playgroud)
在这里,可以使用“忽略”,如果您允许一些用户已经在里面。可选地,您可以在此步骤之前使用类似于步骤 III 的 UPDATE 来查找已在其中的用户(并在 tmp 表中标记它们)。这里我们假设,用户名PRIMARY在 users 表中声明。
第三步:应用更新从用户中读取所有用户 id 到 tmp 表。这是必不可少的步骤。
UPDATE tmp JOIN users ON tmp.username=users.username SET tmp.id=users.id
Run Code Online (Sandbox Code Playgroud)
第四步:创建另一个表,为用户使用读取ID
INSERT INTO profiles (userid, bio, homepage)
SELECT id, bio, homepage FROM tmp
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
269140 次 |
| 最近记录: |