【问题标题】:ADD SYSTEM VERSIONING Exception in Laravel Migration在 Laravel 迁移中添加系统版本异常
【发布时间】:2019-05-01 04:01:27
【问题描述】:

我正在尝试在 Laravel 中使用 MariaDB 10.3 的 System Versioned Tables 功能。但是,每当我尝试运行更改表的工匠迁移时,都会遇到以下异常。

C:\htdocs\Computers>php artisan migrate:fresh
Dropped all tables successfully.
Migration table created successfully.

   PDOException  : SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'row_start'

  at C:\htdocs\Computers\database\migrations\2018_07_14_191112_add_system_version_to_computers.php:16
    12|      * @return void
    13|      */
    14|     public function up()
    15|     {
  > 16|         DB::connection()->getPdo()->exec("ALTER TABLE `COMPUTERS` ADD SYSTEM VERSIONING;");
    17|     }
    18|
    19|     /**
    20|      * Reverse the migrations.

  Exception trace:

  1   PDO::exec("ALTER TABLE `COMPUTERS` ADD SYSTEM VERSIONING;")
      C:\htdocs\Computers\database\migrations\2018_07_14_191112_add_system_version_to_computers.php:16

  2   AddSystemVersionToComputers::up()
      C:\htdocs\Computers\vendor\laravel\framework\src\Illuminate\Database\Migrations\Migrator.php:359

  Please use the argument -v to see more details.
  1. 我已经在一张空表以及已经有数据的表上试过这个

  2. 我尝试使用以下方法抑制 PDO 异常,但它的行为好像可以正常工作,但在我检查表时未添加系统版本控制

    DB::connection()->getPdo()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
    
  3. 如果我在 HeidiSQL 中执行相同的 SQL,我可以将系统版本控制添加到表中

  4. 我已经在 Laravel 文档和代码中搜索了任何允许我在创建时添加此表选项但找不到任何内容的方法。

我可以手动解决这个问题,但我真的想将其包含在 Laravel 迁移文件中,以便将其包含在 Git 存储库中。


运行命令的结果

SHOW CREATE TABLE `computers`;

...

+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table     | Create Table                                                                                                                                                                                                                                                                                                                                                          |
+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| computers | CREATE TABLE `computers` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `Name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `computers_name_unique` (`Name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci |
+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.000 sec)

以下是从 MariaDB 命令行运行相同 SQL 语句的结果。请注意在表定义中添加了“WITH SYSTEM VERSIONING”。

MariaDB [computers]> ALTER TABLE COMPUTERS ADD SYSTEM VERSIONING;
Query OK, 0 rows affected (0.025 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [computers]> SHOW CREATE TABLE `computers`;
+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table     | Create Table                                                                                                                                                                                                                                                                                                                                                                                 |
+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| computers | CREATE TABLE `computers` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `Name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `computers_name_unique` (`Name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci WITH SYSTEM VERSIONING |
+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.002 sec)

在 Artisan Tinker 中运行相同的 alter table 命令并得到相同的错误:

    >>>             DB::connection()->getPdo()->exec("ALTER TABLE `COMPUTERS` ADD SYSTEM VERSIONING;");
PDOException with message 'SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'row_start''

如果我尝试为computers-lcl 用户授予所有权限,仍然会出现相同的错误。

DROP USER IF EXISTS `computers-lcl`@`localhost`;
FLUSH PRIVILEGES;
GRANT ALL ON *.* TO `computers-lcl`@`localhost` IDENTIFIED BY 'qej8lOjoc81Ekub1d26uzerOv332Qa' WITH GRANT OPTION;

提前感谢您提供的任何指导。

【问题讨论】:

  • 什么版本的 PHP?
  • 嗨瑞克!对不起,我忘记标记了。具体来说是 7.2.7。
  • 'row_start' 的默认值无效,它的默认值是什么?
  • 这与 laravel 无关,请检查是否可以从命令行执行,然后将其用作 laravel raw
  • @flakerimi 我看不出默认值是什么,因为“ALTER TABLE COMPUTERS ADD SYSTEM VERSIONING;”语句引发异常,当我尝试查看显示表的内容时,没有任何变化。我将编辑原始问题以包含表定义。

标签: sql laravel mariadb laravel-5.6 php-7.2


【解决方案1】:

TL;DR: 问题是由于在 laravel 使用的 sql_mode 中设置了 NO_ZERO_DATE。在'mysql' => []部分设置'strict' => falseconfig/database.php


我自己偶然发现了这个问题,我很确定我们正在处理同样的问题,这是由于在您的 sql_mode 中设置了 NO_ZERO_DATE 引起的。

由于ALTER TABLE 语句在您通过 CLI 客户端或 HeidiSQL(或任何其他 DB GUI)执行该语句时工作正常,请将来自该客户端的sql_mode 与来自该客户端的sql_mode 进行比较你的 laravel 数据库会话。

这是 CLI 客户端使用的我的SQL_MODE

mysql -u root -p    
MariaDB [(none)]> SELECT @@SQL_MODE;
+-----------------------------------------------------------------------+
| @@SQL_MODE                                                            |
+-----------------------------------------------------------------------+
| ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-----------------------------------------------------------------------+
1 row in set (0.000 sec)

这是我的 SQL_MODE laravel 使用的:

php artisan tinker
Psy Shell v0.9.9 (PHP 7.3.4-1+ubuntu18.10.1+deb.sury.org+3 — cli) by Justin Hileman
>>> DB::select( DB::raw("SELECT @@SQL_MODE") );
=> [
     {#3102
       +"@@SQL_MODE": "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION",
     },
   ]

如您所见,laravel 使用的是NO_ZERO_DATE,而我的命令行客户端没有使用。这是因为strict 模式是config/database.php 中MySQL 数据库的默认设置。如果'strict' => true,则在laravel/framework/src/Illuminate/Database/Connectors/MySqlConnector.php中的DB-connection设置期间触发以下代码:

    /**
     * Get the query to enable strict mode.
     *
     * @param  \PDO  $connection
     * @return string
     */
    protected function strictMode(PDO $connection)
    {
        if (version_compare($connection->getAttribute(PDO::ATTR_SERVER_VERSION), '8.0.11') >= 0) {
            return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'";
        }

        return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'";
    }

还有罪人NO_ZERO_DATE。在config/database.php 中设置'strict' => false,laravel 不会再摆弄你的sql_mode。如果您只想删除NO_ZERO_DATE 部分而保留其余的严格模式,则一种解决方案可能是提供your own MySqlConnector ServiceProvider。

【讨论】:

    猜你喜欢
    • 2020-10-06
    • 2021-06-11
    • 2019-10-05
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-06
    • 2019-10-22
    相关资源
    最近更新 更多