使用Doctrine DBAL创建视图和存储过程

时间:2014-04-16 15:55:17

标签: php mysql symfony pdo

我们在Symfony2应用程序中使用Doctrine。为了帮助进行一些数据库交互,我们定义了一些视图和存储过程。它们存储在项目源的特定目录中,然后置于版本控制之下,以便团队中的每个人都可以访问它们。每个视图或存储过程都有自己的.sql文件,其中包含将创建视图/存储过程的查询,包括" drop(如果已存在)"线。

我们编写了一个控制台命令来浏览保存.sql文件的目录,然后通过从Doctrine dbal连接创建的PDO对象向数据库发出查询。

检查MySQL查询日志显示每个"创建视图"和"创建程序"命令已执行,PDO连接没有给出任何错误。但是,当我们在命令运行后检查数据库时,并不是所有预期的项都存在。这是奇怪的一点......目前,我们有命令创建3个视图和1个存储过程。当我们第一次运行命令时,会创建2个视图。然后,我们再次运行它,并创建第三个视图。无论我们运行命令多少次,都不会创建存储过程。

所以,任何人都可以提供任何帮助,说明为什么会发生这种情况。数据库用户具有必要的权限,查询日志表明一切正常。

这是console命令的执行方法;

/**
* execute command
*
* @param InputInterface  $input
* @param OutputInterface $output
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
    $path = $input->getArgument('path');

    $this->setAbsolutePath($path);

    if (!$this->doesPathExist()) {
        throw new \InvalidArgumentException($this->absolutePath.' does not exist, or is not a directory');
    }

    $files = $this->getFiles();

    foreach ($files as $file) {
        $bits = explode('.', $file);
        if (count($bits)>1) {
            $extension = end($bits);
            if (strtolower($extension) === 'sql' ) {

                if ($this->runScript($file)) {
                    $output->writeln($file.' ran successfully!');
                } else {
                    $output->writeln($file. ' errored!');
                }
            }
        }
    }

    $output->writeln('Done');
}

调用此方法' runScript' ...

/**
* run script
* executes the sql commands in the provided file
* returns true if the script executed, false otherwise
*
* @param string $filename
*
* @return boolean
*/
private function runScript($filename)
{
    $em = $this->getContainer()->get('doctrine')->getManager();

    $connection = $em->getConnection();
    $host = $connection->getHost();
    $username = $connection->getUsername();
    $password = $connection->getPassword();
    $database = $connection->getDatabase();
    $pdoConn = new \PDO('mysql:host=' . $host . ';dbname=' . $database, $username, $password);

    $result = false;

    if ($pdoConn) {
        $result = false;
        $script = file_get_contents($this->absolutePath.'/'.$filename);
        $stmt = $pdoConn->prepare($script);
        try {
            $result = $stmt->execute();
        } catch (\PDOException $e) {
            $result = false;
        }
        unset($stmt);
    }
    unset($pdoConn);

    return $result;
}

如您所见,我们一直在尝试创建一个全新的PDO数据库连接来发出命令。运行该命令时,它会列出四个.sql文件,并说它们都运行成功。

如果我们在命令行上使用MySQL执行.sql文件目录,使用Symfony用于连接数据库的同一用户,所有视图和过程都是正确创建的,所以我们确定没有.sql文件中的错误。

我们难过了!

1 个答案:

答案 0 :(得分:2)

问题是在存储过程的定义中使用DELIMITER $$。该定义最初是使用MySQL命令行编写的,因此需要区分表示命令结束的实际分号和存储过程中的分号。因此,分隔符已更改。

通过DBAL / PDO连接创建存储过程时不需要这样做。

因此,简而言之,解决方案是坚持在创建存储过程的.sql脚本中使用分号作为分隔符。