【问题标题】:How do I run multiple SQL queries per call to "query" using Zend_Db_Adapter?如何使用 Zend_Db_Adapter 在每次调用“查询”时运行多个 SQL 查询?
【发布时间】: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 服务器版本相对应的手册,以了解在 ';' 附近使用的正确语法

【问题讨论】:

    标签: php sql zend-framework


    【解决方案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。
    • 嗯,这会导致另一个问题 -> stackoverflow.com/questions/7395326/… .. 我不能使用 shell_exec 因为 mysql 二进制文件在 PHP 服务器上不可用,而且我没有进入 SQL解析自己。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    • 2013-08-10
    • 2011-06-18
    • 1970-01-01
    相关资源
    最近更新 更多