Обсуждение: Is this correct behavior for ON DELETE rule?

Поиск
Список
Период
Сортировка

Is this correct behavior for ON DELETE rule?

От
"Rick Schumeyer"
Дата:

 

I have two related tables, “item” and “book”.  I have defined

a view, “bookview” that contains fields from item and book.

My goal was to have all inserts, updates, and deletes performed

on bookview rather than on the tables directly.  I was able

to do this with ON INSERT and ON UPDATE rules easily.

 

I am having trouble with the ON DELETE rule.  When a row is

deleted from bookview, the appropriate row should be deleted

from item and from book.  The example below only deletes the

row from book.

 

Is this expected behavior, and if so, what is the right way

to do this?  At the moment I have defined an ON DELETE rule

on item which works.  But I would prefer if this could be

done on the view.

 

Thanks for any help.

 

----------------------------------------------------------

drop table book cascade;

drop table item cascade;

 

-- "parent" table

create table item

      (id serial primary key,

      type  varchar(8),

      title varchar(20)

);

 

-- "child" table

create table book

      (id     integer references item primary key,

      title varchar(20),

      author  varchar(20)

);

 

-- combine stuff from item and book tables

create view bookview as

      select i.id, b.title, b.author from item i, book b

      where i.id=b.id;

 

-- insert to item and book instead of bookview

create rule bookviewins as on insert to bookview do instead (

      insert into item (type, title)

      values ('book', new.title);

      insert into book (id, title, author)

      values (currval('item_id_seq'), new.title, new.author);

);

 

-- delete to item and book instead of bookview

create rule bookviewdel as on delete to bookview do instead (

      delete from book where id=old.id;

      delete from item where id=old.id;

);

 

-- everyone has access to bookview

grant all on bookview to public;

 

insert into bookview (title, author) values ('Dune','Herbert');

insert into bookview (title, author) values ('Hobbit','Tolkein');

 

select * from bookview;

 

delete from bookview where author='Tolkein';

-- "DELETE 0"

 

select * from bookview;

-- looks correct

 

select * from item;

-- shows both books

 

select * from book;

-- looks correct

 

 

Re: Is this correct behavior for ON DELETE rule?

От
Bruce Momjian
Дата:
Uh, because of your REFERENCES clause you have to delete from 'item'
first, then 'book':

> -- delete to item and book instead of bookview
> create rule bookviewdel as on delete to bookview do instead (
>       delete from item where id=old.id;
>       delete from book where id=old.id;
> );

And your posting is double-spaces for some reason.

---------------------------------------------------------------------------

Rick Schumeyer wrote:
>
>
> I have two related tables, "item" and "book".  I have defined
>
> a view, "bookview" that contains fields from item and book.
>
> My goal was to have all inserts, updates, and deletes performed
>
> on bookview rather than on the tables directly.  I was able
>
> to do this with ON INSERT and ON UPDATE rules easily.
>
>
>
> I am having trouble with the ON DELETE rule.  When a row is
>
> deleted from bookview, the appropriate row should be deleted
>
> from item and from book.  The example below only deletes the
>
> row from book.
>
>
>
> Is this expected behavior, and if so, what is the right way
>
> to do this?  At the moment I have defined an ON DELETE rule
>
> on item which works.  But I would prefer if this could be
>
> done on the view.
>
>
>
> Thanks for any help.
>
>
>
> ----------------------------------------------------------
>
> drop table book cascade;
>
> drop table item cascade;
>
>
>
> -- "parent" table
>
> create table item
>
>       (id serial primary key,
>
>       type  varchar(8),
>
>       title varchar(20)
>
> );
>
>
>
> -- "child" table
>
> create table book
>
>       (id     integer references item primary key,
>
>       title varchar(20),
>
>       author  varchar(20)
>
> );
>
>
>
> -- combine stuff from item and book tables
>
> create view bookview as
>
>       select i.id, b.title, b.author from item i, book b
>
>       where i.id=b.id;
>
>
>
> -- insert to item and book instead of bookview
>
> create rule bookviewins as on insert to bookview do instead (
>
>       insert into item (type, title)
>
>       values ('book', new.title);
>
>       insert into book (id, title, author)
>
>       values (currval('item_id_seq'), new.title, new.author);
>
> );
>
>
>
> -- delete to item and book instead of bookview
>
> create rule bookviewdel as on delete to bookview do instead (
>
>       delete from book where id=old.id;
>
>       delete from item where id=old.id;
>
> );
>
>
>
> -- everyone has access to bookview
>
> grant all on bookview to public;
>
>
>
> insert into bookview (title, author) values ('Dune','Herbert');
>
> insert into bookview (title, author) values ('Hobbit','Tolkein');
>
>
>
> select * from bookview;
>
>
>
> delete from bookview where author='Tolkein';
>
> -- "DELETE 0"
>
>
>
> select * from bookview;
>
> -- looks correct
>
>
>
> select * from item;
>
> -- shows both books
>
>
>
> select * from book;
>
> -- looks correct
>
>
>
>
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: Is this correct behavior for ON DELETE rule?

От
Tom Lane
Дата:
"Rick Schumeyer" <rschumeyer@ieee.org> writes:
> -- delete to item and book instead of bookview
> create rule bookviewdel as on delete to bookview do instead (
>       delete from book where id=old.id;
>       delete from item where id=old.id;
> );

This is an ancient gotcha: as soon as you delete the book row, there is
no longer any such entry in the bookview view ... and "old.id" is
effectively a reference to the bookview view, so the second delete
finds no matching rows.

If you can reasonably turn the view into a LEFT JOIN in one direction or
the other, then a workaround is to delete from the nullable side first.

            regards, tom lane

Re: Is this correct behavior for ON DELETE rule?

От
"Rick Schumeyer"
Дата:
I suspected that might be part of the answer.

Would some combination of triggers work instead?  I've played
with those too, but without success.

>
> This is an ancient gotcha: as soon as you delete the book row, there is
> no longer any such entry in the bookview view ... and "old.id" is
> effectively a reference to the bookview view, so the second delete
> finds no matching rows.
>


Re: Is this correct behavior for ON DELETE rule?

От
"Rick Schumeyer"
Дата:
I tried that, but I get a "...violates foreign-key constraint" error.

> -----Original Message-----
> From: pgsql-general-owner@postgresql.org [mailto:pgsql-general-
> owner@postgresql.org] On Behalf Of Bruce Momjian
> Sent: Friday, February 25, 2005 6:23 PM
> To: Rick Schumeyer
> Cc: 'PgSql General'
> Subject: Re: [GENERAL] Is this correct behavior for ON DELETE rule?
>
>
> Uh, because of your REFERENCES clause you have to delete from 'item'
> first, then 'book':
>
> > -- delete to item and book instead of bookview
> > create rule bookviewdel as on delete to bookview do instead (
> >       delete from item where id=old.id;
> >       delete from book where id=old.id;
> > );
>


Re: Is this correct behavior for ON DELETE rule?

От
Bruce Momjian
Дата:
Rick Schumeyer wrote:
> I tried that, but I get a "...violates foreign-key constraint" error.

Oh, sorry.

---------------------------------------------------------------------------


>
> > -----Original Message-----
> > From: pgsql-general-owner@postgresql.org [mailto:pgsql-general-
> > owner@postgresql.org] On Behalf Of Bruce Momjian
> > Sent: Friday, February 25, 2005 6:23 PM
> > To: Rick Schumeyer
> > Cc: 'PgSql General'
> > Subject: Re: [GENERAL] Is this correct behavior for ON DELETE rule?
> >
> >
> > Uh, because of your REFERENCES clause you have to delete from 'item'
> > first, then 'book':
> >
> > > -- delete to item and book instead of bookview
> > > create rule bookviewdel as on delete to bookview do instead (
> > >       delete from item where id=old.id;
> > >       delete from book where id=old.id;
> > > );
> >
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 7: don't forget to increase your free space map settings
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Re: Is this correct behavior for ON DELETE rule?

От
Tom Lane
Дата:
"Rick Schumeyer" <rschumeyer@ieee.org> writes:
> Would some combination of triggers work instead?

Nope, you can't put triggers on a view, sorry.  In theory a BEFORE
INSERT trigger would be a workable alternative to an ON INSERT rule
for redirecting insertions.  (I think we disallow it at the moment
though.)  But UPDATE and DELETE triggers can't work because the view
doesn't actually contain any physical tuples and so there is nothing
for the triggers to fire on.

            regards, tom lane

Re: Is this correct behavior for ON DELETE rule?

От
Keary Suska
Дата:
on 2/25/05 4:09 PM, rschumeyer@ieee.org purportedly said:

> I have two related tables, ³item² and ³book².  I have defined
> a view, ³bookview² that contains fields from item and book.
> My goal was to have all inserts, updates, and deletes performed
> on bookview rather than on the tables directly.  I was able
> to do this with ON INSERT and ON UPDATE rules easily.

You may have better luck letting foreign key constraints work for you, and
specify ON DELETE CASCADE in your constraint. If, however, you don't always
want to delete related "book" rows when "item" rows are deleted, you may
want to re-think your relation.

> -- "child" table
> create table book
>     (id    integer references item primary key,
>     title varchar(20),
>     author varchar(20)
> );

Best,

Keary Suska
Esoteritech, Inc.
"Demystifying technology for your home or business"