Knex: 耇数のPKを䜜成するこずはできたせん.primaryで.incrementsをミックスむン

䜜成日 2014幎07月18日  Â·  31コメント  Â·  ゜ヌス: knex/knex

次のMySQLダンプに基づいおテヌブルを䜜成したいず思いたす。

CREATE TABLE `my_table` (
  `cmdId` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `deviceId` char(16) NOT NULL,
  `fnNumber` int(10) unsigned DEFAULT NULL,
  `chNumber` int(10) unsigned DEFAULT NULL,
  `cmd` varchar(50) DEFAULT NULL,
  `cmdDate` datetime DEFAULT NULL,
  `delivered` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`cmdId`,`deviceId`),
  KEY `deviceId` (`deviceId`),
  CONSTRAINT `tblcommands_ibfk_1` FOREIGN KEY (`deviceId`) REFERENCES `second_table` (`deviceId`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

私のknexは次のようになりたす

knex.schema.createTable('my_table', function(t) {
    t.primary(['cmdId', 'deviceId']);
    t.increments('cmdId');
    t.string('deviceId', 16).notNullable().references('second_table.deviceId');
    t.integer('fnNumber').unsigned();
    t.integer('chNumber').unsigned();
    t.string('cmd96', 50);
    t.dateTime('cmdDate');
    t.boolean('delivered');
});

ただし、䞻キヌには問題がありたす。 次の゚ラヌが発生したす

Error: Multiple primary key defined

incrementsメ゜ッドはすでにPKを䜜成し、 primaryメ゜ッドは別のPKを䜜成しお゚ラヌを匕き起こすず思いたす。

この圢匏のテヌブルを実珟するこずは可胜ですか

最も参考になるコメント

たたは、で自動むンクリメント列を䜜成できたす

table.specificType('myid','serial');

Postgresqlの堎合のみ

しかし、 table.increments().primary()で手動で指定した堎合にのみ、 table.increments()がPKを䜜成する方がはるかに優れおいるず思いたす。

党おのコメント31件

いいえ、しかしおそらくそうあるべきです。 私はこれに぀いお䜕かを調べたす。

https://github.com/tgriesser/knex/blob/master/lib/dialects/mysql/schema/column.js#L30によるず

ColumnCompiler_MySQL.prototype.increments = 'int unsigned not null auto_increment primary key';

したがっお、 .increments()はPKを䜜成したす。 匷すぎる行動ではないですか PKなしでAUTO_INCREMENT列を䜜成する方が良いず思いたすので、次のようにしたす。

int unsigned not null auto_increment

そしお、PKを䜜成するには、 .primary()を呌び出す必芁がありたす。

table.increments('id').primary();

AUTO_INCREMENT列で倚くのPKを䜜成できたす。

私が今䜿っおいるworkaroudずしお

table.primary(['cmdId', 'deviceId']);
table.integer('cmdId').notNullable();
table.string('deviceId', 16).notNullable().references('second_table.deviceId');

そしおthenコヌルバックで

knex.schema.raw('ALTER TABLE my_table MODIFY cmdId INT UNSIGNED AUTO_INCREMENT');

同様の問題がありたす。䞻キヌではなく.increments()を䜿甚したいず思いたす。 私の堎合、それはパフォヌマンス䞊の理由によるものです。 むンデックスのない぀たり䞻キヌのないテヌブルを䜜成し、そこに倚くの行を挿入しおから、自動むンクリメント列にむンデックスを远加したいず思いたす。 これはよりパフォヌマンスが高く、実際にはPostgresのドキュメントhttp://www.postgresql.org/docs/9.4/static/populate.html#POPULATE-RM-INDEXESを参照で掚奚されおいたすが、珟圚のずころ、これを行うこずは䞍可胜のようです。 knex。

私も同様の問題に遭遇しおいるようです。 次のようなテヌブルを䜜成できたせん。

knex.schema.createTable("numeric_table", function (table) {
    table.integer("integer_key").primary;

   // Both increments & bigIncrements tries to create primary key.
    table.increments("increment_key");
    table.bigIncrements("big_increment_key");
});

ここで同じ問題.incrementsは、手動で䞻キヌを指定した堎合でも、䞻キヌを定矩しようずしたす

生のク゚リを䜿甚しお、䞻キヌなしで増分列を远加できたす。

exports.up = function (knex) {
  return Promise.all([
    knex.raw('alter table "my_table" add column "my_seq" bigserial'),
  ]);
};

exports.down = (knex) => {
  return Promise.all([
    knex.schema.table('my_table', (t) => {
      t.dropColumn('my_seq');
    }),
  ]);
};

たたは、で自動むンクリメント列を䜜成できたす

table.specificType('myid','serial');

Postgresqlの堎合のみ

しかし、 table.increments().primary()で手動で指定した堎合にのみ、 table.increments()がPKを䜜成する方がはるかに優れおいるず思いたす。

離れおみたせんか
increments: 'serial'
の代わりに
increments: 'serial primary key'

それの問題は䜕ですか

それでも同じ゚ラヌが発生したす。
IMHO .incrementsはPKを䜜成するべきではありたせん。

この問題に関するニュヌスはありたすか

同意したした-この問題をさたざたな方法で回避するこずは確かに可胜ですが、APIが䞻キヌにせずに自動むンクリメント列を䜜成するためのファヌストクラスのサポヌトを持っおいないのはかなり奇劙です。

そうは蚀っおも、これはただ修正されおいないず思いたす。これを最も賢明な方法で修正するこずは重倧な倉曎であり、メゞャヌバヌゞョンのバンプの䞀郚である必芁があるためです。

@zacronos
テヌブルを䜜成するずきに列で.primary()を䜿甚するず、結果はテヌブルを䜜成するための個別のク゚リず、䞻キヌを定矩するための別のalter tableク゚リになりたす。
MySQLたたはおそらく他のDBMSもでは、PKでなければauto_incremementフィヌルドを持぀こずはできないず思いたす。
したがっお、knexは䞻キヌを䜿甚しおテヌブルを䜜成したすが、テヌブルにはすでに1぀あるため、 alterで2぀の䞻キヌを定矩するこずはできたせん。
これを修正できれば、おそらく.incrementsはPKを䜜成したすが、他の列もすべお1぀のcreate tableク゚リでPKできるので、メゞャヌバヌゞョンのバンプはおそらく必芁ありたせん。

たたは、このために別の列タむプを远加し、䞋䜍互換性を損なわないように.incrementsをそのたたにしおおくこずもできたす。

@ amir-sknexがそのように動䜜する理由を説明しおいたす-サポヌトされおいるさたざたなDBMS間で同等の動䜜をしようずしおいるようです。 私は特にそれが奜きではありたせんが、少なくずも今は奇劙に芋えたせん。

あなたの提案の問題は、定矩䞊、テヌブルに耇数の䞻キヌを持぀こずができないずいうこずです。 耇数の列に1぀の耇合PKを蚭定できたすが、これは2぀の単䞀列PKを䜿甚する堎合ずは倧きく異なりたす。

したがっお、 .incrementsがPKを䜜成する堎合、他の列もPKずしおマヌクするこずを蚱可するこずはできたせん。 .incrementsに枡すこずができるオプションを䜜成しお、Postgresおよびそのような動䜜をサポヌトする他のDBMSで䞻キヌの動䜜を無効にするこずができたす。 䞋䜍互換性を損なうこずはなく、DBMS間の互換性も損なうこずがないため、おそらくこれが最善の解決策です。 私はただそれが奜きではなく、Postgresのデフォルトの動䜜を倉曎しお.incrementsもPKにならないようにしおいたすが、より簡単に受け入れられるPRになりたす。

誰かがそれらの線に沿っおPRを提出したいのなら、私はその賛成を䞻匵したいず思いたす。 :-)

@zacronos申し蚳ありたせんが、「耇数のPK」ずは、「耇数の列に1぀のPK」を意味したす。

䞊蚘のすべおのコメントに同意したす。 この動䜜は、耇合䞻キヌず非キヌの自動むンクリメント列を䜜成しようずしたずきに予期しないものでした。 これが実装されるのを芋るのは玠晎らしいこずです。

私もこの問題に盎面しおいたすが、 Postgres Postgresを䜿甚し、倖郚キヌずしおシリアルフィヌルドを䜿甚しおいる堎合、 Postgresシリアルフィヌルドのknex実装はincrements()これにより、デフォルトでそれらが䞻キヌになりたす。 postgresだけでなくsqlite3もビルドできるようにしたいので、生のknexク゚リを䜿甚するず、たたはのいずれかに制限されたす。 回避策の提案はありたすか

このスレッドはしばらくの間あたり泚目されおいたせん。 理想的な䞋䜍互換性のある゜リュヌションしたがっお、マむナヌリリヌスの䞀郚になる可胜性がありたすであるず私が思うこずを繰り返したいず思いたす。 .increments()に新しいオプションを远加したす。おそらくprimaryKey: falseです。 これが可胜なDBMSの堎合その機胜の䞻キヌ郚分を無効にしたす。

.increments()はデフォルトの動䜜を保持しおいるため、これは完党に䞋䜍互換性がありたす。

@zacronosコヌドを
https://github.com/DeedMob/knex/tree/master/src

ここで同じ問題。 別の䞻キヌを䜜成しようずするためにbigIncrements()を回避するには、生のク゚リを䜿甚する必芁がありたす。

回避策

table.bigincrements();
table.biginteger('other').notNullable();
table.dropPrimary();
table.primary(['id', 'other']);

このトピックに関する以前の調査を正しく理解しおいる堎合、䞀郚のDB぀たり、MySQLは䞻キヌでないずシリアルを䜜成できないため、knexは䞻キヌを厳密に匷制したすか そのような堎合、Postgresに関しおは䞋䜍互換性に぀いおあたり心配する必芁はありたせん。

MySQLナヌザヌは、それがプラむマリであるず期埅したす。
Postgresナヌザヌはそうしたせん。 _䞊蚘で明らかです_

このため、Postgresで䞻キヌを匷制しないように調敎しお倉曎ログに远加するのはかなり安党だず思いたす。 パッチずしおではなく、次のメゞャヌバヌゞョン甚です。

このため、Postgresで䞻キヌを匷制しないように調敎し、それを倉曎ログに远加するのはかなり安党だず思いたす。 パッチずしおではなく、次のメゞャヌバヌゞョン甚です。

postgresqlに぀いおも.primary()なしでtable.bigincrements('id')だけを曞くだけで垞に移行を曞いおきた䜕十人もの人々を知っおいたす。なぜなら、それは垞にそのように機胜しおいるからです。

䞻キヌを䜜成しないように指瀺するために䜿甚する必芁がある远加のオプションがありたしたが、そこにはないようです。 少なくずも、䞻キヌの䜜成をスキップするこずに぀いお、postgres / mysqlの実装に぀いおは䜕も芋぀かりたせんでした。

これは、移行時の䞋䜍互換性を損なう倧きな倉曎であり、これが発生するのを芋るのは嫌です。 この叀い移行APIにパッチを適甚し続ける堎合は、最初にバヌゞョン管理サポヌトを远加しお、すべおの人がすべおのknexバヌゞョンで叀い移行を修正できないようにする必芁がありたす移行コヌドの倉曎は、たったく同じように機胜するこずを確認するのが非垞に困難です自動テストなので、knexのナヌザヌコヌドでは非垞に脆匱な郚分です。

解決策はありたすか

これに関するニュヌスはありたすか

このスレッドはしばらくの間あたり泚目されおいたせん。 理想的な䞋䜍互換性のある゜リュヌションしたがっお、マむナヌリリヌスの䞀郚になる可胜性がありたすであるず私が思うこずを繰り返したいず思いたす。 .increments()に新しいオプションを远加したす。おそらくprimaryKey: falseです。 これが可胜なDBMSの堎合その機胜の䞻キヌ郚分を無効にしたす。

.increments()はデフォルトの動䜜を保持しおいるため、これは完党に䞋䜍互換性がありたす。

このような増分を䜿甚できたすか すべおのアップデヌト

調子はどう これは本圓に面倒です。特にMSSQLでは、PK制玄はデフォルトでは名前が付けられおいたせんが、「PK__requests__DD771E3CC0CD0A5E」のようになっおいるため、ドロップしおPKを䜜成するこずすらできたせん。
制玄の名前を指定するのは本圓ですが、incrementsでは機胜したせん

それでも䜕もありたせんか

.incrementsのオプションのパラメヌタも非垞に気に入っおいたす 生のク゚リは明らかに機胜する可胜性がありたすが、耇数の異なるDBたずえば、本番甚のmariadb、テスト甚のsqliteを実行する人にずっおは煩わしいものです。 これに関する曎新はありたすか すでにPRが行われおいるようですが、ちょっず黙っおいたしたか

もう䞀床蚀いたすが、1぀のプロゞェクトですでに3回必芁でした。

ここでも同じ問題がありたすが、PKシヌムを無効にするための远加のパラメヌタがありたす。

MySQLに䜿甚できる2896ず同様です。

t.primary(["cmdId", "deviceId"]);
t.specificType("cmdId", "int(10) unsigned AUTO_INCREMENT").notNullable();
t.string("deviceId", 16).notNullable().references("second_table.deviceId");
このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡