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) {
};
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!
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');