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

如何在Doctrine QueryBuilder中添加MySQL分区查询

在Doctrine QueryBuilder中实现MySQL指定分区查询

Doctrine QueryBuilder本身并未内置支持MySQL的PARTITION语法,不过可以通过以下两种方式实现你的需求:

方法1:直接使用原生SQL查询(最简便可靠)

直接通过EntityManager执行原生SQL,完全保留你需要的分区指定逻辑:

use App\Entity\Action;
use Doctrine\ORM\EntityManagerInterface;

// 注入EntityManager
public function queryPartitionedActions(EntityManagerInterface $em)
{
    $sql = <<<SQL
        SELECT t1.*
        FROM actions PARTITION (m6, m7) as t1
        WHERE t1.created_at >= NOW() - INTERVAL 14 DAY
    SQL;

    // 如果需要映射到实体类,传入类元数据
    $query = $em->createNativeQuery($sql, $em->getClassMetadata(Action::class));
    $results = $query->getResult();

    // 若无需实体映射,直接执行即可
    // $results = $em->getConnection()->executeQuery($sql)->fetchAllAssociative();

    return $results;
}

方法2:结合QueryBuilder使用原生FROM片段

如果想保留QueryBuilder的链式调用特性,可以在from()方法中直接传入包含分区的表名片段:

use Doctrine\ORM\EntityManagerInterface;

public function queryWithQueryBuilder(EntityManagerInterface $em)
{
    $qb = $em->createQueryBuilder();

    $results = $qb->select('t1')
        // 直接在表名后拼接分区指定
        ->from('actions PARTITION (m6, m7)', 't1')
        ->where($qb->expr()->gte('t1.created_at', ':date'))
        ->setParameter('date', new \DateTime('-14 days'))
        ->getQuery()
        ->getResult();

    return $results;
}

动态指定分区的注意事项

如果需要动态选择分区,不能用参数绑定分区名(MySQL不支持),需先验证分区名的合法性再拼接,避免SQL注入:

use Doctrine\ORM\EntityManagerInterface;

public function queryDynamicPartitions(EntityManagerInterface $em, array $partitions)
{
    // 定义允许的分区列表,和你的分区表定义对应
    $allowedPartitions = ['m1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8', 'm9', 'm10', 'm11', 'm12'];
    
    // 验证每个传入的分区是否合法
    foreach ($partitions as $partition) {
        if (!in_array($partition, $allowedPartitions)) {
            throw new \InvalidArgumentException("非法分区名:{$partition}");
        }
    }

    $partitionStr = implode(', ', $partitions);

    $qb = $em->createQueryBuilder();
    $results = $qb->select('t1')
        ->from("actions PARTITION ({$partitionStr})", 't1')
        ->where($qb->expr()->gte('t1.created_at', ':date'))
        ->setParameter('date', new \DateTime('-14 days'))
        ->getQuery()
        ->getResult();

    return $results;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 01:24:30