:
tariff_id | reception
cheap | USA
expensive | Russia
users_tariffsで間違った状況、安い関税は米国だけのためであるため、解決策1:外部キー制約
私は次の表の定義を前提としています。 特に、複合キーuser_tariffs
では、これはusers
とtariffs
の多対多の関係になります。
CREATE TABLE tariffs (tariff_id int NOT NULL PRIMARY KEY,
reception text NOT NULL);
CREATE TABLE users (user_id int NOT NULL PRIMARY KEY,
reception text NOT NULL);
CREATE TABLE user_tariffs (tariff_id int NOT NULL REFERENCES tariffs (tariff_id),
user_id int NOT NULL REFERENCES users (user_id),
PRIMARY KEY (tariff_id, user_id));
は、おそらくどこかに、すべての3つの列の組み合わせを必要とし、その者は、これを作成してみましょう:
は
ALTER TABLE user_tariffs ADD COLUMN reception text;
UPDATE user_tariffs a
SET reception = b.reception
FROM (SELECT * FROM tariffs) b
WHERE a.tariff_id = b.tariff_id;
ALTER TABLE user_tariffs ALTER COLUMN reception SET NOT NULL;
今、我々はFOREIGN KEYがusers
に(user_id, reception)
を参照して使用することができます。
CREATE UNIQUE INDEX ON tariffs (tariff_id, reception);
ALTER TABLE user_tariffs ADD FOREIGN KEY (tariff_id, reception)
REFERENCES tariffs (tariff_id, reception);
はまた、我々はtariffs
にFKのREF (tariff_id, reception)
を使用することができます。
CREATE UNIQUE INDEX ON users (user_id, reception);
ALTER TABLE user_tariffs ADD FOREIGN KEY (user_id, reception)
REFERENCES users (user_id, reception);
データを取り込む:あなただけ(1, 1)
かを追加することができますので、あなたは、データを挿入することはできません
WITH data (user_id, tariff_id)
AS (VALUES (1, 2), (2, 1)), -- here is your application data
datas (user_id, tariff_id, reception)
AS (SELECT user_id,
tariff_id,
(SELECT u.reception -- reception calculated by user
FROM users u
WHERE u.user_id = d.user_id)
FROM data d)
INSERT INTO user_tariffs SELECT * FROM datas ;
を:
INSERT INTO users VALUES (1, 'cheap'), (2, 'expensive');
INSERT INTO tariffs VALUES (1, 'cheap'), (2, 'expensive');
は、今、私たちは挿入するには、次のデータ(user_id, tariff_id)
を持っていると仮定(2, 2)
は同じreception
であるが、(1, 2)
または(2, 1)
と異なるreception
さんの。エラーメッセージは次のとおりです。
ERROR: insert or update on table "user_tariffs" violates foreign key constraint "user_tariffs_user_id_fkey1"
DETAIL: Key (user_id, reception)=(2, cheap) is not present in table "users".
しかし、あなたはdata AS VALUES (1, 1), (2, 2)
に挿入することができます。 私はFOREIGN KEY CONSTRAINTソリューションが望ましいと思います。
テーブルデザインを改善したい場合は、functional dependencies
を記載してください。
SOLUTION 2:
CREATE OR REPLACE FUNCTION check_reception()
RETURNS trigger AS $$
DECLARE valid boolean := false;
BEGIN
SELECT (SELECT u.reception FROM users u WHERE u.user_id = NEW.user_id)
= (SELECT t.reception FROM tariffs t WHERE t.tariff_id = NEW.tariff_id)
INTO valid FROM user_tariffs ;
IF valid = false
THEN RAISE EXCEPTION '(user, tariff, reception) invalid.';
END IF;
RETURN NEW;
END; $$ LANGUAGE plpgsql ;
をし、それを登録します:TRIGGER
-- DROP TABLE user_tariffs CASCADE;
-- DROP TABLE users CASCADE;
-- DROP TABLE tariffs CASCADE;
CREATE TABLE tariffs (tariff_id int NOT NULL PRIMARY KEY,
reception text NOT NULL);
CREATE TABLE users (user_id int NOT NULL PRIMARY KEY,
reception text NOT NULL);
CREATE TABLE user_tariffs (tariff_id int NOT NULL REFERENCES tariffs (tariff_id),
user_id int NOT NULL REFERENCES users (user_id),
PRIMARY KEY (tariff_id, user_id));
INSERT INTO users VALUES (1, 'cheap'), (2, 'expensive');
INSERT INTO tariffs VALUES (1, 'cheap'), (2, 'expensive');
-- table user_tariffs (user_id, tariff_id) only, without reception column.
戻り値の型トリガーに関数を作成します
CREATE TRIGGER reception_trigger
AFTER INSERT OR UPDATE ON user_tariffs
FOR EACH ROW EXECUTE PROCEDURE check_reception();
は今(1を挿入しようと、 2)、これは(安く高価な)許可されていません:
INSERT INTO user_tariffs VALUES (1, 2);
ERROR: (user, tariff, reception) invalid.
KONTEXT: PL/pgSQL function check_reception() line 7 at RAISE
しかし、我々は問題なく(安い安い)である、(1,1)を挿入することができます
トリガが、ここでは最善の解決策ではありません
INSERT INTO user_tariffs VALUES (1, 1);
SELECT * FROM user_tariffs;
備考私の意見。可能であれば、トリガーを避けるようにしてください。彼らは副作用(トランザクションなど)を持つことができます。
レセプション:)詳細はStackOverflowのを確認してくださいcontryようなものです。ヨーロッパからの人々は、米国から割当てられた関税を得ることができません。 –
どのような機能的依存関係がありますか? (ユーザ、受信) - >料金表、(料金表、受信) - >ユーザと(ユーザ、料金) - > 3つすべて?サブセットは?多対多とは何ですか? 1対多とは何ですか? 1対1とは何ですか?どれが必須であるか(最低1つのエントリー)?どちらが(ゼロ以上)持つことができますか?あなたの主キーは何ですか?ユニークなものは何ですか?あなたの外来キーは何ですか? – flutter
USER_IDが一意である、tariff_idがユニークで、すべての値がnullではない –