如何在 TYPO3 中的 Scheduler 中从 SQL 文件执行 SQL 语句?

问题描述

概念:

我有一个任务,它在数据库中导入一些数据。数据库架构可以随时更改,因为它已导出到文件夹。所以我必须读取数据库文件并创建结构。我想用 TYPO3 API 来做。在 TYPO3 9 之前,我会做这样的事情:

$sqlQueries = explode(';',file_get_contents(dirname(__FILE__) . DIRECTORY_SEParaTOR . 'myFile.sql'));
foreach ($sqlQueries as $sqlQuery) {
    $sqlQuery = trim($sqlQuery);
    if (!empty($sqlQuery) && $this->db instanceof DatabaseConnection && method_exists($this->db,'sql_query')) {
       $this->db->sql_query($sqlQuery);
    }
 }

我如何使用 TYPO3 10 做到这一点?

最好的问候

解决方法

TYPO3 10 已经有这样的功能,你可以在维护模块下找到它 分析数据库结构。感谢 Mathias Brodala 我找到了我的解决方案。 (它总是可以改进的)。

在您的任务中,您调用 SqlReader 类以从 SQL 文件中提取语句。使用命名空间如下(截至 TYPO3 10)

use TYPO3\CMS\Core\Database\Schema\SqlReader;

现在我们有两个问题

  1. TYPO3 评估和执行的 SQL 仅限于模式。对于内容更改,您需要第三方库/工具。
  2. 它只创建表,默认情况下不会删除它们。

第一个“问题”是说您只能执行数据库结构更改,而不能更改其中的内容。为此,可以使用 QueryBuilder

第二个问题是 SqlReader 类中的 getCreateTableStatementArray 函数执行以下操作:

return $this->getStatementArray($dumpContent,'^CREATE TABLE');

这会调用 getStatementArray 函数,它只返回 CREATE TABLE 命令。所以如果你在 SQL 文件中有一个 DROP TABLE 命令,它不会被考虑在内。为此,我们需要为 getCreateTableStatementArray 创建我们自己的函数。所以在你的任务中,创建这个函数:

/**
 * @param string $dumpContent
 * @return array
 */
public function getCreateTableStatementArray(string $dumpContent): array
{
    $sqlReader = GeneralUtility::makeInstance(SqlReader::class);
    return $sqlReader->getStatementArray($dumpContent);
}

这样,TYPO3 将不会按命令名称评估语句,而是会获取 sql 文件中可用的所有命令。

既然我们已经这样做了,我们需要将语句传递到我们的自定义函数中进行解析。所以在你的代码中你会得到文件的内容。我是这样的:

/**
 * @return bool
 * @throws \Exception
 */
public function execute()
{
  ...
  $this->createTableStructure();
  ...
}

protected function createTableStructure()
{
    $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
    $sqlStatements = $this->getCreateTableStatementArray(file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'myFile.sql'));
    foreach ($sqlStatements as $sqlStatement) {
        if (strpos($sqlStatement,' CHARSET=utf8') !== false) {
            $sqlStatement = str_replace(" DEFAULT CHARSET=utf8","",$sqlStatement);
        }
        $connection = $connectionPool->getConnectionByName('Default');
        try {
            $connection->executeUpdate($sqlStatement);
        } catch (DBALException $e) {
            //Your log here
        }
    }
}

对于这部分,我收到一个错误,即 TYPO3 无法读取 DEFAULT 属性,因此我不得不将其删除。

if (strpos($sqlStatement,' CHARSET=utf8') !== false) {
   $sqlStatement = str_replace(" DEFAULT CHARSET=utf8",$sqlStatement);
}

这在 SQL 文件中看起来像这样:

DROP TABLE IF EXISTS `myTable`;
CREATE TABLE IF NOT EXISTS `myTable` (
  `myColumn1` int(10) NOT NULL DEFAULT '0',`myColumn2` varchar(255) DEFAULT NULL,`myColumn3` varchar(255) DEFAULT NULL,`myColumn4` date DEFAULT NULL,`myColumn5` varchar(255) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

希望对你有帮助!

最好的问候