views:

368

answers:

2

Let's assume I have a table magazine:

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)
);

And another table issue:

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
);

Current INSERTS:

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');

Now a row should only be inserted into 'magazine', if it does not already exist. However if it exists, the table 'issue' needs to get the 'magazine_id' of the row that already exists in order to establish the reference.

How can i do this?

Thx in advance!

A: 

I'm not sure that if you can do this with SQL. I know that Oracle can be used for triggers, but i don't think SQL is able to. Someone correct me if I'm wrong.

lugte098
I'm not even sure what to say about this "answer."
Gary Chambers
A: 

How do you know if a magazine is already in magazine table? Does issn column define a magazine? If yes then it should be a primary key, or at least unique.

The easiest way would be to do a check for magazine existence in your client application, like this (in pseudocode):

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";
    }
}

If you just have to do this in one query then you can implement this pseudocode as pl/pgsql function in database and just select insert_issue(?, ?, ?, ?, ?, ?).

Tometzky
thanks for your answer. how i know if a magazine is already in magazine table? i don't know how to do this but i guess you would have to check if the row you are about to insert already exists, maybe with a WHERE EXISTS query. the magazine_id should define a magazine, at least i planned it this way.
flhe
I'm confused. Please, answer some questions: 1. Can there be two magazines with the same ISSN? 2. Can there be two magazines with the same longname? 3. Can there be two magazines with the same shortname?
Tometzky
Sorry for having confused you. 1. No, a magazine has a unique ISSN. 2. No the magazines are unique. 3. No.The problem is that it might happen, that i insert a dataset with the magazine xy and magazine_id=1. Then later it might happen that the absolute same magazine xy would be inserted into the table as dataset 400. So magazine xy would also have magazine_id=400 which is bad. magazine xy should stick with magazine_id=1
flhe
Then just add UNIQUE constraint to longname, shortname and issn columns. The database server will not allow creating 2 magazines with the same name, issn or shortname. Also consider adding NOT NULL constraints there by asking youself a question - does every magazine has to have name, issn, and shortname and is it always known.
Tometzky
Yes but then I have the problem that the dataset with magazine_id=400 will not be referenced at all. Understand? The issue table needs the magazine_id=1 for dataset 400. A UNIQUE constraint would only cause that it is not entered into the db.
flhe
Please try to understand a code in my answer. I have added extensive comments to it, for easier understanding. This is an answer to your question. Port this code from pseudocode to your client language. I'm not able to explain this clearer.
Tometzky