我正在将所有 mysqli 查询迁移到存储过程。 它应该像更改 mysqli 调用中的一行一样简单,但是,以下两个代码给出不同的结果:
常规查询,可以正常工作:
$query = $this->mysqli->query("SELECT DISTINCT ID FROM user
WHERE
MATCH (name) AGAINST ('* *$sanitized* *') ");
if ($query) {
$nrows = $query -> num_rows;
if ($nrows > 0) {
$searchResult = 'We found '. $nrows .' results';
}
}
调用 PROCEDURE,它返回一个“fetch_array() on boolean”错误:
$query = $this->mysqli->query("CALL myfunction('.$sanitized.')");
其中程序定义为:
DELIMITER $$
CREATE PROCEDURE myfunction (sanitized VARCHAR(124))
BEGIN
SELECT DISTINCT ID FROM user
WHERE
MATCH (name) AGAINST ('* *sanitized* *');
END
$$
DELIMITER ;
我找不到解决方案,而且这个论坛上似乎没有人有类似的问题。
最佳答案
考虑 Prepared Statements与 concat()
一起使用和往常一样。
DROP PROCEDURE if exists myStoredProc101;
DELIMITER $$
CREATE PROCEDURE myStoredProc101
( pSanitized VARCHAR(124)
)
BEGIN
set @mySql:=concat("SELECT DISTINCT ID FROM user where match(name) against ('* *",pSanitized,"* *')");
PREPARE stmt1 FROM @mySql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END
$$
DELIMITER ;
您的存储过程没有机会工作,因为它甚至没有使用您的参数。你所做的是将一些东西埋在字符串文字中。另外,varchar(124) 有点奇怪 :p
人们使用准备好的语句取得的唯一成功是使用用户变量(使用 @
)与使用局部变量(来自 DECLARE)的失败尝试。因此,这可能会为您节省几个小时的时间。
来自 PHP 手册页 Stored Procedures :
Handling result sets
Stored procedures can return result sets. Result sets returned from a stored procedure cannot be fetched correctly using mysqli_query. The mysqli_query function combines statement execution and fetching the first result set into a buffered result set, if any. However, there are additional stored procedure result sets hidden from the user which cause mysqli_query to fail returning the user expected result sets.
Result sets returned from a stored procedure are fetched using mysqli_real_query or mysqli_multi_query. Both functions allow fetching any number of result sets returned by a statement, such as CALL. Failing to fetch all result sets returned by a stored procedure causes an error.
关于从mysqli
调用存储过程,请看Answer来自巴勃罗·托巴尔。对于许多变量,它看起来并不是特别令人愉快,但这似乎就是它所在的位置。剧透警告:使用 mysql 变量,而不是 PHP 变量。
当然,Pablo 没有返回结果集,而是写入存储过程中的 OUT
var。也许你需要做他为 IN
参数做的事情,然后调用 multi_query()
,然后是 store_result()
,然后是 fetch_all()
(简而言之,PHP 引用一个页面)。
或者,调用将由 Palladium 完成 here .
无论哪种情况,都必须注意大小写以避免将 SQL 注入(inject) 传递给存储过程例程的已知漏洞。
关于php - 使用存储过程 : different results in mysqli->query ("CALL select_procedure") VS mysqli->query ("SELECT ..."),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38294813/