sql >> データベース >  >> RDS >> PostgreSQL

一部の列値が他のテーブルに存在する外部キー制約

    書籍名のすべての外部キーを省略しました。

    だから私はテーブル定義の完全に強化されたセットで答えます、これは外部キーについてですよね?簡素化された例を挙げたShure。

    解決すべき問題は、reading_event_discussionのレコードでした。 その本に存在するテーマに関するものでなければなりません:

    drop table book cascade;
    drop table book_theme;
    drop table reading_event cascade;
    drop table reading_event_discussion;
    
    create table book (
        name text primary key -- new, a must because it is FK in reading_event
    );
    insert into book (name) values ('game of thrones'),('Database design');
    
    create table book_theme (
        bookname  text references book(name), -- new
        themename text
    );
    insert into book_theme (bookname, themename) values 
      ('game of thrones', 'ambition'), ('game of thrones', 'power');
    
    create table reading_event (
      i        SERIAL primary key, 
      venue    text, 
      bookread text references book(name) -- FK is new
    );
    insert into reading_event (venue, bookRead) VALUES
      ('Municipal Library', 'game of thrones');  
    
    -- this is the solution: extended reference check
    create or replace function themecheck (i integer, th text) returns boolean as $$
        select 
         (th in (select themename from book_theme bt 
           join reading_event re on i=re.i and re.bookRead=bt.bookname))
    $$ language sql;
    
    create table reading_event_discussion (
        i integer references reading_event(i), 
        themeDiscussed text check (themecheck (i, themeDiscussed))
    );
    
    -- Test statements:
    -- just check data
    select * from reading_event;
    -- this should be ok
    insert into reading_event_discussion values (1,'ambition'),(1,'power');
    -- this must be refused
    insert into reading_event_discussion values (1,'databases');
    

    したがって、解決策はカスタムチェック関数を作成することです。これは他のデータベースシステムに移植できません。

    この関数は複数の言語(plpgsql、pltcl、...)で記述できますが、SQL関数はクエリにインライン化できるため、より高速になる可能性があります。




    1. DUALからのサブクエリに対して機能しないことによるOracleOrder

    2. PHPは前のクエリの結果をクエリできますか?

    3. SELECTでさえエラーを返すようにMySQL行を意図的にロックするにはどうすればよいですか?

    4. 同じテーブルの挿入後トリガーで更新