1

テーブルマガジンがあるとしましょう:

CREATE TABLE magazine
(
  magazine_id integer NOT NULL DEFAULT nextval(('public.magazine_magazine_id_seq'::text)::regclass),
  longname character varying(1000),
  shortname character varying(200),
  issn character varying(9),
  CONSTRAINT pk_magazine PRIMARY KEY (magazine_id)
);

そして別のテーブルの問題:

CREATE TABLE issue
(
  issue_id integer NOT NULL DEFAULT nextval(('public.issue_issue_id_seq'::text)::regclass),
  number integer,
  year integer,
  volume integer,
  fk_magazine_id integer,
  CONSTRAINT pk_issue PRIMARY KEY (issue_id),
  CONSTRAINT fk_magazine_id FOREIGN KEY (fk_magazine_id)
      REFERENCES magazine (magazine_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);

現在のインサート:

INSERT INTO magazine (longname,shotname,issn)
VALUES ('a long name','ee','1111-2222');

INSERT INTO issue (fk_magazine_id,number,year,volume)
VALUES (currval('magazine_magazine_id_seq'),'8','1982','6');

これで、行がまだ存在しない場合にのみ、「magazine」に行を挿入する必要があります。ただし、存在する場合、参照を確立するために、テーブル 'issue' は既に存在する行の 'magazine_id' を取得する必要があります。

これどうやってするの?

事前にt​​hx!

4

3 に答える 3

1

雑誌がすでにmagazineテーブルにあるかどうかを知るにはどうすればよいですか? issn列は雑誌を定義しますか? はいの場合、主キー、または少なくともunique.

最も簡単な方法は、次のように (疑似コードで) クライアント アプリケーションで雑誌の存在を確認することです。

function insert_issue(longname, shotname, issn, number,year,volume) {
    /* extensive comments for newbies */
    start_transaction();
    q_get_magazine_id = prepare_query(
      'select magazine_id from magazine where issn=?'
    );
    magazine_id = execute_query(q_get_magazine_id, issn);
    /* if magazine_id is null now then there’s no magazine with this issn */
    /* and we have to add it */
    if ( magazine_id == NULL ) {
      q_insert_magazine = prepare_query(
        'insert into magazine (longname, shotname, issn)
          values (?,?,?) returning magazine_id'
      );
      magazine_id = execute_query(q_insert_magazine, longname, shortname, issn);
      /* we have tried to add a new magazine; */
      /* if we failed (magazine_id==NULL) then somebody else just added it */
      if ( magazine_id == NULL ) { 
        /* other, parerelly connected client just inserted this magazine, */
        /* this is unlikely but possible */
        rollback();
        start_transaction();
        magazine_id = execute_query(q_get_magazine_id, issn);
      }
    }
    /* now magazine_id is an id of magazine, */
    /* added if it was not in a database before, new otherwise */
    q_insert_issue = prepare_query(
      'insert into issue (fk_magazine_id,number,year,volume)
         values (?,?,?,?)'
    );
    execute_query(q_insert_issue, magazine_id, number, year, volume);
    /* we have inserted a new issue referencing old, */
    /* or if it was needed new, magazine */
    if ( ! commit() ) {
      rollback();
      raise "Unable to insert an issue";
    }
}

これを 1 つのクエリで実行する必要がある場合は、この疑似コードをデータベースの pl/pgsql 関数として実装し、select insert_issue(?, ?, ?, ?, ?, ?).

于 2010-03-12T13:02:57.940 に答える
0

PostgreSQL 9.1 以降を使用している場合は、次のようなことができます。

WITH ref_key (id) AS (
    WITH ins (id) AS (
       INSERT INTO magazine (longname,shotname,issn)
       VALUES ('a long name','ee','1111-2222')
       RETURNING id
    )
    SELECT id 
      FROM magazine 
      LEFT JOIN ins USING id
     WHERE issn = '1111-2222'
)
INSERT INTO INTO issue (fk_magazine_id,number,year,volume)
SELECT id,'8','1982','6'
  FROM ref_key;

書き込み可能な CTE の FTW!

于 2012-09-27T02:13:32.843 に答える
-1

SQLでこれを実行できるかどうかはわかりません。Oracle をトリガーに使用できることは知っていますが、SQL は使用できないと思います。私が間違っている場合は、誰かが私を修正してください。

于 2010-03-12T11:40:32.333 に答える