Обсуждение: Re: My brain hurts - update field based on value of another table's field

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

Re: My brain hurts - update field based on value of another table's field

От
missive@frontiernet.net (Lee Harr)
Дата:
On Sun, 23 Sep 2001 03:56:50 GMT, Pat M <pmeloy@removethispart.home.com> wrote:
> I'm just a hobbyist so this is probably atroceous, but I'm trying to do
> something like the following. Sorry its not in real SQL format. I know how
> to auto-update by referencing to a primary key of another table, but what if
> you want a field to change along with a non-unique field from a different
> table? Here's an example of what I mean
>
> table areas
> -------------
> area_id serial primary key
> area_name text
>
> table sites
> ----------
> site_id serial primary key
> site_name text
> site_area int references areas on delete cascade
>
> table buildings
> ------------
> building_id serial primary key
> building_name text
> building_area int <--- needs to change when site_area changes
> building_site int references sites on delete cascade
>

I think you would do this by _not_ having building_area at all.
You have a building_site, which has a site_area. Is it possible
to have a building_area that is _different_ from the site_area
of the building_site? That does not make sense to me.


> table zones
> ------------
> zone_id serial primary key
> zone_name text
> zone_area int  <--- needs to change when building_area changes
> zone_site int  <--- needs to change when building_site changes
> zone_building int references buildings on delete cascade
>

It is really difficult to help you not knowing what these "site" and
"area" and "zone" things are.


> None of the primary keys will be changing of course. But the area a building
> is in may change (area being an arbitrary designation, not municiple
> boundaries), as may other fields as I work my way through building the data.
>
> I know I can join things together in queries, avoiding all this, but it gets
> real confusing trying to join 12 tables, and slow... I want to be able to
> get the area from the buildings table and not have to join three tables just
> to find out what area it belongs to. Unless someone knows an easier way than
> select area_name from areas,sites,buildings where area_id=site_area and
> site_id=building_id and building_id=1; Speed and easy queries are my focus,
> not disk space or ram savings.
>
> I looked at foreign keys, but they get uptight when the referenced field
> isn't unique. On update cascade would have been wonderful 8(
>
> I looked at inheritance, but I don't think its what I had in mind.
>
> I'm thinking I have to delve into the horrors that are triggers and
> functions...
>
> Any cool ideas floating around out there?
>
>

Re: My brain hurts - update field based on value of another table's field

От
missive@frontiernet.net (Lee Harr)
Дата:
> * area - arbitrary name for a collection of sites (optional)
>
> * site name for a collection of buildings (may only be one building)
> optional
>
> * building - a single building not optional name for a collection of rooms
>
> * zone - sub area of a building not optional name for a collection of rooms.
>
> * rooms (not listed)
>

CREATE TABLE room (room_id int, room_name text);
CREATE TABLE zone (zone_id int, zone_name text);
CREATE TABLE zone_room (zone_id int REFERENCES zone,
                        room_id int REFERENCES room);
CREATE TABLE building (building_id int, building_name text);
CREATE TABLE building_zone (building_id int REFERENCES building,
                            zone_id int REFERENCES zone);
CREATE TABLE site (site_id int, site_name text);
CREATE TABLE site_building (site_id int REFERENCES site,
                            building_id int REFERENCES building);
CREATE TABLE area (area_id int, area_name text);
CREATE TABLE area_site (area_id int REFERENCES area,
                        site_id int REFERENCES site);

I think I would do something like this. Try not to duplicate information
anywhere in your schema. This way, if you decide to move a site to a
different area or a room to a different building ;) you only need to
change it in one place.


>
> The main record here is Building. Areas and sites are optional ways of
> grouping buildings. Zones and rooms are required.
>
> Since the area and site are optional and arbitrary (you may change your
> organizational chart) I need a way of updating the children of that record
> to reflect the changes. I can do it easy enough in php, just don't know how
> with postgres.
>

Re: My brain hurts - update field based on value of another table's field

От
missive@frontiernet.net (Lee Harr)
Дата:
On Mon, 24 Sep 2001 11:22:40 -0700, Pat M <pmeloy@removethispart.home.com>:
> Woohoo! I got it. VIEWS! I can pre-do a pile of the work in a view and cut
> down on my scripting complexity a LOT. Instead of duplicating data all the
> time, create a view that includes all the parent record fields that I'd
> usually have to join manually in a script.
>

Sounds good. I use views like this also (to reduce complexity).

I used to always want to "do it all in one query."

That gets out of hand pretty quickly, but if you can encapsulate
different sections of the query in views...



Re: My brain hurts - update field based on value of another table's field

От
"Pat M"
Дата:
Ok, here's what they are

* area - arbitrary name for a collection of sites (optional)

* site name for a collection of buildings (may only be one building)
optional

* building - a single building not optional name for a collection of rooms

* zone - sub area of a building not optional name for a collection of rooms.

* rooms (not listed)


The main record here is Building. Areas and sites are optional ways of
grouping buildings. Zones and rooms are required.

Since the area and site are optional and arbitrary (you may change your
organizational chart) I need a way of updating the children of that record
to reflect the changes. I can do it easy enough in php, just don't know how
with postgres.

Here's an example of the php script. Probably won't indent properly...

$building_id is the current building
$sel_BuildingSite is the new site for this building

if ($but_UpdateBuilding) {
  $txt_buildingname=trim($txt_buildingname);
  if ($txt_buildingname) {
    $check=pg_Exec($connection,"select building_id from buildings where
building_id='$building_id';");
    if ($check) {
      if(pg_NumRows($check)==1) {
        $check=pg_Exec($connection,"
          update zones
          set zone_site='$sel_BuildingSite'
          where zone_building='$building_id';");
        $check=pg_Exec($connection,"
          update rooms
          set room_site='$sel_BuildingSite'
          where room_building='$building_id';");
        $check=pg_Exec($connection,"
          update buildings
          set building_name='$txt_buildingname',
          building_site='$sel_BuildingSite'
          where building_id='$building_id';");
      } else  {
        $error="Building ID Not found";
      }
    } else {
      $error="Error - check is null for this building_id!";
    }
  }
}

What I'd like to do is have the php script change the building_site field
value then have postgres update the zone_site and room_site fields by
itself. The more I read the docs (thus the brain pain) the more I'm
convinced I need a trigger and function. I just can't seem to figure out how
they work.

Yes, I will be moving to transactions and more error checking, just trying
to figure out how I'm going to do this before I get too involved 8)


"Lee Harr" <missive@frontiernet.net> wrote in message
news:9okp4i$2q58$1@news.tht.net...
> On Sun, 23 Sep 2001 03:56:50 GMT, Pat M <pmeloy@removethispart.home.com>
wrote:
> > I'm just a hobbyist so this is probably atroceous, but I'm trying to do
> > something like the following. Sorry its not in real SQL format. I know
how
> > to auto-update by referencing to a primary key of another table, but
what if
> > you want a field to change along with a non-unique field from a
different
> > table? Here's an example of what I mean
> >
> > table areas
> > -------------
> > area_id serial primary key
> > area_name text
> >
> > table sites
> > ----------
> > site_id serial primary key
> > site_name text
> > site_area int references areas on delete cascade
> >
> > table buildings
> > ------------
> > building_id serial primary key
> > building_name text
> > building_area int <--- needs to change when site_area changes
> > building_site int references sites on delete cascade
> >
>
> I think you would do this by _not_ having building_area at all.
> You have a building_site, which has a site_area. Is it possible
> to have a building_area that is _different_ from the site_area
> of the building_site? That does not make sense to me.
>
>
> > table zones
> > ------------
> > zone_id serial primary key
> > zone_name text
> > zone_area int  <--- needs to change when building_area changes
> > zone_site int  <--- needs to change when building_site changes
> > zone_building int references buildings on delete cascade
> >
>
> It is really difficult to help you not knowing what these "site" and
> "area" and "zone" things are.
>
>
> > None of the primary keys will be changing of course. But the area a
building
> > is in may change (area being an arbitrary designation, not municiple
> > boundaries), as may other fields as I work my way through building the
data.
> >
> > I know I can join things together in queries, avoiding all this, but it
gets
> > real confusing trying to join 12 tables, and slow... I want to be able
to
> > get the area from the buildings table and not have to join three tables
just
> > to find out what area it belongs to. Unless someone knows an easier way
than
> > select area_name from areas,sites,buildings where area_id=site_area and
> > site_id=building_id and building_id=1; Speed and easy queries are my
focus,
> > not disk space or ram savings.
> >
> > I looked at foreign keys, but they get uptight when the referenced field
> > isn't unique. On update cascade would have been wonderful 8(
> >
> > I looked at inheritance, but I don't think its what I had in mind.
> >
> > I'm thinking I have to delve into the horrors that are triggers and
> > functions...
> >
> > Any cool ideas floating around out there?
> >
> >



Re: My brain hurts - update field based on value of another table's field

От
"Pat M"
Дата:
Yeah, that part I know. The problem is that I'm going to have relations
tables up the wazoo. Been there before and I'd love to avoid it if at all
possible. I've managed (barely) to do joins on 11 tables at once and it was
freaking tough. I know duplication is supposed to be bad, but if I can get
the database to enforce references in the way I want, at least I won't
accidently get fields out of sync.

Mind you, my past experience with with 6.x... maybe now with selects for
"from" sources, it won't be so bad... hmmm

"Lee Harr" <missive@frontiernet.net> wrote in message
news:9olnc8$8sv$1@news.tht.net...
> > * area - arbitrary name for a collection of sites (optional)
> >
> > * site name for a collection of buildings (may only be one building)
> > optional
> >
> > * building - a single building not optional name for a collection of
rooms
> >
> > * zone - sub area of a building not optional name for a collection of
rooms.
> >
> > * rooms (not listed)
> >
>
> CREATE TABLE room (room_id int, room_name text);
> CREATE TABLE zone (zone_id int, zone_name text);
> CREATE TABLE zone_room (zone_id int REFERENCES zone,
>                         room_id int REFERENCES room);
> CREATE TABLE building (building_id int, building_name text);
> CREATE TABLE building_zone (building_id int REFERENCES building,
>                             zone_id int REFERENCES zone);
> CREATE TABLE site (site_id int, site_name text);
> CREATE TABLE site_building (site_id int REFERENCES site,
>                             building_id int REFERENCES building);
> CREATE TABLE area (area_id int, area_name text);
> CREATE TABLE area_site (area_id int REFERENCES area,
>                         site_id int REFERENCES site);
>
> I think I would do something like this. Try not to duplicate information
> anywhere in your schema. This way, if you decide to move a site to a
> different area or a room to a different building ;) you only need to
> change it in one place.
>
>
> >
> > The main record here is Building. Areas and sites are optional ways of
> > grouping buildings. Zones and rooms are required.
> >
> > Since the area and site are optional and arbitrary (you may change your
> > organizational chart) I need a way of updating the children of that
record
> > to reflect the changes. I can do it easy enough in php, just don't know
how
> > with postgres.
> >



Re: My brain hurts - update field based on value of another table's field

От
"Pat M"
Дата:
Yeah, that part I know. The problem is that I'm going to have relations
tables up the wazoo. Been there before and I'd love to avoid it if at all
possible. I've managed (barely) to do joins on 11 tables at once and it was
freaking tough. I know duplication is supposed to be bad, but if I can get
the database to enforce references in the way I want, at least I won't
accidently get fields out of sync.

Mind you, my past experience with with 6.x... maybe now with selects for
"from" sources, it won't be so bad... hmmm

"Lee Harr" <missive@frontiernet.net> wrote in message
news:9olnc8$8sv$1@news.tht.net...
> > * area - arbitrary name for a collection of sites (optional)
> >
> > * site name for a collection of buildings (may only be one building)
> > optional
> >
> > * building - a single building not optional name for a collection of
rooms
> >
> > * zone - sub area of a building not optional name for a collection of
rooms.
> >
> > * rooms (not listed)
> >
>
> CREATE TABLE room (room_id int, room_name text);
> CREATE TABLE zone (zone_id int, zone_name text);
> CREATE TABLE zone_room (zone_id int REFERENCES zone,
>                         room_id int REFERENCES room);
> CREATE TABLE building (building_id int, building_name text);
> CREATE TABLE building_zone (building_id int REFERENCES building,
>                             zone_id int REFERENCES zone);
> CREATE TABLE site (site_id int, site_name text);
> CREATE TABLE site_building (site_id int REFERENCES site,
>                             building_id int REFERENCES building);
> CREATE TABLE area (area_id int, area_name text);
> CREATE TABLE area_site (area_id int REFERENCES area,
>                         site_id int REFERENCES site);
>
> I think I would do something like this. Try not to duplicate information
> anywhere in your schema. This way, if you decide to move a site to a
> different area or a room to a different building ;) you only need to
> change it in one place.
>
>
> >
> > The main record here is Building. Areas and sites are optional ways of
> > grouping buildings. Zones and rooms are required.
> >
> > Since the area and site are optional and arbitrary (you may change your
> > organizational chart) I need a way of updating the children of that
record
> > to reflect the changes. I can do it easy enough in php, just don't know
how
> > with postgres.
> >



Re: My brain hurts - update field based on value of another table's field

От
"Pat M"
Дата:
Woohoo! I got it. VIEWS! I can pre-do a pile of the work in a view and cut
down on my scripting complexity a LOT. Instead of duplicating data all the
time, create a view that includes all the parent record fields that I'd
usually have to join manually in a script.

Areas
------------
area_id pkey
area_name

Sites
--------
site_id pkey
site_name
site_area references area_id

Buildings
------------
building_id pkey
building_name
building_site references site_id

create view building_view as select buildings.*,(select site_name from sites
where site_id=building_site) as building_site_name,(select area_id from
areas,sites where area_id=site_area and site_id=building_area) as
building_area_id,(select area_name from area,sites where area_id=site_area
and site_id=building_site) as building_area_name from buildings

Which gives me

buildings_view
---------------
building_id
building_name
building_site
building_site_name
building_area_id
building_area_name

If I change the area a site is associated with( say site_area is changed
from 32 to 122, the value is reflected in building_area_id without any
intervention on my part. Have I got this right? btw - the real schema has a
LOT more than just this, which is why my big effort to reduce the complexity
(wrapping my brain around) of queries in the web page scripts.




Re: My brain hurts - update field based on value of another table's field

От
"Pat M"
Дата:
Woohoo! I got it. VIEWS! I can pre-do a pile of the work in a view and cut
down on my scripting complexity a LOT. Instead of duplicating data all the
time, create a view that includes all the parent record fields that I'd
usually have to join manually in a script.

Areas
------------
area_id pkey
area_name

Sites
--------
site_id pkey
site_name
site_area references area_id

Buildings
------------
building_id pkey
building_name
building_site references site_id

create view building_view as select buildings.*,(select site_name from sites
where site_id=building_site) as building_site_name,(select area_id from
areas,sites where area_id=site_area and site_id=building_area) as
building_area_id,(select area_name from area,sites where area_id=site_area
and site_id=building_site) as building_area_name from buildings

Which gives me

buildings_view
---------------
building_id
building_name
building_site
building_site_name
building_area_id
building_area_name

If I change the area a site is associated with( say site_area is changed
from 32 to 122, the value is reflected in building_area_id without any
intervention on my part. Have I got this right? btw - the real schema has a
LOT more than just this, which is why my big effort to reduce the complexity
(wrapping my brain around) of queries in the web page scripts.