You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MySQL存储过程中传递数组参数?附代码求助

问题分析与修复方案

从你的代码来看,有几个关键问题导致你无法得到预期结果,我来逐一拆解并给出修复步骤:

核心问题梳理

  1. 存储过程名称不匹配:Model里调用的是getCertificateByEmail,但你实际创建的存储过程叫Certificate_By_Email,名称不一致直接导致调用失败。
  2. 参数类型错误:存储过程定义的certID是INT类型,但你需要传递的是多个ID的集合(逗号分隔的字符串),FIND_IN_SET函数需要的是字符串参数,不是单个整数。
  3. Controller数据获取与逻辑断层:你从表单获取的是邮箱列表,但存储过程是根据cert_id查询,两者没有关联;同时获取POST数组的写法有误,且certID参数传递缺失。

逐步修复步骤

1. 修正存储过程

统一名称并修改参数类型,适配多ID集合的需求:

DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `getCertificateByEmail`(IN `certIDs` VARCHAR(255))
BEGIN
SELECT `cert_id`, `cert_user_id`, `cert_landlord_id`, tbl_landlord.landlord_id, tbl_landlord.landlord_main_email, `cert_property_id`, tbl_property.property_code, tbl_property.property_city, tbl_property.property_cluster, tbl_cluster.cluster_name, `cert_status`, `cert_number`, tbl_certificates.certificate_name, `cert_issue_date`, `cert_expiry_date`, `cert_duration`, `cert_updated_date`, `cert_remarks`, `cert_notes`
FROM `tbl_certificate_details`
LEFT OUTER JOIN tbl_landlord ON tbl_certificate_details.cert_landlord_id = tbl_landlord.landlord_id
LEFT OUTER JOIN tbl_property ON tbl_certificate_details.cert_property_id = tbl_property.property_id
LEFT OUTER JOIN tbl_certificates ON tbl_certificate_details.certificate_id = tbl_certificates.certificate_id
LEFT OUTER JOIN tbl_cluster ON tbl_property.property_cluster = tbl_cluster.cluster_id
LEFT OUTER JOIN tbl_area ON tbl_property.property_area = tbl_area.area_name
WHERE FIND_IN_SET(cert_id, certIDs);
END$$
DELIMITER ;

2. 修正View的复选框(二选一)

根据你的实际需求调整:

  • 如果是选中证书记录,获取对应邮箱发邮件,把复选框value改为cert_id:
<input type="checkbox" class="checkbox" name="sendMail[]" value="<?= $certify->cert_id; ?>">
  • 如果是选中邮箱,获取该邮箱关联的所有证书,保持value为邮箱即可,后续需要先通过邮箱查询对应的cert_id集合。

3. 修正Controller逻辑

这里以「选中证书记录」的需求为例调整代码:

public function sendMail() {
    if(isset($_POST['submit']) && !empty($_POST['sendMail'])){
        // 把选中的cert_id数组转为逗号分隔的字符串
        $certIDs = implode(',', $_POST['sendMail']);
        
        // 调用Model获取证书数据
        $result['certMails'] = $this->c->getCertificateByEmail($certIDs);
        
        // 从结果中提取邮箱列表
        $email_to = array_column($result['certMails'], 'landlord_main_email');
        
        // 把数据传给邮件模板视图
        $body = $this->load->view('Emails/emailAll', $result, true);
        
        // 这里添加你的邮件发送逻辑...
    } else {
        // 处理未选中任何选项的情况
        redirect('certificate/index');
    }
}

如果是「选中邮箱」的需求,需要先通过邮箱查询cert_id:

public function sendMail() {
    if(isset($_POST['submit']) && !empty($_POST['sendMail'])){
        $selectedEmails = $_POST['sendMail'];
        // 先获取邮箱对应的cert_id集合
        $this->db->select('cert_id');
        $this->db->from('tbl_certificate_details');
        $this->db->join('tbl_landlord', 'tbl_certificate_details.cert_landlord_id = tbl_landlord.landlord_id');
        $this->db->where_in('tbl_landlord.landlord_main_email', $selectedEmails);
        $query = $this->db->get();
        $certIDs = implode(',', array_column($query->result_array(), 'cert_id'));
        
        // 调用存储过程获取数据
        $result['certMails'] = $this->c->getCertificateByEmail($certIDs);
        // 后续邮件逻辑...
    }
}

4. 修正Model的存储过程调用

添加参数绑定避免SQL注入,同时正确处理存储过程的结果:

public function getCertificateByEmail($certIDs) {
    // 使用参数绑定防止SQL注入
    $query = $this->db->query("call getCertificateByEmail(?)", array($certIDs));
    if ($query) {
        $data = $query->result();
        // 处理MySQL存储过程的连接遗留问题
        $query->next_result();
        $query->free_result();
        return $data;
    } else {
        return false;
    }
}

额外注意事项

  • SQL注入防护:一定要用参数绑定的方式传递参数,不要直接拼接字符串。
  • 表单参数传递:如果你的业务需要单个certID,可以在表单中添加隐藏域传递:
<input type="hidden" name="certID" value="<?= $certID; ?>">

然后在Controller中通过$this->input->post('certID')获取。

内容的提问来源于stack exchange,提问作者Ganesh Aher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:20:10