我有一个包含autos
列的表name
,我想检查表中的前5行,如果name
值是"toyota"
,则在表{ {1}}写“是”,否则写“不”。
我编写存储过程,但mytable
返回错误,我有mysqli_error()
。
如果在EXECUTE ...
中我不写WHEN
,而是直接写查询,则该过程有效。
请看我的代码告诉我,哪里错了?
PREPARED STATEMENT
答案 0 :(得分:2)
(关于EXECUTE
的建议被删除为不正确且可能令人困惑。)
您尝试使用存储过程解决的问题实际上可以在没有它的情况下使用完全不同的方法解决:只需使用单个INSERT ... SELECT
语句:
INSERT INTO mytable (log)
SELECT
CASE name
WHEN 'toyota' THEN 'yes'
ELSE 'no'
END
FROM autos
ORDER BY id
LIMIT 5
也就是说,上述语句与存储过程相同:它从autos
检索前5行,并在mytable
中插入5行。根据{{1}}的值,它会生成name
es或yes
s。
答案 1 :(得分:2)
Andriy M的INSERT
声明是最优雅的解决方案,但如果您仍想使用某个程序,这将有效:
CREATE PROCEDURE proc_auto()
BEGIN
DECLARE start INT DEFAULT 0;
PREPARE stmt FROM
'SELECT name INTO @name FROM autos ORDER BY id LIMIT ?,1';
WHILE start < 5 DO
SET @start = start;
EXECUTE stmt USING @start;
IF @name = 'toyota' THEN
INSERT INTO mytable (log) VALUES('yes');
ELSE
INSERT INTO mytable (log) VALUES('no');
END IF;
SET start = start + 1;
END WHILE;
END;
但是,在这种情况下,使用CURSOR
会产生更好的效果:
CREATE PROCEDURE proc_auto()
BEGIN
DECLARE start INT DEFAULT 0;
DECLARE b_not_found BOOL DEFAULT FALSE;
DECLARE cur CURSOR FOR
'SELECT name FROM autos ORDER BY id LIMIT 5';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET b_not_found = TRUE;
OPEN cur;
loop1: WHILE start < 5 DO
FETCH cur INTO @name;
IF b_not_found THEN
LEAVE loop1;
END IF;
IF @name = 'toyota' THEN
INSERT INTO mytable (log) VALUES('yes');
ELSE
INSERT INTO mytable (log) VALUES('no');
END IF;
SET start = start + 1;
END WHILE;
CLOSE cur;
END;