插入 n 行 LAST_INSERT_ID
Insert n rows with LAST_INSERT_ID
我有 3 个表,分别是 POSTS、HASHTAGS 和 POSTS_HASHTAGS_RELATION,如下。
CREATE TABLE POSTS(
post_id int unsigned NOT NULL AUTO_INCREMENT,
content varchar(200) NOT NULL,
PRIMARY KEY (post_id)
);
CREATE TABLE HASHTAGS(
hashtag_id int unsigned NOT NULL AUTO_INCREMENT,
hashtag varchar(40) NOT NULL,
PRIMARY KEY (hashtag_id)
);
CREATE TABLE POSTS_HASHTAGS_RELATION(
post_id int unsigned NOT NULL,
hashtag_id int unsigned NOT NULL,
PRIMARY KEY (post_id, hashtag_id)
);
当用户发帖时,他们 select 从保存在 HASHTAGS 中的标签中最多选择 20 个标签。我将这些主题标签的 hashtag_id(s) 作为逗号分隔的字符串从前端发送到后端,在那里它被转换为 nodejs 中的列表。
首先,有没有更好的方法来构建这个?
其次,如何在单个查询中向 POSTS_HASHTAGS_RELATION 插入可变数量的行?
INSERT INTO POSTS (content) VALUES ('bla bla bla bla');
SET @post_id = LAST_INSERT_ID();
INSERT INTO POSTS_HASHTAGS_RELATION (post_id, hashtag_id) VALUES (@post_id, 19), (@post_id, 41) ...;
// Something like this but the number of values can be between 1 and 20
如果之前有人回答过这个问题,请引导我找到那个答案。我找不到任何相关的东西。我认为这不是一个非常独特的问题。
你展示的就是我会做的方式。您可以按照显示的方式使用 INSERT 插入多行,方法是在 VALUES 关键字之后编写多行构造函数。如果这样做,则必须在每一行构造函数中为 INSERT 语句中命名的所有列包含一个值。因此,您必须在每一行构造函数中引用 @post_id
变量。
如果你真的不想多次写@post_id
,你可以这样做:
INSERT INTO POSTS_HASHTAGS_RELATION (post_id, hashtag_id)
SELECT @post_id, hashtag_id FROM (
SELECT 19 AS hashtag_id UNION SELECT 41 UNION SELECT 42 UNION ...
) AS t;
但这似乎 不如 清晰易读。
回复您的评论:
我不是 node.js 程序员,但我已经在其他语言中使用该技术来构建 SQL 语句,其中包含基于输入列表的多个行构造函数。正确的查询参数只能用于代替标量值,而不是列表或表达式或标识符或 SQL 关键字等。但我知道 node.js 有一些额外的 string-substitution 魔法,所以他们'没有真正做查询参数。
假设您刚刚将 INSERT 插入到 POSTS 中,您可以捕获最后的插入 ID:
var postId = result.insertId;
然后为您的下一个插入创建部分 INSERT 语句:
insert = 'INSERT INTO POSTS_HASHTAGS_RELATION (post_id, hashtag_id) VALUES';
您将需要一个用于行构造函数的数组和一个用于参数的数组:
let rowConstructors = [];
let parameters = [];
hashtags.forEach(function (hashtag) {
rowConstructors.push('(?, ?)');
parameters.concat(postId, hashtag);
});
现在你有一个行构造函数数组,toString()
将变成一个 comma-separated 字符串。你有一组值作为参数传递。
connection.query(insert + rowConstructors.toString(),
parameters, function (error, results, fields) {
if (error) throw error;
// ...
});
我想 .toString()
是可选的,因为应该通过将数组连接到 insert
字符串来自动将数组强制转换为字符串。
再次声明,我不是node.js程序员,如果有错误或风格问题请多多包涵。但这应该会让您了解这种技术。
将数据保存到 SP 格式的表中:
CREATE PROCEDURE save_post_and_tags (post_content VARCHAR(200), hashtag_ids TEXT)
BEGIN
DECLARE post_id INT UNSIGNED;
DECLARE tag_id INT UNSIGNED;
INSERT INTO posts VALUES (DEFAULT, post_content);
SET post_id := LAST_INSERT_ID();
SET hashtag_ids := concat(hashtag_ids, ',');
REPEAT
SET tag_id := 0 + SUBSTRING_INDEX(hashtag_ids, ',', 1);
SET hashtag_ids := TRIM(SUBSTRING(hashtag_ids FROM 1 + LOCATE(',', hashtag_ids)));
INSERT INTO posts_hashtags_relation VALUES (post_id, tag_id);
UNTIL hashtag_ids = '' END REPEAT;
END
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=a9c622ea7ad2dd48dba18312c7a33487(故意使用草率的 CSV)。
我有 3 个表,分别是 POSTS、HASHTAGS 和 POSTS_HASHTAGS_RELATION,如下。
CREATE TABLE POSTS(
post_id int unsigned NOT NULL AUTO_INCREMENT,
content varchar(200) NOT NULL,
PRIMARY KEY (post_id)
);
CREATE TABLE HASHTAGS(
hashtag_id int unsigned NOT NULL AUTO_INCREMENT,
hashtag varchar(40) NOT NULL,
PRIMARY KEY (hashtag_id)
);
CREATE TABLE POSTS_HASHTAGS_RELATION(
post_id int unsigned NOT NULL,
hashtag_id int unsigned NOT NULL,
PRIMARY KEY (post_id, hashtag_id)
);
当用户发帖时,他们 select 从保存在 HASHTAGS 中的标签中最多选择 20 个标签。我将这些主题标签的 hashtag_id(s) 作为逗号分隔的字符串从前端发送到后端,在那里它被转换为 nodejs 中的列表。
首先,有没有更好的方法来构建这个?
其次,如何在单个查询中向 POSTS_HASHTAGS_RELATION 插入可变数量的行?
INSERT INTO POSTS (content) VALUES ('bla bla bla bla');
SET @post_id = LAST_INSERT_ID();
INSERT INTO POSTS_HASHTAGS_RELATION (post_id, hashtag_id) VALUES (@post_id, 19), (@post_id, 41) ...;
// Something like this but the number of values can be between 1 and 20
如果之前有人回答过这个问题,请引导我找到那个答案。我找不到任何相关的东西。我认为这不是一个非常独特的问题。
你展示的就是我会做的方式。您可以按照显示的方式使用 INSERT 插入多行,方法是在 VALUES 关键字之后编写多行构造函数。如果这样做,则必须在每一行构造函数中为 INSERT 语句中命名的所有列包含一个值。因此,您必须在每一行构造函数中引用 @post_id
变量。
如果你真的不想多次写@post_id
,你可以这样做:
INSERT INTO POSTS_HASHTAGS_RELATION (post_id, hashtag_id)
SELECT @post_id, hashtag_id FROM (
SELECT 19 AS hashtag_id UNION SELECT 41 UNION SELECT 42 UNION ...
) AS t;
但这似乎 不如 清晰易读。
回复您的评论:
我不是 node.js 程序员,但我已经在其他语言中使用该技术来构建 SQL 语句,其中包含基于输入列表的多个行构造函数。正确的查询参数只能用于代替标量值,而不是列表或表达式或标识符或 SQL 关键字等。但我知道 node.js 有一些额外的 string-substitution 魔法,所以他们'没有真正做查询参数。
假设您刚刚将 INSERT 插入到 POSTS 中,您可以捕获最后的插入 ID:
var postId = result.insertId;
然后为您的下一个插入创建部分 INSERT 语句:
insert = 'INSERT INTO POSTS_HASHTAGS_RELATION (post_id, hashtag_id) VALUES';
您将需要一个用于行构造函数的数组和一个用于参数的数组:
let rowConstructors = [];
let parameters = [];
hashtags.forEach(function (hashtag) {
rowConstructors.push('(?, ?)');
parameters.concat(postId, hashtag);
});
现在你有一个行构造函数数组,toString()
将变成一个 comma-separated 字符串。你有一组值作为参数传递。
connection.query(insert + rowConstructors.toString(),
parameters, function (error, results, fields) {
if (error) throw error;
// ...
});
我想 .toString()
是可选的,因为应该通过将数组连接到 insert
字符串来自动将数组强制转换为字符串。
再次声明,我不是node.js程序员,如果有错误或风格问题请多多包涵。但这应该会让您了解这种技术。
将数据保存到 SP 格式的表中:
CREATE PROCEDURE save_post_and_tags (post_content VARCHAR(200), hashtag_ids TEXT)
BEGIN
DECLARE post_id INT UNSIGNED;
DECLARE tag_id INT UNSIGNED;
INSERT INTO posts VALUES (DEFAULT, post_content);
SET post_id := LAST_INSERT_ID();
SET hashtag_ids := concat(hashtag_ids, ',');
REPEAT
SET tag_id := 0 + SUBSTRING_INDEX(hashtag_ids, ',', 1);
SET hashtag_ids := TRIM(SUBSTRING(hashtag_ids FROM 1 + LOCATE(',', hashtag_ids)));
INSERT INTO posts_hashtags_relation VALUES (post_id, tag_id);
UNTIL hashtag_ids = '' END REPEAT;
END
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=a9c622ea7ad2dd48dba18312c7a33487(故意使用草率的 CSV)。