如何使用 Zend_Db_Adapter 在每次调用“查询”时运行多个 SQL 查询?

Posted

技术标签:

【中文标题】如何使用 Zend_Db_Adapter 在每次调用“查询”时运行多个 SQL 查询?【英文标题】:How do I run multiple SQL queries per call to "query" using Zend_Db_Adapter? 【发布时间】:2011-09-12 23:05:32 【问题描述】:

这是我写的Zend_Application_Resource,用于在部署中进行更改时自动更新架构。

<?php

/**
 * Makes sure the current schema version matches what we're expecting for this
 * particular version of the application.
 * 
 * The version of the database is compared against the value configured in
 * application.ini. SQL scripts corresponding to versions between the database
 * version's and the current local SQL scripts are run against the database to
 * get things up to date.
 *
 * @copyright 2011 Case Western Reserve University, College of Arts and Sciences
 * @author Billy O'Neal III (bro4@case.edu)
 */
class Cas_Application_Resource_Schema extends Zend_Application_Resource_ResourceAbstract

    /**
     * Creates an array of filepaths corresponding to the scripts that need
     * to run.
     * 
     * @param int $from
     * @param int $to
     * @return array
     */
    private function GetScriptsToRun($from, $to)
    
        $application = APPLICATION_PATH . '/configs/sql/';
        $result = array();
        for($cur = $from + 1; $cur <= $to; $cur++)
        
            $result[] = "$application$cur.sql";
        
        return $result;
    

    /**
     * Returns the version the application is locally configured to expect.
     * 
     * @return int
     */
    private function GetLocalVersion()
    
        $options = $this->getOptions();
        $version = (int)$options['version'];
        return $version;
    

    /**
     * Returns the version the database thinks it is.
     * 
     * @return int
     */
    private function GetDbVersion()
    
        $adapter = Zend_Db_Table::getDefaultAdapter();
        $metadataTable = new Cas_Model_Table_Metadata;
        $verQuery = $metadataTable->select()->from($metadataTable, array('Value'));
        $verQuery->where("$adapter->quoteIdentifier('Key') = ?", 'Version');
        $dbVersion = $adapter->fetchOne($verQuery);
        return (int)$dbVersion;
    

    /**
     * Runs the specified filepath's file contents as a SQL script.
     * 
     * @param string $scriptPath
     */
    private function RunSqlScript($scriptPath)
    
        $adapter = Zend_Db_Table::getDefaultAdapter();
        $contents = file_get_contents($scriptPath);
        $adapter->query($contents);
    

    /**
     * Updates the version number in the database to match the version
     * specified in the local configuration file.
     */
    private function UpdateVersion()
    
        $metadataTable = new Cas_Model_Table_Metadata;
        $metadataTable->delete(array("$metadataTable->getAdapter()->quoteIdentifier('Key') = ?" => 'Version'));
        $metadataTable->insert(array('Version' => $this->GetLocalVersion()));
    

    /**
     * Performs the actual schema checks.
     */
    public function init()
    
        //We depend on the database being connected.
        $this->getBootstrap()->bootstrap('db');
        $local = $this->GetLocalVersion();
        $remote = $this->GetDbVersion();
        if ($local < $remote)
        
            throw new Exception('Database version is newer than local version.');
        
        else if ($remote < $local)
        
            $scripts = self::GetScriptsToRun($remote, $local);
            foreach($scripts as $script)
            
                $this->RunSqlScript($script);
            
            $this->UpdateVersion();
        
    

这会失败,因为有问题的脚本(例如 configs/sql/1.sql、configs/sql/2.sql 等)包含多个 SQL 语句,用 ;s 分隔,消息如下:

Zend_Db_Statement_mysqli_Exception:Mysqli 准备错误:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以了解在 ';' 附近使用的正确语法

【问题讨论】:

【参考方案1】:

Zend_Db_Adapter 不支持multi_query()

您可以选择解决方法:

调用$adapter-&gt;getConnection(),它将返回底层mysqli资源的一个实例。可以调用该资源的multi_query()方法。

将文件内容拆分为一组单独的 SQL 语句,并为每个语句调用 $adapter-&gt;query()。 Be careful about edge cases.

使用shell_exec() 调用mysql 命令行工具的子进程来处理SQL 脚本。

【讨论】:

:sigh: ...这令人沮丧。 +1。 嗯,这会导致另一个问题 -> ***.com/questions/7395326/… .. 我不能使用 shell_exec 因为 mysql 二进制文件在 PHP 服务器上不可用,而且我没有进入 SQL解析自己。

以上是关于如何使用 Zend_Db_Adapter 在每次调用“查询”时运行多个 SQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章

性能调优基本原则

dbms_stats(性能调优)

我把eclipse字体调大了,每次重启又变小了,怎么办?一重启就变小,

如何调优JVM - 优化Java虚拟机(大全+实例)

LNMP 参数调优 ( 无注释 )

layui前端分页不要每次调后端