web-dev-qa-db-ja.com

外部キー制約を含む列を既存のテーブルに追加するにはどうすればよいですか?

次の表があります。

CREATE TABLE users (id int PRIMARY KEY);

-- already exists with data
CREATE TABLE message ();

messagesテーブルを次のように変更するにはどうすればよいですか。

  1. senderという新しい列が追加されます
  2. ここで、senderusersテーブルを参照する外部キーです

これは機能しませんでした

# ALTER TABLE message ADD FOREIGN KEY (sender) REFERENCES users;
ERROR:  column "sender" referenced in foreign key constraint does not exist

このステートメントは列も作成しませんか?

11
Hassan Baig

比較的簡単なこと-別のステップを追加するだけです。

_FOREIGN KEY_列FKにするためには、存在する必要があります。私は次のことを行いました( here および documentation から):

_CREATE TABLE x(t INT PRIMARY KEY);

CREATE TABLE y(s INT);

ALTER TABLE y ADD COLUMN z INT;    

ALTER TABLE y
  ADD CONSTRAINT y_x_fkey FOREIGN KEY (z)
      REFERENCES x (t)
      ON UPDATE CASCADE ON DELETE CASCADE;
_

注意すべきいくつかの点:

[〜#〜]常に[〜#〜]は、外部キーに意味のある名前を付けます。キー「SYS_C00308108」に違反していると言われてもあまり役に立ちません。フィドルを参照 ここ このような状況でのOracleの動作については、キー名はフィドルごとに異なりますが、SYS _...で始まる任意の文字列です)

あなたの声明を考慮してください:

_ALTER TABLE message ADD FOREIGN KEY (sender) REFERENCES users;
_

RDBMSが、参照されるフィールドと一致するデータ型を使用して、必要なフィールドを自動的に作成できる場合は、「Nice-to-have」になります。私が言えることは、DDLの変更はめったに使用されない操作であり(少なくともそうである必要があります)、定期的に実行する必要のある操作ではないということです。また、すでにかなりの量のドキュメントを追加するリスクもあります。

少なくともPostgreSQLは適切な処理を試みます-テーブル名、_FOREIGN KEY_フィールド名、および__fkey_を連結し、DETAIL: Key (sender_id)=(56) is not present in table "user_".を追加して、人間に意味のあるものを提供します-フィドルを参照 ここ

18
Vérace

なぜ誰もがこれを2つのステップで実行する必要があると言っているのかわかりません。 実際、あなたはしませんFOREIGN KEYを追加しようとしましたが、これは、設計上、列が存在し、列が存在しない場合にそのエラーをスローします。 COLUMNを追加すると、REFERENCESを使用して作成時に明示的にFOREIGN KEYにすることができます。

ALTER TABLE message
  ADD COLUMN sender INT
  REFERENCES users;  -- or REFERENCES table(unique_column)

正常に動作します。 ここでALTER TABLEの構文を参照

ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
action [, ... ]

"action"として、

ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]

これらの例はドキュメントにもあります

ALTER TABLE distributors
  ADD CONSTRAINT distfk
  FOREIGN KEY (address)
  REFERENCES addresses (address);

ALTER TABLE distributors
  ADD CONSTRAINT distfk
  FOREIGN KEY (address)
  REFERENCES addresses (address)
  NOT VALID;

しかし、自動命名と主キーの解決に頼ることができるため、これらすべては必要ありません(table-nameのみが指定されている場合は、主キーを参照しています)。

8
Evan Carroll

CASE1:新しいテーブルの作成中に外部キーを作成する必要がある場合

CREATE TABLE table1(
id SERIAL PRIMARY KEY,
column1 varchar(n) NOT NULL,
table2_id SMALLINT REFERENCES table2(id)
); 

上記のコマンドは、「table1」という名前のテーブルを作成し、「id」(主キー)、「column1」、「table2_id」(table2のid列を参照するtable1の外部キー)という名前の3つの列を作成します。

DATATYPE 'serial'は、このデータ型を自動生成列として使用する列を作成します。テーブルに値を挿入する場合、この列についてまったく言及する必要はありません。または、値の場所に引用符なしで 'default'を指定できます。

主キー列は常に値「tablename_pkey」を持つテーブルのインデックスに追加されます。

テーブル作成時に外部キーが追加されると、パターン '(present_table_name)_(foreign_key_id_name)_fkey'でCONSTRAINTが追加されます。

外部キーを追加するときは、列名の横にキーワード「REFERENCES」を入力する必要があります。これは、この列がテーブルを参照することをpostgresに伝え、次に参照の横に参照用のテーブルを指定する必要があるためです。参照されるテーブルの列名。通常、外部キーは主キー列として指定されます。

ケース2:既存の列の既存のテーブルへの外部キーが必要な場合

ALTER TABLE table1
ADD CONSTRAINT table1_table2_id_id_fkey
FOREIGN KEY (table2_id) REFERENCES table2(id);

注:FOREIGN KEYとREFERENCES tabel2の後のブラケット '()'は必須です。そうでない場合、postgresはエラーをスローします。

0
Ashok Allu

私は問題を知っています。列名が異なります。たぶん1つの列では、列名の後にスペースが追加されるので、列名の名前が正確に同じであることを確認してください。

0
XIN WANG