私はpostgreSQLの新人です。 3つのテーブルがあり、1つのテーブルが他の2つのテーブルの主キーを参照しています。しかし、_Table3
_にデータを挿入できませんでした。以下のコードを参照してください:
_DROP TABLE Table1 CASCADE;
CREATE TABLE Table1(
"DataID" bigint NOT NULL DEFAULT '0',
"AdData" integer DEFAULT NULL,
PRIMARY KEY ("DataID")
);
DROP TABLE IF EXISTS Table2 CASCADE;
CREATE TABLE Table2 (
"Address" numeric(20) NOT NULL DEFAULT '0',
"Value" numeric(20) DEFAULT NULL,
PRIMARY KEY ("Address")
);
DROP TABLE IF EXISTS Table3 CASCADE;
CREATE TABLE table3 (
"ID" bigint NOT NULL DEFAULT '0',
"DataID" bigint DEFAULT NULL,
"Address" numeric(20) DEFAULT NULL,
"Data" bigint DEFAULT NULL,
PRIMARY KEY ("ID"),
FOREIGN KEY ("DataID") REFERENCES Table1("DataID") on delete cascade on update cascade,
FOREIGN KEY ("Address") REFERENCES Table2("Address") on delete cascade on update cascade
);
_
エラー:テーブル "Table3"の挿入または更新が外部キー制約 "Table3_DataID_fkey"に違反しています詳細:キー(DataID)=(27856)がテーブル "Table1"に存在しません。
3つのテーブルにデータを挿入しようとすると、エラーが発生しました。 postgreSQLドキュメント を参照し、コードを次のように変更しました(残念ながら、別のエラーが表示されていました)。
_DROP TABLE Table1 CASCADE;
CREATE TABLE Table1(
"DataID" bigint NOT NULL DEFAULT '0',
"AdData" integer DEFAULT NULL,
PRIMARY KEY ("DataID")
);
DROP TABLE IF EXISTS Table2 CASCADE;
CREATE TABLE Table2 (
"Address" numeric(20) NOT NULL DEFAULT '0',
"Value" numeric(20) DEFAULT NULL,
PRIMARY KEY ("Address")
);
DROP TABLE IF EXISTS Table3 CASCADE;
CREATE TABLE table3 (
"ID" bigint NOT NULL DEFAULT '0',
"DataID" bigint DEFAULT NULL REFERENCES Table1 ON DELETE RESTRICT,
"Address" numeric(20) DEFAULT NULL REFERENCES Table2 ON DELETE CASCADE,
"Data" bigint DEFAULT NULL,
PRIMARY KEY ("ID"),
PRIMARY KEY("DataID", "Address")
);
_
エラー:テーブル「Table3」の複数の主キーは使用できません。行65:PRIMARY KEY( "DataID"、 "Address")
助けてください...どうすれば参照を作成できますか?
ID
をUNIQUE
に変更し、PRIMARY KEY ("ID")
という行を削除しました。そのとき、次のような別のエラーが表示されます:
エラー:重複するキー値が一意の制約「Table3_pkey」に違反しています
テーブルにいくつかの問題があります。あなたがそれらについて質問したので、私は最初に外部キーに対処しようとします:)
ただし、その前に、2つのテーブルセット(作成した最初の3つと、最初のセットを削除した後に作成した2つ目のセット)が同じであることを理解する必要があります。もちろん、2回目の試行での_Table3
_の定義には構文エラーと論理エラーがありますが、基本的な考え方は次のとおりです。
_CREATE TABLE table3 (
"ID" bigint NOT NULL DEFAULT '0',
"DataID" bigint DEFAULT NULL,
"Address" numeric(20) DEFAULT NULL,
"Data" bigint DEFAULT NULL,
PRIMARY KEY ("ID"),
FOREIGN KEY ("DataID") REFERENCES Table1("DataID") on delete cascade on update cascade,
FOREIGN KEY ("Address") REFERENCES Table2("Address") on delete cascade on update cascade
);
_
この定義は、おおよそPostgreSQLに次のように伝えます。「4つの列を持つテーブルを作成し、1つを主キー(PK)にし、その他をNULL
にすることができます。新しい行が挿入される場合は、DataID
とAddress
を確認してください。 NULL値(27856など)の場合、DataID
checkの_Table1
_とAddress
の_Table2
_を確認してください。これらのテーブルにそのような値がない場合は、エラーを返します。 "あなたが最初に見たこの最後のポイント:
_ERROR: insert or update on table "Table3" violates foreign key constraint
"Table3_DataID_fkey" DETAIL: Key (DataID)=(27856) is not present in table "Table1".
_
とても単純です。_Table1
_に行がない場合、_DataID = 27856
_の場合、その行を_Table3
_に挿入することはできません。
その行が必要な場合は、first _Table1
_に_DataID = 27856
_を使用して行を挿入し、次に_Table3
_に挿入してみてください。 これがあなたが望むものではないと思われる場合は、達成したいことを数文で説明してください。そうすれば、優れた設計を支援できます。
そして今、他の問題について。
PKを次のように定義します
_CREATE all_your_tables (
first_column NOT NULL DEFAULT '0',
[...]
PRIMARY KEY ("ID"),
_
主キーは、その中のすべての項目が互いに異なることを意味します。つまり、値はUNIQUE
です。 DEFAULT
列に静的なUNIQUE
(_'0'
_など)を指定すると、常に予期しない事態が発生します。これは、3番目のエラーメッセージで得られたものです。
さらに、_'0'
_はテキスト文字列を意味しますが、数値(あなたの場合はbigint
またはnumeric
)を意味しません。代わりに単純に_0
_を使用してください(または、上で書いたように、まったく使用しないでください)。
最後のポイント(私はここでは間違っているかもしれません):_Table2
_では、Address
フィールドがnumeric(20)
に設定されています。同時に、それはテーブルのPKです。列名とデータ型は、このアドレスが将来変更される可能性があることを示しています。これが本当なら、それはPKにとって非常に悪い選択です。次のシナリオについて考えてみましょう。「1234567890454」というアドレスがあり、これは_Table3
_のように子を持っています
_ID DataID Address Data
123 3216547 1234567890454 654897564134569
_
さて、そのアドレスはたまたま別のものに変わっています。 _Table3
_の子行を親の後に新しい住所にするにはどうすればよいですか? (これには解決策がありますが、多くの混乱を引き起こす可能性があります。)これが当てはまる場合は、ID列をテーブルに追加します。これには、実際の情報は含まれず、単に識別値として機能します(つまり、 、ID)。
それはすべて、データをどのように処理するかによって異なります。
最初の例-すべてのテーブルで一貫性のあるデータを保持したいが、Table1と一致しない値を挿入しようとしています。
2番目の例-一貫性のあるデータを持ちたくないが、何かを正確に知らないで、何か他のことを試みてください。テーブルに複数の主キーを含めることはできません。
3番目の例-あなたはまだ何を達成したいのかわからず、同じ値を複数回持つ可能性のある列にUNIQUE制約を設定します。
データを挿入したいだけの場合-最初の例で外部キー参照を取り除いてください。すべてのテーブルに一貫性のあるデータが必要な場合-データをクリーンアップしてから、外部キー制約を使用してテーブルに挿入します。
tl; dr:最初の例のコードを使用してTable3にデータを挿入します-Table3.DataIdに存在する欠損値をTable1.DataID列に挿入します。