加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php – Zend DB无法模拟MS SQL的限制和偏移量

发布时间:2020-12-13 22:50:19 所属栏目:PHP教程 来源:网络整理
导读:我正在使用Zend Framework 1.12来访问MSSQL 2008服务器.我使用FreeTDS作为数据库驱动程序. 我正在使用Zend_Db生成以下查询. $obj_sel = $obj_db - select () - from (array ('ps' = 'ProductStock'),array ('PLU','stock' = 'SUM(ps.stock)')) - join (array
我正在使用Zend Framework 1.12来访问MSSQL 2008服务器.我使用FreeTDS作为数据库驱动程序.

我正在使用Zend_Db生成以下查询.

$obj_sel = $obj_db
          -> select ()
          -> from (array ('ps' => 'ProductStock'),array ('PLU','stock' => 'SUM(ps.stock)'))
          -> join (array ('pc' => 'ProductCatalogue'),'ps.PLU = pc.PLU',NULL)
          -> join (array ('gl' => 'Gemini_Location'),'ps.Location = gl.LocationID',array ('LocationID'))
          -> where ('ps.status = 1')
          -> where ('ps.PLU IS NOT NULL');
           > where ('pc.rootPLU >= ?',$this -> int_start_rootplu);
          -> group ('ps.PLU')
          -> group ('gl.LocationID')
          -> order (array ('ps.PLU','gl.LocationID'));

如果我运行并执行此操作,我会得到一个看起来很好并且正确的查询.

SELECT "ps"."PLU",SUM(ps.stock) AS "stock","gl"."LocationID" FROM "ProductStock" AS "ps"
 INNER JOIN "ProductCatalogue" AS "pc" ON ps.PLU = pc.PLU
 INNER JOIN "Gemini_Location" AS "gl" ON ps.Location = gl.LocationID WHERE (ps.status = 1) AND (ps.PLU IS NOT NULL) AND (pc.rootPLU >= 93838) GROUP BY "ps"."PLU","gl"."LocationID" ORDER BY "ps"."PLU" ASC,"gl"."LocationID" ASC

但是当我尝试向查询添加限制或偏移时,如下所示:

$obj_sel = $obj_db
          -> select ()
          -> from (array ('ps' => 'ProductStock'),'gl.LocationID'))
          -> limit (1000,2000);

我得到以下查询SQL服务器拒绝执行.

SELECT * FROM (SELECT TOP 1000 * FROM (SELECT TOP 3000 "ps"."PLU","gl"."LocationID" ASC) AS inner_tbl ORDER BY "ps"."PLU","gl"."LocationID" DESC) AS outer_tbl ORDER BY "ps"."PLU","gl"."LocationID" asc

我收到以下错误:

SQLSTATE[HY000]: General error: 4104 General SQL Server error: Check messages from the SQL Server [4104] (severity 16) [(null)]

我不像MSSQL那样熟悉MySQL或Postgres,所以我不得不假设TOP技术是正确的.但是,很明显,无论SQL Zend DB在这里生成什么都是不对的.

这是Zend DB中的已知问题吗?如果是这样,我该如何解决呢?

解决方法

ZF 1没有正确地在SQL Server上实现分页,尽管ZF 2确实如此.

我通过继承Zend_Db_Adapter_Pdo_Mssql解决了这个问题:

class My_Zend_Db_Adapter_Pdo_Mssql extends Zend_Db_Adapter_Pdo_Mssql
{
    /**
     * @see Zend_Db_Adapter_Pdo_Mssql::limit()
     */
    public function limit($sql,$count,$offset = 0)
    {
        $count = intval($count);
        if ($count <= 0) {
            /** @see Zend_Db_Adapter_Exception */
            require_once 'Zend/Db/Adapter/Exception.php';
            throw new Zend_Db_Adapter_Exception('count parameter invalid: ' . $count);
        }

        $offset = intval($offset);
        if ($offset < 0) {
            /** @see Zend_Db_Adapter_Exception */
            require_once 'Zend/Db/Adapter/Exception.php';
            throw new Zend_Db_Adapter_Exception('offset parameter invalid: ' . $count);
        }

        if (0 == $offset) {
            $sql = preg_replace('/^SELECTs+(DISTINCTs)?/i','SELECT $1TOP ' . ($count+$offset) . ' ',$sql);
            return $sql;
        }

        $selectStart = stripos($sql,'SELECT');
        $fromStart = stripos($sql,'FROM');

        $orderby = stristr($sql,'ORDER BY');

        if ($orderby === false) {
            $orderby = 'ORDER BY (SELECT 1)';
        }

        $sql = rtrim(str_replace($orderby,'',$sql));

        $selectParams = trim(substr($sql,$selectStart + 6,$fromStart - $selectStart - 6));
        $selectParams .= ',ROW_NUMBER() OVER (' . $orderby . ') AS [ZEND_ROW_NUMBER]';

        $sql = substr($sql,$selectStart + 6) . ' ' . $selectParams . ' ' . substr($sql,$fromStart);

        $outerSql = 'SELECT * FROM (' . $sql . ') AS [ZEND_OFFSET_EMULATION]'
                  . ' WHERE [ZEND_OFFSET_EMULATION].[ZEND_ROW_NUMBER] BETWEEN '
                  . ($offset + 1) . ' AND '
                  . ($offset + $count)
                  . ' ORDER BY [ZEND_ROW_NUMBER] ASC';

        return $outerSql;
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读