Confluence 에 심각한 보안 취약점이 발견되었으니 사용자분들은 업그레이드 하세요.!
 
1
0
-1

안녕하세요. 질문 드려봅니다.

public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id')->unsigned()->index();
$table->string('title');
$table->text('content');
$table->timestamps();

$table->foreign('user_id')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
});
}

위의 마이그레이션 파일을 작성후 php artisan migrate 명령을 날리면 아래와 같은 에러가 발생 합니다.

Illuminate\Database\QueryException : SQLSTATE[HY000]: General error: 100 5 Can't create table `myapp`.`#sql-3008_4d` (errno: 150 "Foreign key constra int is incorrectly formed") (SQL: alter table `articles` add constraint `art icles_user_id_foreign` foreign key (`user_id`) references `users` (`id`) on delete cascade)

1 PDOException::("SQLSTATE[HY000]: General error: 1005 Can't create tabl e `myapp`.`#sql-3008_4d` (errno: 150 "Foreign key constraint is incorrectly formed")")

2 PDOStatement::execute()

위의 내용은 "라라벨로배우는 실전 PHP웹프로그래밍"의 83페이지 내용 입니다. 왜 위와같은 에러가 발생 하는지 궁금 합니다. 책에선 이상 없다고 진행이 되서요 ;;


    CommentAdd your comment...

    2 answers

    1.  
      1
      0
      -1

      예 user_id 컬럼을 bigInteger()로 해 보실래요. 

      ---

      모바일이라 짧게 답변 드렸는데, 해결되었기를 바랍니다.

      Schema::create('articles', function (Blueprint $table) {
          $table->unsignedBigInteger('user_id')->index();
          // ...
      });

      라라벨 버전 문제입니다. 추적해보니, 라라벨 5.8부터 users.id 컬럼을 bigInteger(==long, 2^64)을 쓰기 시작했네요.


      혹시 여전히 문제가 해결되지 않았다면, 외래키/참조키를 맺는 테이블의 인코딩 및 문자셋도 확인해 보시기 바랍니다. 정수형이라 크게 무관해 보이기는 하지만, utf8mb4를 썼다면 연결되는 모든 테이블들이 같은 인코딩/문자셋으로 선언되어야 문제없을 것 같아요.

        CommentAdd your comment...
      1.  
        1
        0
        -1

        9장까지 진행하셨다면, 10장을 시작할 때 데이터베이스 상태는 아래와 같습니다.

        $ mysql
        # Welcome to the MySQL monitor.  Commands end with ; or \g.
        # Your MySQL connection id is 20
        # Server version: 5.7.26-0ubuntu0.16.04.1 (Ubuntu)
        # 
        # Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
        # 
        # Oracle is a registered trademark of Oracle Corporation and/or its
        # affiliates. Other names may be trademarks of their respective
        # owners.
        # 
        # Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
        
        mysql> use myapp;
        # Database changed
        
        mysql> show tables;
        # +-----------------+
        # | Tables_in_myapp |
        # +-----------------+
        # | migrations      |
        # | password_resets |
        # | users           |
        # +-----------------+
        # 3 rows in set (0.00 sec)
        
        mysql> describe users;
        # +----------------+------------------+------+-----+---------+----------------+
        # | Field          | Type             | Null | Key | Default | Extra          |
        # +----------------+------------------+------+-----+---------+----------------+
        # | id             | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
        # | name           | varchar(255)     | NO   |     | NULL    |                |
        # | email          | varchar(255)     | NO   | UNI | NULL    |                |
        # | password       | varchar(60)      | NO   |     | NULL    |                |
        # | remember_token | varchar(100)     | YES  |     | NULL    |                |
        # | created_at     | timestamp        | YES  |     | NULL    |                |
        # | updated_at     | timestamp        | YES  |     | NULL    |                |
        # +----------------+------------------+------+-----+---------+----------------+
        # 7 rows in set (0.00 sec)


        articles 테이블에 대한 스키마 마이그레이션을 실행하기 전에 아래와 같이 --pretend 옵션을 붙였을 때, 아래처럼 출력되는 지 확인해주세요.

        ~/myapp(master) $ php artisan migrate --pretend
        # CreateArticlesTable: create table `articles` (`id` int unsigned not null auto_increment primary key, `user_id` int unsigned not null, `title` varchar(255) not null, `content` text not null, `created_at` timestamp null, `updated_at` timestamp null) default character set utf8 collate utf8_unicode_ci
        # CreateArticlesTable: alter table `articles` add constraint `articles_user_id_foreign` foreign key (`user_id`) references `users` (`id`) on delete cascade on update cascade
        # CreateArticlesTable: alter table `articles` add index `articles_user_id_index`(`user_id`)


        (질문에서 articles 테이블에서도 increments() 대신 bigIncrements()를 쓰셨는데요) 혹시 모르니, users.id 컬럼과 articles.user_id 컬럼의 타입도 비교해보시겠어요.

        1. 테렌

          안녕하세요. 답변 감사드립니다.

          현재 제 상태는 아래와 같습니다.


          show tables;


          describe users;


          php artisan migrate --pretend

          CreateArticlesTable: create table `articles` (`id` bigint unsigned not null auto_increment
          primary key, `created_at` timestamp null, `updated_at` timestamp null) default character
          set utf8mb4 collate 'utf8mb4_unicode_ci'


          users는 따로 건들진 않아서 자동으로 만들어진걸 보면 id 타입이 bigint로 되어 있네요.

          책의 82페이지 코드10-1 예제를 보면

          public function up()
          {
          Schema::create('articles', function (Blueprint $table) {
          $table->increments('id');
          $table->integer('user_id')->unsigned()->index();
          $table->string('title');
          $table->text('content');
          $table->timestamps();

          $table->foreign('user_id')->references('id')->on('users')
          ->onUpdate('cascade')->onDelete('cascade');
          });
          }


          이렇게 하라고 되어 있습니다.

          하지만 저상태로 실행하면 에러가 발생 합니다;


        2. 테렌

          만약 컬럼 타입이 달라서 생기는 문제라면 

          users 테이블의 컬럼 타입을 바꾸는것 보다는 

          새로 추가할 articles의 create 스키마에서 

          $table->integer('user_id')->unsigned()→index(); 로 하지말고 다르게 하는 방법은 없겠죠?


          라라벨에서 자동으로 생성한 users 테이블의 id 타입이 bigincrements 인데 이걸 바꾸는게

          맞는건가 좀 의구심이 들어서요;;

        CommentAdd your comment...