如何在Zend Framework 2中设置sql_mode?

时间:2013-04-15 22:40:21

标签: mysql sql zend-framework2 zend-db sql-mode

我目前在Zend Framework 2中遇到分页问题。

此代码

public function findAllByCriteria(CourseSearchInput $input) {
    $concatDelimiter = self::CONCAT_DELIMITER;
    $select = new Select();
    $where = new Where();
    $having = new Having();
    $select->columns(array(
        'id', 'title', 'description'
    ));
    $select->from($this->tableGateway->getTable());
    $select
        ->join('coursedata', 'courses.id = coursedata.id', array(
            'relevance' => $this->buildRelevanceExpressionFromCriteria($input)
        ))
    ;
    $having
        ->greaterThanOrEqualTo('relevance', self::RELEVANCE_MIN);
    ;
    $select->where($where, Predicate::OP_AND);
    $select->having($having);
    $select->group(array('courses.id'));

    $dbAdapter = $this->tableGateway->getAdapter();
    // $dbAdapter->getDriver()->getConnection()->execute('SET sql_mode = "";');
    $adapter = new \Zend\Paginator\Adapter\DbSelect($select, $dbAdapter);
    $paginator = new \Zend\Paginator\Paginator($adapter);
    return $paginator;
}

创建此SQL:

SELECT
    `courses`.`id` AS `id`,
    `courses`.`title` AS `title`,
    `courses`.`description` AS `description`,
    MATCH (coursedata.title) AGAINST ('Salsa') * 5 + MATCH (coursedata.description) AGAINST ('Salsa') * 2 AS `relevance`
FROM `courses`
INNER JOIN `coursedata` ON `courses`.`id` = `coursedata`.`id`
GROUP BY `courses`.`id`
HAVING `relevance` >= '3'

如果sql_mode设置为ONLY_FULL_GROUP_BY,则会MySQL Extensions to GROUP BY使用并且无法执行。因此,我尝试在执行语句之前重置sql_mode(请参阅上面注释掉的行:$dbAdapter->getDriver()->getConnection()->execute('SET sql_mode = "";');)。但它没有奏效。那么,如何设置sql_mode以执行我的非标准SQL?

1 个答案:

答案 0 :(得分:1)

这可能不是您要问的问题的答案,但无论何时使用Paginator,我都会发现您的查询会出现问题。

Paginator的DbSelect适配器不喜欢那里的聚合函数(Group By)

Paginator将尝试使用您的查询构建自己的查询来计算集合中项目的“计数”。由于您在查询中使用聚合,因此会破坏,任何组等都会破坏适配器。

如果您检查默认实现,您将看到:

/**
 * Returns the total number of rows in the result set.
 *
 * @return integer
 */
public function count()
{
    if ($this->rowCount !== null) {
        return $this->rowCount;
    }

    $select = clone $this->select;
    $select->reset(Select::COLUMNS);
    $select->reset(Select::LIMIT);
    $select->reset(Select::OFFSET);

    // This won't work if you've got a Group By in your query
    $select->columns(array('c' => new Expression('COUNT(1)')));

    $statement = $this->sql->prepareStatementForSqlObject($select);
    $result    = $statement->execute();
    $row       = $result->current();

    $this->rowCount = $row['c'];

    return $this->rowCount;
}

这与您使用Group BY时不一样,并且会返回错误的结果。

您可以创建自己的adataper,并在计划使用Group BY时扩展现有的DbSelect并覆盖count方法;

在我的脑海中,这样的东西应该可行,但可能不是最有效的方式

/**
 * Returns the total number of rows in the result set.
 * 
 * @return integer
 */
public function count()
{
    if ($this->rowCount !== null) {
        return $this->rowCount;
    }

    /**
     * If the query hasn't got 'GROUP BY' just try and use the old method
     */
    $stateGroup = $this->select->getRawState('group');
    if( ! isset($stateGroup) || empty($stateGroup)) {
        return parent::count();
    }

    $select = clone $this->select;
    $select->reset(Select::LIMIT);
    $select->reset(Select::OFFSET);

    $statement = $this->sql->prepareStatementForSqlObject($select);
    $result    = $statement->execute();

    $this->rowCount = $result->count();

    return $this->rowCount;
}