MYSQL - 在 INSERT 语句中使用函数

Posted

技术标签:

【中文标题】MYSQL - 在 INSERT 语句中使用函数【英文标题】:MYSQL - using Functions inside a INSERT statement 【发布时间】:2020-03-23 21:38:48 【问题描述】:

我正在将数据从电子表格移动到 mysql。 所以我们知道,在电子表格中通常没有 ID,只有文本。

City;Country;...
New York;USA;...
Berlim;Germany;...
Munich,Germany,...

考虑到这一点,让我们考虑两个表:

国家:[ID,姓名]

城市 : [ID , 国家 (FK) , 名称]

我不想创建多个具有相同名称的国家/地区,但我想使用现有的国家/地区。完美,所以,让我们在 INSERT 状态下添加一个 FUNCTION,用于搜索、插入(如果需要)并返回 Country ID。

所以我创建了一个函数来FIRST评估国家是否存在如果不存在则创建一个国家

getCountry (parameter IN strCountry varchar(100))
BEGIN
SELECT ID INTO @id from `country` WHERE country.country = strCountry ;
IF (@id is NULL OR @id= 0) THEN
    INSERT INTO `country` (country) VALUES (strCountry);
    if (ROW_COUNT()>0) THEN
        SET @id = LAST_INSERT_ID();
    else
        SET @id = NULL;
    END IF;
END IF ;
RETURN @id;
END

然后我有数十万个插入,例如

INSERT INTO city (name, country) VALUES ('name of the city', getCountry('new or existing one'));

函数单独执行时效果很好,比如

SELECT getCountry('Aruba');

但是,当我在那个非常长的 SQL(22K+ 行)中执行它时,它不起作用....它基本上使用在开始执行之前创建的最新 ID。也许我应该“等待”函数执行并返回正确的结果?但是怎么做?

我做错了什么?

【问题讨论】:

你说的是VALUES ('city1', getCountry('country1')), ('city2', getCountry('country2')), ...吗? 几乎,电子表格只允许每行创建一个 插入城市值 ('city1', getCountry('country1'));插入城市值 ('city2', getCountry('country1')); INSERT into City VALUES ('city3', getCountry('country1')); 嗨 @Barmar .. 在 INSERT 语句中使用该函数“编译”虽然它没有给我想要的正确 ID 【参考方案1】:

为什么不使用存储过程而不是函数,那么该过程将处理检查和插入。

https://www.mysqltutorial.org/getting-started-with-mysql-stored-procedures.aspx

DELIMITER $$
CREATE PROCEDURE `sp_city_add`(in p_city varchar(100), in p_country varchar(100))
BEGIN

DECLARE country_id INT;

IF (SELECT COUNT(1) FROM country WHERE country.country = p_country) = 0 THEN
    INSERT INTO country (country) VALUE (p_country);

    SET country_id = LAST_INSERT_ID();
ELSE
    SELECT ID INTO country_id FROM country WHERE country.country = p_country;
END IF;

INSERT INTO city (name, country) VALUES (p_city, country_id);

END$$
DELIMITER ;

如果你想执行一个过程

CALL sp_city_add('Bogota', 'Colombia');
CALL sp_city_add('Phnom Penh', 'Cambodia');
CALL sp_city_add('Yaounde', 'Cameroon');
CALL sp_city_add('Ottawa', 'Canada');
CALL sp_city_add('Santiago', 'Chile');
CALL sp_city_add('Beijing', 'China');
CALL sp_city_add('Bogotá', 'Colombia');
CALL sp_city_add('Moroni', 'Comoros');

您也可以添加条件来检查城市和国家是否存在,以防止重复输入。

【讨论】:

【参考方案2】:

我找不到它的任何文档,但是当您在另一个 INSERT 期间调用的函数中执行 INSERT 时可能会发生冲突。所以尝试使用变量将它们分开:

SELECT @country := getCountry('new or existing one');
INSERT INTO city (name, country) VALUES ('name of the city', @country);

【讨论】:

我应该对 script.sql 中的每一行都这样做吗?有更好的方法吗? ['sql']SELECT @country := getCountry('Germany');INSERT INTO city (name, country) VALUES ('Berlin', @country); SELECT @country := getCountry('Germany');INSERT INTO city (name, country) VALUES ('Munich', @country); SELECT @country := getCountry('Germany');INSERT INTO city (name, country) VALUES ('Passau', @country); SELECT @country := getCountry('Brazil');INSERT INTO city (name, country) VALUES ('Sao Paulo', @country);['sql'] 是的,每个插入都需要分成两部分。 虽然如果您按国家/地区对它们进行分组,您可以只执行一次getCountry() 谢谢@Barmar,我们试试 不幸的是它没有正常工作,@Barmar:看看link 我分享脚本的地方和我得到的结果【参考方案3】:

使用@Barman 的想法,加上将 COMMIT 添加到每一行我可以解决这个问题:

SELECT @id := getCountry("Colombia");INSERT into city ( city, country) VALUES ('Bogota',@id);COMMIT;
SELECT @id := getCountry("Colombia");INSERT into city ( city, country) VALUES ('Medelin',@id);COMMIT;
SELECT @id := getCountry("Brazil");INSERT into city ( city, country) VALUES ('Medelin',@id);COMMIT;
SELECT @id := getCountry("Brazil");INSERT into city ( city, country) VALUES ('Sao Paulo',@id);COMMIT;
SELECT @id := getCountry("Brazil");INSERT into city ( city, country) VALUES ('Curitiba',@id);COMMIT;
SELECT @id := getCountry("USA");INSERT into city ( city, country) VALUES ('Boston',@id);COMMIT;
SELECT @id := getCountry("USA");INSERT into city ( city, country) VALUES ('DallaS',@id);COMMIT;

没有在每一行末尾的 COMMIT,MySQL 不再计算变量,而是抛出它收集的最后一个结果。

【讨论】:

以上是关于MYSQL - 在 INSERT 语句中使用函数的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL批量插入语句怎么写

mysql的执行insert是不是有返回值

MYSQL 数据库基本操作

MySQL实战中的Insert语句的使用心得

如何在MySQL中的INSERT语句中使用SELECT MAX?

如何使用mysql语句向表中插入数据