无法创建或更改没有主键的表 - Laravel DigitalOcean 托管数据库

Posted

技术标签:

【中文标题】无法创建或更改没有主键的表 - Laravel DigitalOcean 托管数据库【英文标题】:Unable to create or change a table without a primary key - Laravel DigitalOcean Managed Database 【发布时间】:2020-10-06 15:05:13 【问题描述】:

我刚刚使用(托管数据库)将我的应用程序部署到 DigitalOcean,并且在调用 php artisan migrate 时出现以下错误

SQLSTATE[HY000]: General error: 3750 Unable to create or change a table without a primary key, when the system variable 'sql_require_primary_key' is set. Add a primary key to the table or unset this variable to avoid this message. Note that tables without a primary key can cause performance problems in row-based replication, so please consult your DBA before changing this setting. (SQL: create table `sessions` (`id` varchar(255) not null, `user_id` bigint unsigned null, `ip_address` varchar(45) null, `user_agent` text null, `payload` text not null, `last_activity` int not null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')

mysql var sql_require_primary_key 设置为 true 时,Laravel 迁移似乎不起作用。

你有什么解决办法吗?

【问题讨论】:

【参考方案1】:

定义了一个简洁的解决方案here。解决方案是添加侦听器以迁移脚本并在执行迁移之前和之后打开和关闭sql_require_primary_key。此解决方案解决了无法修改迁移脚本的问题,例如当它们来自库或 Voyager 等框架时。

<?php

namespace App\Providers;

    use Illuminate\Database\Events\MigrationsStarted;
    use Illuminate\Database\Events\MigrationsEnded;
    use Illuminate\Support\Facades\DB;
    use Illuminate\Support\Facades\Event;
    use Illuminate\Support\ServiceProvider;
    
    class AppServiceProvider extends ServiceProvider 
        /**
         * Register any application services.
         *
         * @return void
         */
        public function register() 
    
            // check this one here https://github.com/laravel/framework/issues/33238#issuecomment-897063577
            Event::listen(MigrationsStarted::class, function ()
                if (config('databases.allow_disabled_pk')) 
                    DB::statement('SET SESSION sql_require_primary_key=0');
                
            );
    
            Event::listen(MigrationsEnded::class, function ()
                if (config('databases.allow_disabled_pk')) 
                    DB::statement('SET SESSION sql_require_primary_key=1');
                
            );
         
// rest of the class 


【讨论】:

【参考方案2】:

对于更大的sql文件,可以用这个命令(如果你的文件大小

第一:

sed  -i '1i SET SQL_REQUIRE_PRIMARY_KEY = 0;' db.sql

第二:

sed  -i '1i SET @ORIG_SQL_REQUIRE_PRIMARY_KEY = @@SQL_REQUIRE_PRIMARY_KEY;' db.sql

【讨论】:

【参考方案3】:

我通过工单联系了 DigitalOcean,询问他们是否要禁用该要求,他们在第二天就这样做了 :)

所以你可以问他们

感谢您与我们联系! 我了解您希望禁用托管数据库的主要要求。您的托管数据库 ****** 的主要要求已被禁用

【讨论】:

【参考方案4】:

添加您的第一个迁移:

\Illuminate\Support\Facades\DB::statement('SET SESSION sql_require_primary_key=0');

内部:Schema::create() 函数。

【讨论】:

您的建议效果很好,非常感谢!【参考方案5】:

我试图通过使用 WordPress 安装中的 mysqldump 文件导入 DO Managed MySQL 来解决此问题。我发现将其添加到文件顶部确实对我的导入有用。

SET @ORIG_SQL_REQUIRE_PRIMARY_KEY = @@SQL_REQUIRE_PRIMARY_KEY;
SET SQL_REQUIRE_PRIMARY_KEY = 0;

然后我使用 JetBrains DataGrip 导入,它没有错误地工作。

【讨论】:

为什么不在导入前向缺少它们的表添加主键?【参考方案6】:

很遗憾,我们无法更改数字海洋 MySQL 数据库中的 sql_require_primary_key 值。相反,您可以通过添加 primary() 将 id 设置为主键

【讨论】:

我将它添加到 digitalocean 上的 sql 文件中并且它有效【参考方案7】:

只需添加set sql_require_primary_key = off 像这样

到您的 SQL 文件。

【讨论】:

设置 sql_require_primary_key =off; DigitalOcean ManagedDatabases 中不允许此 sis。【参考方案8】:

将此行添加到您的迁移文件中。 $table->increments('aid');

【讨论】:

【参考方案9】:

根据 MySQL 文档中这个系统变量的用途是

为了避免复制性能问题:“启用此变量有助于避免在表没有主键时可能发生的基于行的复制中的性能问题。”

恕我直言,您的问题有两种可能的选择;

向此表和迁移中的每个表添加主键,包括临时表。这个更好,我认为这样做更方便,因为每个表都有主键没有缺点。

创建新表或更改现有表结构的语句是否强制要求表具有primary key。

更改您的提供商,因为根据here“我们仅支持 MySQL v8。”

这里还有bug report

【讨论】:

【参考方案10】:

启用后,sql_require_primary_key 具有以下效果:

    尝试创建没有主键的新表失败并出现错误。这包括 CREATE TABLE ... LIKE。它还包括 CREATE TABLE ... SELECT,除非 CREATE TABLE 部分包含主键定义。 尝试从现有表中删除主键失败并出现错误,但允许删除主键并在同一 ALTER TABLE 语句中添加主键除外。

即使表还包含 UNIQUE NOT NULL 索引,删除主键也会失败。

    尝试导入没有主键的表失败并出现错误。

默认值为 OFF ,但在您的情况下,您需要从 ON 设置 OFF

IMPORTANT LINK

HOW TO SET

【讨论】:

@Michal 你觉得这个答案有帮助吗,然后请标记为答案或投赞成票

以上是关于无法创建或更改没有主键的表 - Laravel DigitalOcean 托管数据库的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy Automap不为没有主键的表创建类

是否可以在柴油中使用没有主键的表?锈

Sql Server中的游标最好只能用于有主键或唯一键的表

具有多列主键的 Laravel 模型

如何在SQL Server中获取具有复合主键的表列表?

复合键的 Laravel 验证