Knex: Não é possível adicionar restrição de chave estrangeira

Criado em 17 abr. 2014  ·  11Comentários  ·  Fonte: knex/knex

Ao executar uma migração com o código abaixo, recebo a mensagem "Não é possível adicionar restrição de chave estrangeira". Alguém me indica a direção certa?

exports.up = function(knex, Promise) {
    var defer=Promise.defer();

    knex.schema.createTable('User',function(table){

        //--Create User Table
        table.increments('UserId').primary();
        table.string('username');
        table.string('email',60);
        table.string('password',65);
        table.timestamps();

    })
    .then(function(){
        return knex.schema.createTable('Comment',function(table){

            //--Create Comment Table
            table.increments('CommentId').primary();
            table.string('Comment');

            table.integer('UserId',11).inTable('User').references('UserId');

        });     
    })
    .then(function(){

            defer.resolve();
    });


    return defer.promise;

};

exports.down = function(knex, Promise) {

};  

Comentários muito úteis

Como um FYI para futuras pessoas lendo isso:
table.integer('UserId',11).unsigned().inTable('User').references('UserId');
é agora
table.integer('UserId',11).unsigned().references('UserId').inTable('User');

Todos 11 comentários

Supondo que você esteja usando mysql, você precisa especificar que UserId é .unsigned()

Você também não deve precisar desse adiamento lá, você pode apenas retornar o knex.schema.createTable .

exports.up = function(knex, Promise) {
  return knex.schema.createTable('User',function (table){ 
      table.increments('UserId').primary();
      table.string('username');
      table.string('email',60);
      table.string('password',65);
      table.timestamps();
  })
  .then(function () {
    return knex.schema.createTable('Comment',function(table){
      table.increments('CommentId').primary();
      table.string('Comment');
      table.integer('UserId',11).unsigned().inTable('User').references('UserId');
    });     
  });
};

Você quase nunca precisará Promise.defer .

Uau. Vocês são foda!! Funcionou perfeitamente. Obrigado pela resposta rápida e pelas dicas sobre código mais limpo :)

Você entendeu! Você pode achar mais fácil apenas dividir campos de dados/pk e referências fk em duas migrações. A alternativa é o que você fez aqui, mas lembre-se de que você também precisa garantir a ordem nas reversões.

Na versão em breve, você poderá encadear todas as chamadas de esquema e garantir que elas sejam executadas em sequência:

exports.up = function(knex, Promise) {
  return knex.schema.createTable('User', function(table){ 
      table.increments('UserId').primary();
      table.string('username');
      table.string('email',60);
      table.string('password',65);
      table.timestamps();
  }).createTable('Comment',function(table){
      table.increments('CommentId').primary();
      table.string('Comment');
      table.integer('UserId',11).unsigned().inTable('User').references('UserId');  
  });
};

migrando para baixo:

exports.down = function(knex, Promise) {
  return knex.schema.dropTable('Comment').dropTable('User');
};

Como um FYI para futuras pessoas lendo isso:
table.integer('UserId',11).unsigned().inTable('User').references('UserId');
é agora
table.integer('UserId',11).unsigned().references('UserId').inTable('User');

Obrigado @batman!

Tendo erros com notNullable(). Minhas chaves estrangeiras são sempre nulas:
EX 1:) table.integer('restaurant_id').unsigned().references('id').inTable('Restaurants');
A chave estrangeira ('restaurant_id") não corresponde ao 'id' na tabela 'Restaurants'. É simplesmente null, quando tentei usar:
EX2: ) table.integer('restaurant_id').unsigned().notNullable().references('id').inTable('Restaurants');
que lançou um erro (não é possível adicionar restrições de chave estrangeira).

Eu vi a criação de chave estrangeira deste formulário funcionar se essa chave estrangeira for uma string, mas com um número inteiro referenciando a chave primária ('id). É porque essa chave primária ('id') no pai não é do tipo inteiro e é do tipo padrão?
table.increments('id').primary();

Eu vi chaves estrangeiras funcionarem quando elas são do tipo String, mas ter uma referência de tipo inteiro para a chave primária ('id') em outra tabela gera um erro.

Quando eu uso EX1) Tudo parece funcionar, mas minha chave estrangeira não é incrementada automaticamente, é simplesmente nula o tempo todo. Também não consigo incrementá-lo manualmente usando uma função de modelo. Esse problema foi resolvido em algum lugar?

Obrigado,

atualizar:
Descubra, você simplesmente tem que adicionar a coluna inteira em uma linha separada de onde você a torna uma chave estrangeira.

table.integer('restaurant_id').unsigned();
          table.integer('location_id').unsigned();
          table.foreign('restaurant_id').references('Restaurants.id');
          table.foreign('location_id').references('Locations.id');

Pode valer a pena esclarecer nos documentos que o método .unsigned() deve ser usado ao definir chaves estrangeiras no MySQL. Eu tentei usar isso com Objection.js e quase desisti porque eu estava apenas começando e recebi um erro à primeira vista. Achei que ambos os frameworks estavam com bugs.

Achei que ambos os frameworks estavam com bugs.

@Juanpam não há necessidade de usá-los. PRs são bem-vindos. Boa sorte :)

@elhigu não quis ofender ninguém! Estou mesmo usando o framework 😄. Apenas pensei que para um novato, como eu, pode ser um problema comum, já que as relações são um recurso comumente usado em ORMs e construtores de consultas. Além disso, o MySQL é um RDBMS comum.

Eu não posso fazer um PR agora, mas se alguém estiver interessado, eu estava tentando usar o MySQL XAMPP enquanto criava as chaves estrangeiras. Acontece que ao usar o método .primary() o tipo de campo criado é INT(11) sem sinal e quando você cria o campo de referência usando .integer() o tipo de campo resultante é INT(11) assinado então a criação da chave estrangeira falha. A correção @tgriesser faz maravilhas, mas seria ainda melhor se você pudesse encontrar correções/problemas comuns como esses nos documentos.

De qualquer forma, ótimo trabalho!

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

zettam picture zettam  ·  3Comentários

nklhrstv picture nklhrstv  ·  3Comentários

tjwebb picture tjwebb  ·  3Comentários

rarkins picture rarkins  ·  3Comentários

PaulOlteanu picture PaulOlteanu  ·  3Comentários