Mysql SQL查询本身工作,但在存储过程中与“on子句中的未知列”中断

Mysql SQL查询本身工作,但在存储过程中与“on子句中的未知列”中断,mysql,sql,Mysql,Sql,当我单独运行带有内部联接子查询的select查询时,它会工作,但在存储过程上下文中的“on子句”中会导致错误未知列“cities.state”。什么会导致正常工作的查询在存储过程中中断?为什么会为cities.state而不是cities.name返回此未知列错误?MySQL 5.7 CREATE DEFINER=`root`@`localhost` PROCEDURE `geogen`(IN State CHAR(2), CityMin INT(5), CityMax INT(6)) BEGI

当我单独运行带有内部联接子查询的select查询时,它会工作,但在存储过程上下文中的“on子句”中会导致错误未知列“cities.state”。什么会导致正常工作的查询在存储过程中中断?为什么会为cities.state而不是cities.name返回此未知列错误?MySQL 5.7

CREATE DEFINER=`root`@`localhost` PROCEDURE `geogen`(IN State CHAR(2), CityMin INT(5), CityMax INT(6))
BEGIN

#Create a temporary table to hold the final GeoArea product
DROP TABLE IF EXISTS `geodb`.`geoareas`;
CREATE TEMPORARY TABLE `geodb`.`geoareas` LIKE `geodb`.`geoareatemplate`;

INSERT INTO `geodb`.`geoareas` (`geoarea`, `zip`, `state`)
# Zip code sets of cities/towns with a population between CityMin and CityMax are their own GeoAreas.
SELECT CONCAT(`uszipcode`.`name`, ' ', `uszipcode`.`state`) as 'geoarea', `uszipcode`.`zip`, `uszipcode`.`state`
FROM `geodb`.`uszipcode`
INNER JOIN
(SELECT `name`, `state`, SUM(`population`) AS 'Population'
FROM `geodb`.`uszipcode`
WHERE `uszipcode`.`state` = State
GROUP BY `name`
HAVING (SUM(`population`) >= CityMin AND SUM(`population`) <= CityMax)) as `cities`
ON `uszipcode`.`name` = `cities`.`name`
AND `uszipcode`.`state` = `cities`.`state`
ORDER BY `uszipcode`.`name`, `uszipcode`.`zip`;

SELECT * FROM geodb.geoareas;
END
我得到了错误

0   76  13:10:22    CALL geogen('TX', 35000, 70000) Error Code: 1054. Unknown column 'cities.state' in 'on clause'  0.031 sec
但是,当我单独运行查询时,会返回结果

SELECT CONCAT(`uszipcode`.`name`, ' ', `uszipcode`.`state`) as 'geoarea', `uszipcode`.`zip`, `uszipcode`.`state`
FROM `geodb`.`uszipcode`
INNER JOIN
(SELECT `name`, `state`, SUM(`population`) AS 'Population'
FROM `geodb`.`uszipcode`
WHERE `uszipcode`.`state` = 'TX'
GROUP BY `name`
HAVING (SUM(`population`) >= 30000 AND SUM(`population`) <= 70000)) as `cities`
ON `uszipcode`.`name` = `cities`.`name`
AND `uszipcode`.`state` = `cities`.`state`
ORDER BY `uszipcode`.`name`, `uszipcode`.`zip`;
尝试按如下方式包装“选择项”:

INSERT INTO `geodb`.`geoareas` (`geoarea`, `zip`, `state`)
(SELECT CONCAT(`uszipcode`.`name`, ' ', `uszipcode`.`state`) as 'geoarea', `uszipcode`.`zip`, `uszipcode`.`state`
FROM `geodb`.`uszipcode`
INNER JOIN
(SELECT `name`, `state`, SUM(`population`) AS 'Population'
FROM `geodb`.`uszipcode`
WHERE `uszipcode`.`state` = State
GROUP BY `name`, `state`
HAVING (SUM(`population`) >= CityMin AND SUM(`population`) <= CityMax)) as `cities`
ON `uszipcode`.`name` = `cities`.`name`
AND `uszipcode`.`state` = `cities`.`state`
ORDER BY `uszipcode`.`name`, `uszipcode`.`zip`);
试试这个:

 DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `geogen`(IN State CHAR(2), CityMin INT(5), CityMax INT(6))
BEGIN

#temp cities
DROP TABLE IF EXISTS `geodb`.`cities_temp`;
CREATE TEMPORARY TABLE `geodb`.`cities_temp`
SELECT `name`, `state`, SUM(`population`) AS 'Population'
FROM `geodb`.`uszipcode`
WHERE `uszipcode`.`state` = State
GROUP BY `name`
HAVING (SUM(`population`) >= CityMin AND SUM(`population`) <= CityMax) ;
#Create a temporary table to hold the final GeoArea product
DROP TABLE IF EXISTS `geodb`.`geoareas`;
CREATE TEMPORARY TABLE `geodb`.`geoareas` LIKE `geodb`.`geoareatemplate`;

INSERT INTO `geodb`.`geoareas` (`geoarea`, `zip`, `state`)
# Zip code sets of cities/towns with a population between CityMin and CityMax are their own GeoAreas.
SELECT CONCAT(`uszipcode`.`name`, ' ', `uszipcode`.`state`) as 'geoarea', `uszipcode`.`zip`, `uszipcode`.`state`
FROM `geodb`.`uszipcode`
INNER JOIN
`geodb`.`cities_temp` as `cities`
ON `uszipcode`.`name` = `cities`.`name`
AND `uszipcode`.`state` = `cities`.`state`
ORDER BY `uszipcode`.`name`, `uszipcode`.`zip`;

SELECT * FROM geodb.geoareas;
END$$

DELIMITER ;

MySQL很混乱,因为名为State的参数/变量与cities.State的列名相似。我认为这是一个MySQL错误,因为我使用了反勾号,并通过在列前面加上表名来显式引用该列,但如果我错了,请纠正我,这是预期的行为。当我将State参数更新为VarState时,存储过程的结果与独立查询的结果相匹配,如下所示

CREATE DEFINER=`root`@`localhost` PROCEDURE `geogen`(IN VarState CHAR(2), CityMin INT(5), CityMax INT(6))
BEGIN

#Create a temporary table to hold the final GeoArea product
DROP TABLE IF EXISTS `geodb`.`geoareas`;
CREATE TEMPORARY TABLE `geodb`.`geoareas` LIKE `geodb`.`geoareatemplate`;

# Zip code sets of cities/towns with a population between CityMin and CityMax are their own GeoAreas.
INSERT INTO `geodb`.`geoareas` (`geoarea`, `zip`, `state`)
SELECT CONCAT(`uszipcode`.`name`, ' ', `uszipcode`.`state`) as 'geoarea', `uszipcode`.`zip`, `uszipcode`.`state`
FROM `geodb`.`uszipcode`
INNER JOIN
(SELECT `name`, `state`, SUM(`population`) AS 'Population'
FROM `geodb`.`uszipcode`
WHERE `uszipcode`.`state` = VarState
GROUP BY `name`
HAVING (SUM(`population`) >= CityMin AND SUM(`population`) <= CityMax)) AS `cities`
ON `uszipcode`.`name` = `cities`.`name`
AND `uszipcode`.`state` = `cities`.`state`
ORDER BY `uszipcode`.`name`, `uszipcode`.`zip`;

SELECT * FROM geodb.geoareas
ORDER BY `geoarea`, `zip`;
END

在运行Select语句时,如果不从存储过程中将其插入temp表中,是否可以得到结果?不幸的是,在修改存储过程以返回Select语句的结果时,我得到了相同的结果。这意味着您无法从存储过程访问临时表geodb.uszipcode。你能创建一个真正的表并使用它吗?geodb.uszipcode是一个真正的表。我正在创建的唯一临时表是geoareas,用于将结果放入其中。子查询有一个cities别名,问题似乎是它无法访问该别名的state列,但同一别名的name列没有问题,这很奇怪。是否可以按名称、状态将state添加到GROUP中,然后重试?按名称分组,具有sumpolution>=CityMin和sumpolution的州,将HAVING子句包装在parens中如何?e、 g.有总和。。。和'uszipcode`.'state`='cities`.'state`?HAVING子句已经被包装好了,除非我遗漏了什么,但是我添加了额外的参数,结果并没有改变。这似乎是一个建议,可以通过将内部联接子查询的结果插入到临时表中,并将其内部联接,而不是子查询,来解决我遇到的问题,这可能会起作用。除了创建临时表,我还可以去掉内部联接约束的AND部分,在第一个FROM之后添加另一个子查询,并使用where约束仅选择与状态变量匹配的记录。但我的原始存储过程的语法是否有任何问题,或者这是某种奇怪的MySQL错误?没错,测试添加分隔符。哦,我明白你的意思了。我确实更改了开头和结尾的分隔符,只是我发布的代码中没有。
 DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `geogen`(IN State CHAR(2), CityMin INT(5), CityMax INT(6))
BEGIN

#temp cities
DROP TABLE IF EXISTS `geodb`.`cities_temp`;
CREATE TEMPORARY TABLE `geodb`.`cities_temp`
SELECT `name`, `state`, SUM(`population`) AS 'Population'
FROM `geodb`.`uszipcode`
WHERE `uszipcode`.`state` = State
GROUP BY `name`
HAVING (SUM(`population`) >= CityMin AND SUM(`population`) <= CityMax) ;
#Create a temporary table to hold the final GeoArea product
DROP TABLE IF EXISTS `geodb`.`geoareas`;
CREATE TEMPORARY TABLE `geodb`.`geoareas` LIKE `geodb`.`geoareatemplate`;

INSERT INTO `geodb`.`geoareas` (`geoarea`, `zip`, `state`)
# Zip code sets of cities/towns with a population between CityMin and CityMax are their own GeoAreas.
SELECT CONCAT(`uszipcode`.`name`, ' ', `uszipcode`.`state`) as 'geoarea', `uszipcode`.`zip`, `uszipcode`.`state`
FROM `geodb`.`uszipcode`
INNER JOIN
`geodb`.`cities_temp` as `cities`
ON `uszipcode`.`name` = `cities`.`name`
AND `uszipcode`.`state` = `cities`.`state`
ORDER BY `uszipcode`.`name`, `uszipcode`.`zip`;

SELECT * FROM geodb.geoareas;
END$$

DELIMITER ;
CREATE DEFINER=`root`@`localhost` PROCEDURE `geogen`(IN VarState CHAR(2), CityMin INT(5), CityMax INT(6))
BEGIN

#Create a temporary table to hold the final GeoArea product
DROP TABLE IF EXISTS `geodb`.`geoareas`;
CREATE TEMPORARY TABLE `geodb`.`geoareas` LIKE `geodb`.`geoareatemplate`;

# Zip code sets of cities/towns with a population between CityMin and CityMax are their own GeoAreas.
INSERT INTO `geodb`.`geoareas` (`geoarea`, `zip`, `state`)
SELECT CONCAT(`uszipcode`.`name`, ' ', `uszipcode`.`state`) as 'geoarea', `uszipcode`.`zip`, `uszipcode`.`state`
FROM `geodb`.`uszipcode`
INNER JOIN
(SELECT `name`, `state`, SUM(`population`) AS 'Population'
FROM `geodb`.`uszipcode`
WHERE `uszipcode`.`state` = VarState
GROUP BY `name`
HAVING (SUM(`population`) >= CityMin AND SUM(`population`) <= CityMax)) AS `cities`
ON `uszipcode`.`name` = `cities`.`name`
AND `uszipcode`.`state` = `cities`.`state`
ORDER BY `uszipcode`.`name`, `uszipcode`.`zip`;

SELECT * FROM geodb.geoareas
ORDER BY `geoarea`, `zip`;
END