MySQL 5.0
CREATE TABLE `locationcodes` (
`id` int,
`customer` varchar(100),
`locationcode` varchar(50),
`parentid` int
);
insert into locationcodes values (1, 'Test, Inc.', 'California', NULL);
insert into locationcodes values (2, 'Test, Inc.', 'Los Angeles', 1);
insert into locationcodes values (3, 'Test, Inc.', 'San Francisco', 1);
insert into locationcodes values (4, 'Test, Inc.', 'Sacramento', 1);
存储过程:
CREATE PROCEDURE test (_location VARCHAR(100))
BEGIN
SET @location = _location;
SET @select='
SELECT id, locationcode
FROM locationcodes
WHERE customer="Test, Inc."
AND id in (?)
';
PREPARE stmt FROM @select;
EXECUTE stmt USING @location;
DEALLOCATE PREPARE stmt;
END
通话程序:
call test('2, 3')
结果:
2, Los Angeles
结果只有一行,但我想要两行。挑战是准备好的语句看到参数是一个varchar,并相应地在值周围加上引号。我不想引用任何引号,以便我可以构建一个IN语句,怎么能这样做呢?理想情况下,MySQL会有一个int数据类型的列表,所以我不必使用varchar,但这不存在。
我需要保留准备好的语句以防止sql注入攻击。
答案 0 :(得分:1)
似乎无法使用带有IN()的预准备语句并绑定一个值。
出于某种原因,当在相应的比较中只有一个值要绑定时,MySQL的API用=(相等)替换IN()。
我用我们的程序进行了一些测试,这是我得到的。
使用MySQL生成的原始程序(test是我的默认数据库):
((`test`.`locationcodes`.`customer` = 'Test, Inc.') and
(`test`.`locationcodes`.`id` = '2,3'))
在这种情况下,字段id是整数,MySQL转换为' 2,3'比较中的2,这就是它返回洛杉矶的原因,' 3,2'将返回旧金山'明显。
为了确保这与字段类型(id为整数)无关,我试图将该值与locationcode(varchar)进行比较,结果是相同的。
我将您的程序更改为绑定两个值而不是一个。
...
SET @select='
SELECT id, locationcode
FROM locationcodes
WHERE customer="Test, Inc."
AND id in (?,?)
';
PREPARE stmt FROM @select;
EXECUTE stmt USING @location,@location2;
...
在这种情况下,正确创建语句。
((`test`.`locationcodes`.`customer` = 'Test, Inc.') and
(`test`.`locationcodes`.`id` in ('2','3')))
话虽如此,我可以告诉你,必须使用另一种方法,通过准备好的陈述来实现这一目标。
我的测试后发现了这个错误报告:http://bugs.mysql.com/bug.php?id=16564
根据Valeriy,使用值创建一个临时表并使用JOIN。它应该工作。