Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.tools -> Re: SQL Update

Re: SQL Update

From: Thomas J. Kyte <tkyte_at_us.oracle.com>
Date: 2000/06/20
Message-ID: <8io05l$9t6$1@nnrp1.deja.com>

In article <394D8B51.60B06806_at_blarg.net>,   Dinendra <dinendra_at_blarg.net> wrote:
> Thomas,
> Couple of questions on your solution:
> 1)In your second solution why do you have a clause "where exists"?
>
> update name set columnName = ( select value from lookup where
> lookup.keyname = name.keyname and otherColumn = :other_value )
> where exists
> ( select value from lookup where lookup.keyname = name.keyname and
> otherColumn = :other_value )
>
> Since you already have the condition "lookup.keyname = name.keyname
 and
> otherColumn = :other_value " I would think that is sufficient for
 finding
> matching rows.
>

if there are any rows in NAME that do not have a match in LOOKUP, the co-related subquery will have the effect of setting the columnName column to NULL when it cannot find a match. The where clause makes it so we update only rows that have a match instead of EVERY row.

this is why i like to update the JOIN:
> > scott_at_ORA734.WORLD> update
> > 2 ( select columnName, value
> > 3 from name, lookup
> > 4 where name.keyname = lookup.keyname
> > 5 and lookup.otherColumn = :other_value )
> > 6 set columnName = value
> > 7 /

not use a correlated subquery with the WHERE EXISTS.

> 2)Is there a way to update a column in a table by joining it with two
> other tables?
> For example:
>
> update table1 set table1.xz = (select table3.xz from table2,table3
> where
> table1.xx = table2.xx and table2.xy =table3.xy)
>
> Assuming:
> table1 has rows - xx, xz
> table2 has rows - xx, xy
> table3 has rows -xy, xz
>
> When I tried the above statement from a PL/SQL procedure it seems to
> update all the rows in table1 regardless of the join condition. I am
> probably missing something here.
>

that is not an example of updating a join. that is an example of using a correlated subquery to update table1. Since there is no predicate to restrict the number of rows scanned in table1 in the update -- every row will in fact be updated by definition.

If you wanted to update the join, it would look like this:

ops$tkyte_at_8i> create table t1 ( xx int, xz int );

Table created.

ops$tkyte_at_8i> create table t2 ( xx int primary key, xy int );

Table created.

ops$tkyte_at_8i> create table t3 ( xy int primary key, xz int );

Table created.

ops$tkyte_at_8i>
ops$tkyte_at_8i>
ops$tkyte_at_8i> update
  2   (select table1.xz t1_xz, table3.xz t3_xz
  3      from t1 table1, t2 table2, t3 table3
  4     where table1.xx = table2.xx
  5           and table2.xy =table3.xy)

  6 set t1_xz = t3_xz;

0 rows updated.

if you wanted to use the correlated subquery it would look like this:

update table1
  set table1.xz = (select table3.xz

                     from table2,table3
                    where table1.xx = table2.xx
                      and table2.xy =table3.xy)
WHERE EXISTS (select table3.xz
                from table2,table3
               where table1.xx = table2.xx
                 and table2.xy =table3.xy)

> Thanks
> -Deepa
>
> Thomas J. Kyte wrote:
>
> > In article <3948e631_at_news.mdh.se>,
> > "Ulf Körnings" <ulf.kornings_at_mdh.se> wrote:
> > >
> > > Hi!
> > >
> > > I would like to do somthing like this in SQL:
> > >
> > > update table_a,table_b set table_a.data=table_b.data where
> > > table_a.kod=table_b.kod
> > >
> > > Is it possible?
> > >
> > > /Ulf
> > >
> > >
> > There are at least 2 ways to perform this sort of co-related
> > update correctly. I'll show my preferred method (update a join)
> > and then another method that'll work if you cannot put a unique
> > constraint on LOOKUP(keyname) (which is needed for the join
> > update).
> >
> > Here are the test tables:
> >
> > scott_at_ORA734.WORLD> create table name
> > 2 ( keyname int,
> > 3 columnName varchar2(25)
> > 4 )
> > 5 /
> > Table created.
> >
> > scott_at_ORA734.WORLD> create table lookup
> > 2 ( keyname int PRIMARY KEY,
> > 3 value varchar2(25),
> > 4 otherColumn int
> > 5 )
> > 6 /
> > Table created.
> >
> > scott_at_ORA734.WORLD> insert into name values ( 100, 'Original
> > Data' );
> > 1 row created.
> >
> > scott_at_ORA734.WORLD> insert into name values ( 200, 'Original
> > Data' );
> > 1 row created.
> >
> > scott_at_ORA734.WORLD> insert into lookup values ( 100, 'New Data',
> > 1 );
> > 1 row created.
> >
> > scott_at_ORA734.WORLD> commit;
> > Commit complete.
> >
> > here is the "other_value" parameter you are using in the above
> > update you attempted...
> >
> > scott_at_ORA734.WORLD> variable other_value number
> > scott_at_ORA734.WORLD> exec :other_value := 1
> > PL/SQL procedure successfully completed.
> >
> > scott_at_ORA734.WORLD> select * from name;
> >
> > KEYNAME COLUMNNAME
> > ---------- -------------------------
> > 100 Original Data
> > 200 Original Data
> >
> > Here we update a join. We can only modify the columns in one
> > of the tables and the other tables we are *NOT* modifying must
> > be "key preserved" -- that is, we must be able to verify that at
> > most one record will be returned when we join NAME to this other
> > table. In order to do that, keyname in LOOKUP must either be a
> > primary key or have a unique constraint applied to it...
> >
> > scott_at_ORA734.WORLD> update
> > 2 ( select columnName, value
> > 3 from name, lookup
> > 4 where name.keyname = lookup.keyname
> > 5 and lookup.otherColumn = :other_value )
> > 6 set columnName = value
> > 7 /
> >
> > 1 row updated.
> >
> > scott_at_ORA734.WORLD> select * from name;
> >
> > KEYNAME COLUMNNAME
> > ---------- -------------------------
> > 100 New Data
> > 200 Original Data
> >
> > See, the other data is untouched and only the rows we wanted
> > are updated..
> >
> > scott_at_ORA734.WORLD> rollback;
> > Rollback complete.
> >
> > scott_at_ORA734.WORLD> select * from name;
> >
> > KEYNAME COLUMNNAME
> > ---------- -------------------------
> > 100 Original Data
> > 200 Original Data
> >
> > Now, this way will work with no constraints on anything -- you
> > do not need the primary key/unique constraint on lookup (but you
> > better be sure the subquery returns 0 or 1 records!).
> >
> > It is very much like your update, just has a where clause so
> > that only rows that we find matches for are actually updated...
> >
> > scott_at_ORA734.WORLD> update name
> > 2 set columnName = ( select value
> > 3 from lookup
> > 4 where lookup.keyname = name.keyname
> > 5 and otherColumn = :other_value )
> > 6 where exists ( select value
> > 7 from lookup
> > 8 where lookup.keyname = name.keyname
> > 9 and otherColumn = :other_value )
> > 10 /
> >
> > 1 row updated.
> >
> > scott_at_ORA734.WORLD> select * from name;
> >
> > KEYNAME COLUMNNAME
> > ---------- -------------------------
> > 100 New Data
> > 200 Original Data
> >

--
Thomas Kyte (tkyte_at_us.oracle.com) Oracle Service Industries
Howtos and such: http://osi.oracle.com/~tkyte/index.html
Oracle Magazine: http://www.oracle.com/oramag
Opinions are mine and do not necessarily reflect those of Oracle Corp


Sent via Deja.com http://www.deja.com/
Before you buy.
Received on Tue Jun 20 2000 - 00:00:00 CDT

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US