MYSQL - 在 INSERT 语句中使用函数
MYSQL - using Functions inside a INSERT statement
我正在将数据从电子表格移动到 MySQL。
所以我们知道在电子表格中通常没有ID,而只有文本。
City;Country;...
New York;USA;...
Berlim;Germany;...
Munich,Germany,...
考虑到这一点,让我们考虑两个表:
国家:[身份证,姓名]
城市:[ID,国家(FK),姓名]
我不想创建多个同名的国家 -- 但我想使用现有的国家。完美,所以,让我们在 INSERT 状态下添加一个 FUNCTION,用于搜索、插入(如果需要)和 return 国家 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'));
Function单独执行时效果很好,比如
SELECT getCountry('Aruba');
但是,当我执行那个非常长 SQL(22K+ 行)时,它不起作用....它基本上使用在开始执行之前创建的最新 ID。也许我应该 "wait" 函数执行并 return 一个正确的结果?但是怎么办?
我做错了什么?
我找不到它的任何文档,但是当您在另一个 INSERT
期间调用的函数中执行 INSERT
时,可能会发生冲突。所以尝试使用变量将它们分开:
SELECT @country := getCountry('new or existing one');
INSERT INTO city (name, country) VALUES ('name of the city', @country);
使用@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 不再计算变量,相反,只是抛出它收集的一些最后结果。
为什么不使用存储过程而不是函数,那么该过程将处理检查和插入。
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');
您还可以添加一个条件来检查城市和国家是否存在,以防止重复输入。
我正在将数据从电子表格移动到 MySQL。 所以我们知道在电子表格中通常没有ID,而只有文本。
City;Country;...
New York;USA;...
Berlim;Germany;...
Munich,Germany,...
考虑到这一点,让我们考虑两个表:
国家:[身份证,姓名]
城市:[ID,国家(FK),姓名]
我不想创建多个同名的国家 -- 但我想使用现有的国家。完美,所以,让我们在 INSERT 状态下添加一个 FUNCTION,用于搜索、插入(如果需要)和 return 国家 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'));
Function单独执行时效果很好,比如
SELECT getCountry('Aruba');
但是,当我执行那个非常长 SQL(22K+ 行)时,它不起作用....它基本上使用在开始执行之前创建的最新 ID。也许我应该 "wait" 函数执行并 return 一个正确的结果?但是怎么办?
我做错了什么?
我找不到它的任何文档,但是当您在另一个 INSERT
期间调用的函数中执行 INSERT
时,可能会发生冲突。所以尝试使用变量将它们分开:
SELECT @country := getCountry('new or existing one');
INSERT INTO city (name, country) VALUES ('name of the city', @country);
使用@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 不再计算变量,相反,只是抛出它收集的一些最后结果。
为什么不使用存储过程而不是函数,那么该过程将处理检查和插入。
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');
您还可以添加一个条件来检查城市和国家是否存在,以防止重复输入。