KNexによる外部鍵制約データベースの原子性を確保する


フラッシュカードのように、私のQuizletのようなクローンの建物の上で、私はcard_set すべてのflashcards も削除されます.私はこれを処理しようとしたが、これは悪い論理とエッジのケースの悪夢となった.結局、私は一歩後退して、本当に解決しようとしていた問題を調査しようとしました.私のデータベースは私のアプリケーション内のすべてのデータの真実の私の単一のソースです.私のデータベースが上記の操作を安全に扱うことは可能ですか?それは!外部キー制約の追加knex マイグレート私はPostgresデータベース内のデータベースのアトミック性を確保するための手順を取ることができます.

データベースアトミック性とは何か


"An atomic transaction is an indivisible and irreducible series of database operations such that either all occur, or nothing occurs." - Wikipedia


これは、私がデータベースを削除しようとするならばcard_setflashcards , どちらかcard_set そしてflashcards の両方を削除します.

何が外国の鍵ですか?


外部キーは、別のテーブルの主キーへのリファレンスです.外部キーを簡単にテーブル間の関係を確立することができます.
コードにジャンプする前に、私の設定を見てみましょうcard_sets and flashcards . マイcard_sets 表は親テーブルですflashcards チャイルドテーブル.
親は多くの子供を持つことができます、しかし、子供は1つの親だけを持つことができますcard_set 持つことができるflashcards , でもflashcard 単数形card_set . この関係は、「多くの/所有している」という関係として記述することもできる.エーcard_set が多いflashcards , でもflashcard 一つに属するcard_set .

この「親/子」または「多くの/属している」関係を確立するために、私は外部キー制約をセットアップしなければなりません.これは、私の外部キー制約がknex , SQLクエリビルダを使用しています.
// Part of My Flashcards Migration File

  // This code creates my "card_set_id" column as a 
  // not nullable UUID type
    table
      .uuid("card_set_id")
      .notNullable()
      .references("id")
      .inTable("card_sets")
      .onDelete("CASCADE");
これら三つの関数は、私たちの外部キーとその動作を定義するのに役立ちます.

参考文献


The column.references(column) 関数は、外部キーとして参照する主キー値を示します.
上のコードでは、私たちは参照するつもりですid いくつかのテーブルの列(私たちはまだどのテーブルを定義していません!)我々の主キーとしてcard_set_id 外部キー.
さて、どのテーブルのid 列の主キー値を使用します.

不変な


The column.inTable(table) 関数は、どのキーを使用して外部キーとして使用するかを定義します.
上のコードではcard_sets 表.今、我々は2つにバインドして、テーブル間の関係を形成したflashcards.card_set_id 外部キーcard_sets.id

ondelete


The column.onDelete(command) 関数は、この外部キーですべての子行をどのようにしたいのかを定義できますflashcards.card_set_id ) 参照している親行が削除されたときに動作します.card_sets.id ).
Postgresと共に働いていますが、すべてのSQLデータベース実装がこれらのコマンドを受け入れるわけではありません.

  • カスケード-親行が削除されると、親を参照するすべての子行が削除されます

  • set null -親行が削除された場合、親行を参照する外部キーを持つすべての子行は、値“null”に設定されます

  • 制限-子行が親行を参照する場合、親行と子行は削除されません
  • NO ACTION
  • 保証されたデータベース


    今、問題は解決されます!削除するならcard_set 私のPostgreSQLデータベースはすべてを保証しますflashcards それに伴うcard_set も削除される.
    Postgresはトランザクション全体を処理します.トランザクションが失敗したならcard_set と関連付けflashcards はトランザクションが発生する前に状態に戻ります.トランザクションが成功するならば、私は両方とも知っていますcard_set 関連付けflashcards 削除!