Knex: No se puede agregar una restricción de clave externa

Creado en 17 abr. 2014  ·  11Comentarios  ·  Fuente: knex/knex

Cuando ejecuto una migración con el siguiente código, aparece el mensaje "No se puede agregar una restricción de clave externa". ¿Alguien me indica la dirección correcta?

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) {

};  

Comentario más útil

Como información para futuras personas que lean esto:
table.integer('UserId',11).unsigned().inTable('User').references('UserId');
es ahora
table.integer('UserId',11).unsigned().references('UserId').inTable('User');

Todos 11 comentarios

Suponiendo que esté usando mysql, debe especificar que UserId es .unsigned()

Tampoco debería necesitar ese aplazamiento allí, simplemente puede devolver el 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');
    });     
  });
};

Casi nunca necesitarás Promise.defer .

Guau. ¡¡Ustedes molan!! Funcionó perfectamente. Gracias por la rápida respuesta y los consejos sobre un código más limpio :)

¡Lo tienes! Puede que le resulte más fácil simplemente dividir los campos de datos/pk y las referencias de fk en dos migraciones. La alternativa es lo que ha hecho aquí, pero tenga en cuenta que también debe garantizar el orden en las reversiones.

En la próxima versión, podrá encadenar todas las llamadas de esquema y se garantizará que se ejecuten en secuencia:

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 hacia abajo:

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

Como información para futuras personas que lean esto:
table.integer('UserId',11).unsigned().inTable('User').references('UserId');
es ahora
table.integer('UserId',11).unsigned().references('UserId').inTable('User');

¡Gracias @batman!

Tener errores con notNullable(). Mis claves foráneas siempre son nulas:
EJ 1 :) table.integer('restaurant_id').unsigned().references('id').inTable('Restaurants');
La clave externa ('restaurant_id") no coincide con la 'id' en la tabla 'Restaurantes'. Es simplemente nulo, cuando intenté usar:
EX2: ) table.integer('restaurant_id').unsigned().notNullable().references('id').inTable('Restaurants');
que arrojó un error (no se pueden agregar restricciones de clave externa).

He visto que la creación de clave externa de este formulario funciona si esa clave externa es una cadena, pero con un número entero que hace referencia a la clave principal ('id). ¿Es porque esa clave principal ('id') en el padre no es de tipo entero y es de tipo predeterminado?
table.increments('id').primary();

He visto que las claves externas funcionan cuando son de tipo String, pero tener una referencia de tipo entero a la clave principal ('id') en otra tabla genera un error.

Cuando uso EX1) Todo parece funcionar, pero mi clave externa no se incrementa automáticamente, simplemente es nula todo el tiempo. Tampoco puedo incrementarlo manualmente usando una función de modelo. ¿Este problema se resolvió en alguna parte?

Gracias,

actualizar:
Descúbralo, simplemente tiene que agregar la columna entera en una línea separada de donde la convierte en una clave externa.

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

Puede valer la pena aclarar en los documentos que el método .unsigned() debe usarse al definir claves externas en MySQL. Intenté usar esto con Objection.js y casi me doy por vencido porque recién estaba comenzando y recibí un error a primera vista. Pensé que ambos marcos tenían errores.

Pensé que ambos marcos tenían errores.

@Juanpam no hay necesidad de usarlos. Sin embargo, las relaciones públicas son bienvenidas. Buena suerte :)

@elhigu ¡No quise ofender a nadie! De hecho, estoy usando el marco 😄. Solo pensé que para un recién llegado, como yo, puede ser un problema común, ya que las relaciones son una característica que se usa comúnmente en los ORM y los generadores de consultas. Además, MySQL es un RDBMS común.

No puedo hacer una PR en este momento, pero si alguien está interesado, estaba tratando de usar XAMPP MySQL mientras creaba las claves externas. Resulta que cuando se usa el método .primary(), el tipo de campo creado es INT(11) sin firmar y cuando crea el campo de referencia usando .integer(), el tipo de campo resultante es INT(11) firmado, por lo que la creación de la clave externa falla. @tgriesser fix funciona de maravilla, pero sería aún mejor si pudiera encontrar soluciones/problemas comunes como estos en los documentos.

De todos modos, gran trabajo!

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

lanceschi picture lanceschi  ·  3Comentarios

tjwebb picture tjwebb  ·  3Comentarios

koskimas picture koskimas  ·  3Comentarios

aj0strow picture aj0strow  ·  3Comentarios

arconus picture arconus  ·  3Comentarios