简体   繁体   English

MY SQL重播错误1241中的存储过程IF语句

[英]Stored Procedure IF statement in MY SQL returing error 1241

I am writing this code in MYSQL workbench to check for the data in several tables in order to enter a customer and various customer details in multiple tables without duplication and to gather the primary key for the variable from each table before moving onto the next one. 我正在MYSQL工作台中编写此代码,以检查多个表中的数据,以便在不重复的情况下在多个表中输入客户和各种客户详细信息,并在移至下一个表之前从每个表收集变量的主键。 I used the same IF ELSE syntax for an INSERT Statement that worked flawlessly but it is failing with the addition of the SELECT statement in the beginning to check for the customerID in a view and the UPDATE statement at the end instead of INSERTS only. 我对INSERT语句使用了相同的IF ELSE语法,该语法可以完美地工作,但是由于在开头添加了SELECT语句以检查视图中的customerID并在末尾检查UPDATE语句而不是仅插入语句而失败。

It's failing with error 1241 Operand should contain 1 column(s) 失败并出现错误1241操作数应包含1列

I tried to find the answer to this and found lots of questions about this error but none pertaining to this syntax. 我试图找到答案,但发现了许多有关此错误的问题,但都没有与此语法有关的问题。

Can anyone help? 有人可以帮忙吗? Code is below 代码如下

CREATE DEFINER=`U03qew`@`%` PROCEDURE `sp_modify_customer`(IN CUST_ID INT(11), IN CUST_COUNTRY VARCHAR(50), 
IN CUST_NAME VARCHAR(45), IN CUST_ADDRESS VARCHAR(50), IN CUST_ADDRESS2 VARCHAR(50), IN CUST_CITY VARCHAR(50), 
IN CUST_ZIP VARCHAR(10), IN CUST_PHONE VARCHAR(20), IN CUR_USER VARCHAR(50))
BEGIN
DECLARE ccountryId VARCHAR(50);
DECLARE ccityId VARCHAR(50);
DECLARE caddressId VARCHAR(50);
IF (SELECT * FROM customer WHERE customerId = CUST_ID) IS NOT NULL THEN
BEGIN
IF (SELECT countryId FROM country WHERE country = CUST_COUNTRY) IS NOT NULL THEN
BEGIN
SELECT countryId FROM country WHERE country = CUST_COUNTRY
INTO ccountryId;
END;
ELSE BEGIN
INSERT INTO country (country, createDate, createdBy, lastUpdate, lastUpdateBy)
VALUES (CUST_COUNTRY, current_date(), CUR_USER, current_timestamp(), CUR_USER);
SELECT countryId FROM country WHERE country = CUST_COUNTRY
INTO ccountryId;
END;
END IF;
IF (SELECT cityId FROM city WHERE city = CUST_CITY AND countryId = ccountryId) IS NOT NULL THEN
BEGIN
SELECT cityId FROM city WHERE city = CUST_CITY AND countryId = ccountryId
INTO ccityId;
END;
ELSE BEGIN
INSERT INTO city (city, countryId, createDate, createdBy, lastUpdate, lastUpdateBy)
VALUES (CUST_CITY, ccountryId, current_date(), CUR_USER, current_timestamp(), CUR_USER);
SELECT cityId FROM city WHERE city = CUST_CITY AND countryId = ccountryId
INTO ccityId;
END;
END IF;
IF (SELECT addressId FROM address WHERE address = CUST_ADDRESS AND address2 = CUST_ADDRESS2 AND phone = CUST_PHONE AND cityId = ccityId) IS NOT NULL THEN
BEGIN
SELECT addressID FROM address WHERE address = CUST_ADDRESS AND address2 = CUST_ADDRESS2 AND phone = CUST_PHONE AND cityId = ccityID 
INTO caddressId;
END;
ELSE BEGIN
INSERT INTO address (address, address2, cityId, postalCode, phone, createDate, createdBy, lastUpdate, lastUpdateby)
VALUES (CUST_ADDRESS, CUST_ADDRESS2, ccityId, CUST_ZIP, CUST_PHONE, current_date(), CUR_USER, current_timestamp(), CUR_USER);
SELECT addressId FROM address WHERE address = CUST_ADDRESS AND address2 = CUST_ADDRESS2 AND phone = CUST_PHONE AND cityId = ccityID 
INTO caddressId;
END;
END IF;
UPDATE customer 
SET customerName = CUST_NAME, addressId = caddressId, active = 1, lastupdate = current_timestamp(), lastUpdateBy = CUR_USER
WHERE customerId = CUST_ID;
END;
ELSE BEGIN
SELECT * FROM customer WHERE customerId = CUST_ID;
END;
END IF;
END
IF (SELECT cityId FROM city WHERE city = CUST_CITY AND countryId = ccountryId) IS NOT NULL THEN 
BEGIN SELECT cityId FROM city WHERE city = CUST_CITY AND countryId = ccountryId INTO ccityId; 
END; 
ELSE BEGIN INSERT INTO city (city, countryId, createDate, createdBy, lastUpdate, lastUpdateBy) 
VALUES (CUST_CITY, ccountryId, current_date(), CUR_USER, current_timestamp(), CUR_USER); 
SELECT cityId FROM city WHERE city = CUST_CITY AND countryId = ccountryId INTO ccityId; 
END; 
END IF; 
IF (SELECT addressId FROM address WHERE address = CUST_ADDRESS AND address2 = CUST_ADDRESS2 AND phone = CUST_PHONE AND cityId = ccityId) IS NOT NULL THEN 
BEGIN SELECT addressID FROM address WHERE address = CUST_ADDRESS AND address2 = CUST_ADDRESS2 AND phone = CUST_PHONE AND cityId = ccityID INTO caddressId; 
END; 
ELSE 
BEGIN INSERT INTO address (address, address2, cityId, postalCode, phone, createDate, createdBy, lastUpdate, lastUpdateby) 
VALUES (CUST_ADDRESS, CUST_ADDRESS2, ccityId, CUST_ZIP, CUST_PHONE, current_date(), CUR_USER, current_timestamp(), CUR_USER); 
SELECT addressId FROM address WHERE address = CUST_ADDRESS AND address2 = CUST_ADDRESS2 AND phone = CUST_PHONE AND cityId = ccityID INTO caddressId; 
END; 
END IF; 
UPDATE customer 
SET customerName = CUST_NAME, addressId = caddressId, active = 1, lastupdate = current_timestamp(), lastUpdateBy = CUR_USER WHERE customerId = CUST_ID; 
END; 
ELSE 
BEGIN 
SELECT * FROM customer WHERE customerId = CUST_ID; 
END; 
END IF; 
END

To address your error, you should understand that when you use a subquery and compare the result to a single value, the subquery must return a scalar. 要解决您的错误,您应该理解,当您使用子查询并将结果与​​单个值进行比较时,子查询必须返回标量。

The mistake is here: 错误在这里:

IF (SELECT * FROM customer WHERE customerId = CUST_ID) IS NOT NULL THEN

How can SELECT * , which I assume returns multiple columns, be in an `IS NOT NULL expression? 我假设SELECT *可以返回多列,如何在IS IS NULL表达式中? Which of the many columns is tested for null? 测试了多少列中的哪一列为null?

SQL does support tuple comparisons like this: SQL确实支持像这样的元组比较

(column1, column2, column3) = (1, 2, 3)

But some comparison operations don't support this format, for example LIKE or IS NOT NULL . 但是某些比较操作不支持此格式,例如LIKEIS NOT NULL For those, you must use just one column on the left of the comparison. 对于这些,您必须仅使用比较左侧的一列。

See https://dev.mysql.com/doc/refman/5.7/en/scalar-subqueries.html for more details on this. 有关更多详细信息,请参见https://dev.mysql.com/doc/refman/5.7/en/scalar-subqueries.html

It would be more clear to use EXISTS (subquery) instead of (subquery) IS NOT NULL . 使用EXISTS (subquery)代替(subquery) IS NOT NULL会更清楚。

IF EXISTS (SELECT * FROM ...) THEN
    ...

Then it doesn't matter what you put in the select-list, MySQL will ignore it anyway, since it's only interested in whether one or more rows exist, not what they return. 然后,无论您将什么放在选择列表中,MySQL都将忽略它,因为它只对是否存在一行或多行感兴趣,而不关心它们返回的内容。 See https://dev.mysql.com/doc/refman/5.7/en/exists-and-not-exists-subqueries.html 参见https://dev.mysql.com/doc/refman/5.7/en/exists-and-not-exists-subqueries.html


Besides that error, I have some other comments on your code: 除了该错误,我对您的代码还有其他一些评论:

  • You don't need so many BEGIN ... END blocks. 您不需要那么多BEGIN ... END块。 The IF THEN ELSE END IF syntax already supports blocks of multiple statements. IF THEN ELSE END IF语法已经支持多个语句块。 See https://dev.mysql.com/doc/refman/5.7/en/if.html 参见https://dev.mysql.com/doc/refman/5.7/en/if.html

  • Code indentation and formatting is important to help you spot logic mistakes. 代码缩进和格式化对于帮助您发现逻辑错误很重要。

  • You seem to be using UPDATE as if it supports an ELSE clause. 您似乎在使用UPDATE ,好像它支持ELSE子句一样。 Maybe you mean "if it matches no rows, then do this other thing"? 也许您的意思是“如果不匹配任何行,那么就做另一件事”? This is a mistake. 这是个错误。 There is no such feature for UPDATE . UPDATE没有这种功能。

    You might like to use the ROW_COUNT() function instead, to test if the UPDATE changed anything. 您可能想使用ROW_COUNT()函数来测试UPDATE是否更改了任何内容。

  • Several times you use SELECT...INTO to capture an auto-increment ID that was just generated by a preceding INSERT . 多次使用SELECT...INTO捕获由前面的INSERT刚生成的自动增量ID。 It would be simpler to do this: 这样做会更简单:

     SET ccountryId = LAST_INSERT_ID(); 

    That function always returns the most recently generated auto-increment id, and it's safe to use if there are other concurrent sessions doing their own inserts. 该函数始终返回最近生成的自动增量ID,如果还有其他并发会话在执行自己的插入操作,则可以安全使用。 See the manual on the LAST_INSERT_ID() function to read about it. 请参阅LAST_INSERT_ID()函数上的手册以了解其内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM