При выполнении миграции с приведенным ниже кодом я получаю сообщение «Невозможно добавить ограничение внешнего ключа». Кто-нибудь указывает мне в правильном направлении?
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) {
};
Предполагая, что вы можете использовать mysql, вам нужно указать, что UserId
равно .unsigned()
Вам также не нужна эта отсрочка, вы можете просто вернуть 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');
});
});
};
Вам почти никогда не понадобится Promise.defer
.
Вот это да. Вы, ребята, рок!! Работал отлично. Спасибо за быстрый ответ и советы по более чистому коду :)
Ты получил это! Возможно, вам будет проще просто разделить поля data/pk и ссылки fk на две миграции. Альтернативой является то, что вы сделали здесь, но имейте в виду, что вам также необходимо обеспечить порядок на откатах.
В версии, которая скоро появится, вы сможете связать все вызовы схемы, и они гарантированно будут выполняться последовательно:
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');
});
};
миграция вниз:
exports.down = function(knex, Promise) {
return knex.schema.dropTable('Comment').dropTable('User');
};
В качестве информации для будущих людей, читающих это:
table.integer('UserId',11).unsigned().inTable('User').references('UserId');
сейчас
table.integer('UserId',11).unsigned().references('UserId').inTable('User');
Спасибо, @batman!
Возникли ошибки с notNullable(). Мои внешние ключи всегда нулевые:
ПРИМЕР 1 :) table.integer('restaurant_id').unsigned().references('id').inTable('Restaurants');
Внешний ключ («restaurant_id») не соответствует «id» в таблице «Рестораны». Он просто равен нулю, когда я пытался использовать:
EX2: ) table.integer('restaurant_id').unsigned().notNullable().references('id').inTable('Restaurants');
который вызвал ошибку (не может добавить ограничения внешнего ключа).
Я видел, как создание внешнего ключа этой формы работает, если этот внешний ключ является строкой, но с целым числом, ссылающимся на первичный ключ ('id). Это потому, что этот первичный ключ ('id') в родительском элементе не имеет целочисленного типа и имеет тип по умолчанию?
table.increments('id').primary();
Я видел, как внешние ключи работают, когда они имеют тип String, но наличие ссылки целочисленного типа на первичный ключ («id») в другой таблице вызывает ошибку.
Когда я использую EX1), кажется, что все работает, но мой внешний ключ не увеличивается автоматически, он просто равен нулю все время. Я также не могу увеличить его вручную, используя функцию модели. Где-то решился этот вопрос?
Спасибо,
Обновить:
Выясните это, вам просто нужно добавить целочисленный столбец в отдельную строку, где вы делаете его внешним ключом.
table.integer('restaurant_id').unsigned();
table.integer('location_id').unsigned();
table.foreign('restaurant_id').references('Restaurants.id');
table.foreign('location_id').references('Locations.id');
Возможно, стоит уточнить в документах, что метод .unsigned() следует использовать при определении внешних ключей в MySQL. Я пытался использовать это с Objection.js и почти сдался, потому что я только начинал и получил ошибку только на первый взгляд. Думал, что оба фреймворка глючат.
Думал, что оба фреймворка глючат.
@Juanpam не нужно их использовать. Хотя пиар приветствуется. Удачи :)
@elhigu Я не хотел никого обидеть! Я действительно использую фреймворк 😄. Просто подумал, что для новичка, такого как я, это может быть общей проблемой, поскольку отношения — это функция, обычно используемая в ORM и построителях запросов. Кроме того, MySQL является распространенной СУБД.
Я не могу сделать PR прямо сейчас, но если кому-то интересно, я пытался использовать XAMPP MySQL при создании внешних ключей. Оказывается, при использовании метода .primary() тип созданного поля — INT(11) без знака, а когда вы создаете ссылочное поле с помощью .integer(), результирующий тип поля — INT(11) со знаком, поэтому создание внешнего ключа завершается ошибкой. Исправление @tgriesser творит чудеса, но было бы еще лучше, если бы вы могли найти общие исправления/проблемы, подобные этим, в документации.
В любом случае, отличная работа!
Самый полезный комментарий
В качестве информации для будущих людей, читающих это:
table.integer('UserId',11).unsigned().inTable('User').references('UserId');
сейчас
table.integer('UserId',11).unsigned().references('UserId').inTable('User');