【问题标题】:How to create composite primary key by using Migration in Yii2?Yii2中如何使用Migration创建复合主键?
【发布时间】:2015-11-15 04:35:54
【问题描述】:

我尝试运行yii migrate,但它显示以下错误:

create table news-cate ...Exception: SQLSTATE[42000]: Syntax error or access violation: 1075 Incorrect table definition; there can be only one auto column and it must be defined as a key
The SQL being executed was: CREATE TABLE `news-cate` (
        `news-id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
        `cate-id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY

这是我的代码:

class m150821_083020_create_newscate_table extends Migration
{
    public function safeUp()
    {
        $this->createTable('news-cate', [
            'news-id' => $this->primaryKey(),
            'cate-id' => $this->primaryKey(),
        ]);
        $this->addForeignKey("fk_news_cate_nid", "news-cate", "news-id", "news", "id", "RESTRICT", "CASCADE");
        $this->addForeignKey("fk_news_cate_cid", "news-cate", "cate-id", "category", "id", "RESTRICT", "CASCADE");
    }

    public function safeDown()
    {
        echo "m150821_083020_create_newscate_table cannot be reverted.\n";
        $this->dropTable("news-cate");
        return false;
    }
}

那么如何在 Yii2 中使用 Migration 创建复合主键呢?

【问题讨论】:

    标签: sql yii2 database-migration


    【解决方案1】:

    最简单的方法

    理想情况下,您要为两个表创建联结。您可以使用 Yii 命令行通过一行代码创建迁移:

    php yii migrate/create create_junction_table_for_post_and_tag_tables --fields="created_at:bigInteger"
    

    它会生成:

    /**
     * Handles the creation for table `post_tag`.
     * Has foreign keys to the tables:
     *
     * - `post`
     * - `tag`
     */
    class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migration
    {
        /**
         * @inheritdoc
         */
        public function up()
        {
            $this->createTable('post_tag', [
                'post_id' => $this->integer(),
                'tag_id' => $this->integer(),
                'created_at' => $this->dateTime(),
                'PRIMARY KEY(post_id, tag_id)',
            ]);
    
            // creates index for column `post_id`
            $this->createIndex(
                'idx-post_tag-post_id',
                'post_tag',
                'post_id'
            );
    
            // add foreign key for table `post`
            $this->addForeignKey(
                'fk-post_tag-post_id',
                'post_tag',
                'post_id',
                'post',
                'id',
                'CASCADE'
            );
    
            // creates index for column `tag_id`
            $this->createIndex(
                'idx-post_tag-tag_id',
                'post_tag',
                'tag_id'
            );
    
            // add foreign key for table `tag`
            $this->addForeignKey(
                'fk-post_tag-tag_id',
                'post_tag',
                'tag_id',
                'tag',
                'id',
                'CASCADE'
            );
        }
    
        /**
         * @inheritdoc
         */
        public function down()
        {
            // drops foreign key for table `post`
            $this->dropForeignKey(
                'fk-post_tag-post_id',
                'post_tag'
            );
    
            // drops index for column `post_id`
            $this->dropIndex(
                'idx-post_tag-post_id',
                'post_tag'
            );
    
            // drops foreign key for table `tag`
            $this->dropForeignKey(
                'fk-post_tag-tag_id',
                'post_tag'
            );
    
            // drops index for column `tag_id`
            $this->dropIndex(
                'idx-post_tag-tag_id',
                'post_tag'
            );
    
            $this->dropTable('post_tag');
        }
    }
    

    表结构是这样的:

    +------------+------------+------+-----+---------+-------+
    | Field      | Type       | Null | Key | Default | Extra |
    +------------+------------+------+-----+---------+-------+
    | post_id    | int(11)    | NO   | PRI | NULL    |       |
    | tag_id     | int(11)    | NO   | PRI | NULL    |       |
    | created_at | bigint(20) | YES  |     | NULL    |       |
    +------------+------------+------+-----+---------+-------+
    

    请查看下面提到的 URL 以供参考:

    http://www.yiiframework.com/doc-2.0/guide-db-migrations.html

    【讨论】:

      【解决方案2】:

      更新

      从 yii 2.06 版开始,您可以使用新的架构生成器:

      <?php
      use yii\db\Migration;
      ...
      $this->createTable('news-cate', [
          'news-id' => $this->integer()->notNull(),
          'cate-id' => $this->integer()->notNull(),
      ]);
      $this->addPrimaryKey('news-cate_pk', 'news-cate', ['news-id', 'cate-id']);
      ...
      ?>
      

      原始答案

      建表时不要添加主键,只声明类型:

      use yii\db\Schema;
      
      ,,,
      
      $this->createTable('news-cate', [
          'news-id' => Schema::TYPE_INTEGER . ' NOT NULL',
          'cate-id' => Schema::TYPE_INTEGER . ' NOT NULL',
      ]);
      

      之后你可以像这样添加复合主键:

      $this->addPrimaryKey('news-cate_pk', 'news-cate', ['news-id', 'cate-id']);
      

      对于多列,addPrimaryKey() 方法中允许使用数组。

      这比编写原始 sql 更好。

      【讨论】:

      • 这也是创建非整数类型主键的最佳方式。
      • 这是否也会为复合主键创建唯一索引?
      【解决方案3】:

      试试这个方法

      public function safeUp()
      {
         $this->createTable('news-cate', [
              'news-id' =>'int NOT NULL',
              'cate-id' =>'int NOT NULL',
              'PRIMARY KEY (news-id,cate-id)'
            ]);
          $this->addForeignKey("fk_news_cate_nid", "news-cate", "news-id", "news", "id", "RESTRICT", "CASCADE");
          $this->addForeignKey("fk_news_cate_cid", "news-cate", "cate-id", "category", "id", "RESTRICT", "CASCADE");
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多