Bei Verwendung der Migrationsfunktion des Dienstprogramms sequelize cli
können neue Fremdschlüssel durch Hinzufügen einer neuen Spalte erstellt werden. Beim Versuch, mehrere Fremdschlüssel für dasselbe Modell zu erstellen, tritt jedoch ein Fehler auf. Die Fremdschlüssel-Namen, die durch Ausführen von sequelize db:migrate
erzeugt werden, sind nicht unterscheidungskräftig. Der DB-Engine setzt voraus, dass alle Fremdschlüssel sind ein eindeutiger Name zugewiesen, aber SequelizeJS scheinen initally alle Fremdschlüssel zu nennen wie:SequelizeJS-Migration: Hinzufügen mehrerer Fremdschlüssel zum gleichen Modell?
// Excerpt from sequelize/lib/dialects/mysql/query-generator.js
// Line 195
{fkName: this.quoteIdentifier(attrName + '_foreign_idx')}
und dies wird natürlich produzieren gleiche Schlüssel, wenn die Indexnummer idx
nicht korrekt erhöht .
Irgendwo in der Sequelize Bibliothek, der idx
Teil _foreign_idx
muss durch einen tatsächlichen numerischen Wert ersetzt werden, wenn Modelle mit db.sync()
Initialisierung, aber ich habe nicht in der Lage gewesen, wo zu identifizieren. Ich habe auch verifiziert, dass Sequelize tatsächlich den Indexwert bei der Verwendung von db.sync()
erhöht, indem die Fremdschlüssel in einer anderen Datenbank untersucht werden. In dieser Datenbank wurden die Fremdschlüssel genannt als _ibfk_1
, _ibfk_2
, .., _ibfk_n
- Hat jemand ein Problem festgestellt, wo der Fremdschlüsselgenerator identische Namen erzeugt?
- Hat jemand einen Vorschlag, wie dies bei der Verwendung von Sequelize-Migrationen vermieden/gelindert werden kann?
Ich verwende MySQL als Datenbank-Engine, aber der Fremdschlüssel Name Generator folgt die gleiche Prozedur für zB. auch postgre, soweit ich in der Lage war, den Sequelize-Quellcode zu interpretieren.
Beispiel
Die folgende Migration wird drei Modelle erstellen und die Beziehungen zwischen ihnen mit der Funktion addColumn Funktion von sequelize cli
erstellen.
Die Skriptmodelle ein Szenario, in dem sowohl ein Trainer und ein Team von einigen Sponsor gesponsert wird. In diesem Modell möchten wir sowohl in unserem Trainer- als auch in unserem Teammodell auf die Sponsor-ID verweisen. Leider werden dadurch zwei Fremdschlüssel mit dem Namen sponsorId_foreign_idx
(einer im Bus und einer im Teammodell) erstellt und die Fremdschlüssel haben keine eindeutigen Namen. Dies würde jedoch vermieden werden, wenn idx
um einen inkrementierten Wert geändert würde.
var Promise = require('bluebird');
module.exports = {
up: function (queryInterface, Sequelize) {
return Promise
.join(
queryInterface
.createTable('sponsor', {
id: {
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
}),
queryInterface
.createTable('team', {
id: {
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
}),
queryInterface
.createTable('coach', {
id: {
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
})
)
.then(function(){
return queryInterface
.addColumn('team', 'sponsorId', {
type: Sequelize.INTEGER,
references: { model: 'sponsor', key: 'id' }
})
.then(function(){
return queryInterface
.addColumn('coach', 'sponsorId', {
type: Sequelize.INTEGER,
references: { model: 'sponsor', key: 'id' }
});
});
});
},
down: function (queryInterface, Sequelize) {
return queryInterface.dropAllTables();
}
};
komplette Fehlerprotokoll Dump
{ SequelizeBaseError: ER_DUP_KEY: Can't write; duplicate key in table '#sql-3b7_f1'
at Query.formatError (/home/usr/me/node_modules/sequelize/lib/dialects/mysql/query.js:175:14)
at Query._callback (/home/usr/me/node_modules/sequelize/lib/dialects/mysql/query.js:49:21)
at Query.Sequence.end (/home/usr/me/node_modules/mysql/lib/protocol/sequences/Sequence.js:86:24)
at Query.ErrorPacket (/home/usr/me/node_modules/mysql/lib/protocol/sequences/Query.js:94:8)
at Protocol._parsePacket (/home/usr/me/node_modules/mysql/lib/protocol/Protocol.js:280:23)
at Parser.write (/home/usr/me/node_modules/mysql/lib/protocol/Parser.js:74:12)
at Protocol.write (/home/usr/me/node_modules/mysql/lib/protocol/Protocol.js:39:16)
at Socket.<anonymous> (/home/usr/me/node_modules/mysql/lib/Connection.js:109:28)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at Socket.Readable.push (_stream_readable.js:134:10)
at TCP.onread (net.js:551:20)
name: 'SequelizeDatabaseError',
message: 'ER_DUP_KEY: Can\'t write; duplicate key in table \'#sql-3b7_f1\'',
parent:
{ Error: ER_DUP_KEY: Can't write; duplicate key in table '#sql-3b7_f1'
at Query.Sequence._packetToError (/home/usr/me/node_modules/mysql/lib/protocol/sequences/Sequence.js:52:14)
at Query.ErrorPacket (/home/usr/me/node_modules/mysql/lib/protocol/sequences/Query.js:83:18)
at Protocol._parsePacket (/home/usr/me/node_modules/mysql/lib/protocol/Protocol.js:280:23)
at Parser.write (/home/usr/me/node_modules/mysql/lib/protocol/Parser.js:74:12)
at Protocol.write (/home/usr/me/node_modules/mysql/lib/protocol/Protocol.js:39:16)
at Socket.<anonymous> (/home/usr/me/node_modules/mysql/lib/Connection.js:109:28)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at Socket.Readable.push (_stream_readable.js:134:10)
at TCP.onread (net.js:551:20)
--------------------
at Protocol._enqueue (/home/usr/me/node_modules/mysql/lib/protocol/Protocol.js:141:48)
at Connection.query (/home/usr/me/node_modules/mysql/lib/Connection.js:214:25)
at /home/usr/me/node_modules/sequelize/lib/dialects/mysql/query.js:40:21
at Promise._execute (/home/usr/me/node_modules/bluebird/js/release/debuggability.js:300:9)
at Promise._resolveFromExecutor (/home/usr/me/node_modules/bluebird/js/release/promise.js:481:18)
at new Promise (/home/usr/me/node_modules/bluebird/js/release/promise.js:77:14)
at Query.run (/home/usr/me/node_modules/sequelize/lib/dialects/mysql/query.js:39:17)
at /home/usr/me/node_modules/sequelize/lib/sequelize.js:849:20
at /home/usr/me/node_modules/retry-as-promised/index.js:40:21
at Promise._execute (/home/usr/me/node_modules/bluebird/js/release/debuggability.js:300:9)
at Promise._resolveFromExecutor (/home/usr/me/node_modules/bluebird/js/release/promise.js:481:18)
at new Promise (/home/usr/me/node_modules/bluebird/js/release/promise.js:77:14)
at retryAsPromised (/home/usr/me/node_modules/retry-as-promised/index.js:30:10)
at /home/usr/me/node_modules/sequelize/lib/sequelize.js:848:12
at tryCatcher (/home/usr/me/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/usr/me/node_modules/bluebird/js/release/promise.js:510:31)
code: 'ER_DUP_KEY',
errno: 1022,
sqlState: '23000',
index: 0,
sql: 'ALTER TABLE `coach` ADD `sponsorId` INTEGER, ADD CONSTRAINT `sponsorId_foreign_idx` FOREIGN KEY (`sponsorId`) REFERENCES `sponsor` (`id`);' },
original:
{ Error: ER_DUP_KEY: Can't write; duplicate key in table '#sql-3b7_f1'
at Query.Sequence._packetToError (/home/usr/me/node_modules/mysql/lib/protocol/sequences/Sequence.js:52:14)
at Query.ErrorPacket (/home/usr/me/node_modules/mysql/lib/protocol/sequences/Query.js:83:18)
at Protocol._parsePacket (/home/usr/me/node_modules/mysql/lib/protocol/Protocol.js:280:23)
at Parser.write (/home/usr/me/node_modules/mysql/lib/protocol/Parser.js:74:12)
at Protocol.write (/home/usr/me/node_modules/mysql/lib/protocol/Protocol.js:39:16)
at Socket.<anonymous> (/home/usr/me/node_modules/mysql/lib/Connection.js:109:28)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at Socket.Readable.push (_stream_readable.js:134:10)
at TCP.onread (net.js:551:20)
--------------------
at Protocol._enqueue (/home/usr/me/node_modules/mysql/lib/protocol/Protocol.js:141:48)
at Connection.query (/home/usr/me/node_modules/mysql/lib/Connection.js:214:25)
at /home/usr/me/node_modules/sequelize/lib/dialects/mysql/query.js:40:21
at Promise._execute (/home/usr/me/node_modules/bluebird/js/release/debuggability.js:300:9)
at Promise._resolveFromExecutor (/home/usr/me/node_modules/bluebird/js/release/promise.js:481:18)
at new Promise (/home/usr/me/node_modules/bluebird/js/release/promise.js:77:14)
at Query.run (/home/usr/me/node_modules/sequelize/lib/dialects/mysql/query.js:39:17)
at /home/usr/me/node_modules/sequelize/lib/sequelize.js:849:20
at /home/usr/me/node_modules/retry-as-promised/index.js:40:21
at Promise._execute (/home/usr/me/node_modules/bluebird/js/release/debuggability.js:300:9)
at Promise._resolveFromExecutor (/home/usr/me/node_modules/bluebird/js/release/promise.js:481:18)
at new Promise (/home/usr/me/node_modules/bluebird/js/release/promise.js:77:14)
at retryAsPromised (/home/usr/me/node_modules/retry-as-promised/index.js:30:10)
at /home/usr/me/node_modules/sequelize/lib/sequelize.js:848:12
at tryCatcher (/home/usr/me/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/usr/me/node_modules/bluebird/js/release/promise.js:510:31)
code: 'ER_DUP_KEY',
errno: 1022,
sqlState: '23000',
index: 0,
sql: 'ALTER TABLE `coach` ADD `sponsorId` INTEGER, ADD CONSTRAINT `sponsorId_foreign_idx` FOREIGN KEY (`sponsorId`) REFERENCES `sponsor` (`id`);' },
sql: 'ALTER TABLE `coach` ADD `sponsorId` INTEGER, ADD CONSTRAINT `sponsorId_foreign_idx` FOREIGN KEY (`sponsorId`) REFERENCES `sponsor` (`id`);' }
Haben Sie jemals eine geeignete Problemumgehung gefunden? Sieht so aus [war in ihrer v4-Entwicklung behoben] (https://github.com/sequelize/sequelize/pull/6008), aber nicht in v3. –
Ich habe versucht, zugeschnittene SQL-Abfragen zu schreiben, indem ich die Schnittstelle benutze, die bei 'queryInterface.sequelize.query' exponiert ist ([die Existenz wird auf der github-Seite erwähnt]) (https://github.com/sequelize/cli)) – jorgenkg