如何使用 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->getConnection()
,它将返回底层mysqli资源的一个实例。可以调用该资源的multi_query()
方法。
将文件内容拆分为一组单独的 SQL 语句,并为每个语句调用 $adapter->query()
。 Be careful about edge cases.
使用shell_exec()
调用mysql
命令行工具的子进程来处理SQL 脚本。
【讨论】:
:sigh: ...这令人沮丧。 +1。 嗯,这会导致另一个问题 -> ***.com/questions/7395326/… .. 我不能使用shell_exec
因为 mysql 二进制文件在 PHP 服务器上不可用,而且我没有进入 SQL解析自己。以上是关于如何使用 Zend_Db_Adapter 在每次调用“查询”时运行多个 SQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章