【问题标题】:PHP PDO : How to call stored procedure to pass comma separated string to parameterPHP PDO:如何调用存储过程以将逗号分隔的字符串传递给参数
【发布时间】:2014-10-20 01:47:51
【问题描述】:

another thread 的帮助下,我已经制定了一个包含准备好的语句的存储过程,以将逗号分隔的字符串传递给其中一个参数。现在我无法将值绑定到 PHP PDO 中的位置参数。我需要像这样调用存储过程:

CALL load_things('''1283943kd9'',''2e9kk389334''','53')

第一个参数是型号列表,第二个参数53 是用户ID。当我在Adminer或phpmyadmin中输入命令时,它工作正常。

下面是获取括号中相应数量的问号的PHP代码:

 $id_group = $_POST["group"]; // array

 $in  = str_repeat("''?'',", count($id_group) - 1) . "''?''";    

 $sql .= "call loadit('".$in."','?')";

 $users = $dbh->prepare($sql);

 $i = 1;

 foreach ($id_group as $id) 
 {
   $users->bindValue($i++, $id);
 }

 $lasti = (count($id_group) + 1);

 $users->bindValue($lasti,$_SESSION["user_id"]);

 $users->execute();

在发送$_POST["group"] 中的 20 个值的页面上(每个值最多 30 个字符),从以下输出的外观来看,它似乎生成了确切数量的占位符。 (第 21 位是用户 ID),但我没有得到任何结果。这是来自 Chrome 控制台的响应:

SQL: [143] 

call loadit('''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?'',''?''','?')

Params:  21
Key: Position #0:
paramno=0
name=[0] ""
is_param=1
param_type=2
Key: Position #1:
paramno=1
name=[0] ""
is_param=1
param_type=2
Key: Position #2:
paramno=2
name=[0] ""
is_param=1
param_type=2
Key: Position #3:
paramno=3
name=[0] ""
is_param=1
param_type=2
Key: Position #4:
paramno=4
name=[0] ""
is_param=1
param_type=2
Key: Position #5:
paramno=5
name=[0] ""
is_param=1
param_type=2
Key: Position #6:
paramno=6
name=[0] ""
is_param=1
param_type=2
Key: Position #7:
paramno=7
name=[0] ""
is_param=1
param_type=2
Key: Position #8:
paramno=8
name=[0] ""
is_param=1
param_type=2
Key: Position #9:
paramno=9
name=[0] ""
is_param=1
param_type=2
Key: Position #10:
paramno=10
name=[0] ""
is_param=1
param_type=2
Key: Position #11:
paramno=11
name=[0] ""
is_param=1
param_type=2
Key: Position #12:
paramno=12
name=[0] ""
is_param=1
param_type=2
Key: Position #13:
paramno=13
name=[0] ""
is_param=1
param_type=2
Key: Position #14:
paramno=14
name=[0] ""
is_param=1
param_type=2
Key: Position #15:
paramno=15
name=[0] ""
is_param=1
param_type=2
Key: Position #16:
paramno=16
name=[0] ""
is_param=1
param_type=2
Key: Position #17:
paramno=17
name=[0] ""
is_param=1
param_type=2
Key: Position #18:
paramno=18
name=[0] ""
is_param=1
param_type=2
Key: Position #19:
paramno=19
name=[0] ""
is_param=1
param_type=2
Key: Position #20:
paramno=20
name=[0] ""
is_param=1
param_type=2
[]

存储过程和表架构 (fiddle):

DELIMITER ;;
CREATE PROCEDURE `load_things` (IN `yr_model_no` varchar(1000), IN `yr_app_id` int(5))
BEGIN
    SET @s = 

CONCAT('
SELECT * FROM 
(
   SELECT COUNT( c.app_id ) AS users_no, ROUND( AVG( c.min ) , 1 ) AS avg_min, ROUND( AVG( c.max ) , 1 ) AS avg_max, a.mid, a.likes, a.dislikes, b.model_no
        FROM  `like` a
        RIGHT JOIN  `model` b ON a.mid = b.mid
        LEFT JOIN  `details` c ON c.mid = b.mid
        WHERE b.model_no IN (',yr_model_no,')
        GROUP BY b.model_no
)TAB1
JOIN
(
   SELECT a.app_id,b.model_no,IFNULL(c.isbooked,0) AS isbooked,d.min,d.max,e.like_type
     FROM `users` a
     JOIN `model` b
       ON b.model_no IN (',yr_model_no,')
LEFT JOIN `favorite` c 
       ON c.app_id = a.id
      AND c.mid = b.mid         
LEFT JOIN `details` d 
       ON d.app_id = a.id
      AND d.mid = b.mid 
LEFT JOIN `users_likes` e
       ON e.app_id = a.id
      AND e.mid = b.mid
    WHERE a.id = ',yr_app_id,'
)TAB2
ON TAB1.model_no = TAB2.model_no');

PREPARE stmt from @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt3;
END;;
DELIMITER ;

谁能帮我弄清楚 PHP 代码有什么问题?我的存储过程与 PDO 不兼容吗?

【问题讨论】:

    标签: php mysql sql stored-procedures pdo


    【解决方案1】:

    您引用了占位符。那是不行的。数据库和接口库将自己处理所有这些。您只需要自己提供占位符即可:

    $in  = str_repeat('?,' count($id_group) - 1) . '?';
    

    最终应该会产生

    call loadit(?,?,?,......?)
    

    【讨论】:

    • 明白了。那么你正在做的事情根本行不通。 ? 带引号的字符串中的属性无论如何都不会被视为属性,因此您不能将任何内容绑定到它们。 PDO 中的'?' 只是一个字面问号,而不是占位符。对于这种事情,您需要使用内置的值构建一个字符串,这意味着您将受到 sql 注入攻击。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-09
    • 2020-01-13
    相关资源
    最近更新 更多