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: Updates with sequences : not allowed ?

Re: Updates with sequences : not allowed ?

From: Thomas J. Kyte <tkyte_at_us.oracle.com>
Date: 2000/04/22
Message-ID: <8dqr2u$gr5$1@nnrp1.deja.com>

In article <39000E6C.69747F7_at_uhb.fr>,
  Joel SEGUILLON <Joel.Seguillon_at_uhb.fr> wrote:
> Thanks again,
> That's the second time you help me :). I tried to improve your idea
> with a function like :
>
> 1 create or replace function get_s
> 2 (seq_name IN VARCHAR2(30))
> 3 return number
> 4 as
> 5 l_s number;
> 6 begin
> 7 select seq_name.currval into l_s from dual;
> 8 return l_s
> 9* end;
>
> But it does not work... and compiles with errors :(. Anyone has got
 a
> better idea ?
>

you would need to use dynamic sql to do this.

You cannot do dynamic sql in PLSQL to be called in a SQL statement until version 8.1 (at which time, this function would not be necessary at all).

You cannot genericize this in version 8.0 and before.

You would need to use dynamic sql to do this, it would look like this in 8.0 and before:

ops$tkyte_at_8.0> create or replace function get_currval( p_sname in varchar2 ) return number
  2 as

  3      l_theCursor        integer default dbms_sql.open_cursor;
  4      l_columnValue    number default NULL;
  5      l_status        integer;
  6  begin
  7      dbms_sql.parse(  l_theCursor,
  8                      'select ' || p_sname || '.currval from dual',
  9                       dbms_sql.native );
 10
 10      dbms_sql.define_column( l_theCursor, 1, l_columnValue );
 11      l_status := dbms_sql.execute(l_theCursor);
 12      if ( dbms_sql.fetch_rows(l_theCursor) > 0 )
 13       then
 14             dbms_sql.column_value( l_theCursor, 1, l_columnValue );
 15      end if;
 16      dbms_sql.close_cursor( l_theCursor );
 17      return l_columnValue;

 18 end ;
 19 /

Function created.

ops$tkyte_at_8.0>
ops$tkyte_at_8.0> drop sequence my_seq
  2 /

Sequence dropped.

ops$tkyte_at_8.0> create sequence my_seq
  2 /

Sequence created.

ops$tkyte_at_8.0>
ops$tkyte_at_8.0>
ops$tkyte_at_8.0> select my_seq.nextval from dual;

   NEXTVAL


         1

ops$tkyte_at_8.0> select my_seq.nextval from dual;

   NEXTVAL


         2

ops$tkyte_at_8.0>
ops$tkyte_at_8.0> exec dbms_output.put_line( get_currval( 'my_seq' ) ) 2
PL/SQL procedure successfully completed.

ops$tkyte_at_8.0>
ops$tkyte_at_8.0> select get_currval( 'my_seq' ) from dual   2 /
select get_currval( 'my_seq' ) from dual

       *
ERROR at line 1:
ORA-06571: Function GET_CURRVAL does not guarantee not to update database

so that shows how to dynamic refer to the sequence but also shows *you cannot call it* from SQL.

In Oracle8i, release 8.1 and up, this would be:

ops$tkyte_at_dev8i> create or replace function get_currval( p_sname in varchar2 ) return number
  2 as
  3 l_columnValue number default NULL;   4 begin
  5 execute immediate 'select ' || p_sname || '.currval from dual' INTO l_columnValue;
  6 return l_columnValue;
  7 end ;
  8 /

Function created.

ops$tkyte_at_dev8i>
ops$tkyte_at_dev8i> drop sequence my_seq
  2 /

Sequence dropped.

ops$tkyte_at_dev8i> create sequence my_seq
  2 /

Sequence created.

ops$tkyte_at_dev8i>
ops$tkyte_at_dev8i>
ops$tkyte_at_dev8i> select my_seq.nextval from dual;

   NEXTVAL


         1

ops$tkyte_at_dev8i> select my_seq.nextval from dual;

   NEXTVAL


         2

ops$tkyte_at_dev8i>
ops$tkyte_at_dev8i> exec dbms_output.put_line( get_currval( 'my_seq' ) ) 2

PL/SQL procedure successfully completed.

ops$tkyte_at_dev8i>
ops$tkyte_at_dev8i> select get_currval( 'my_seq' ) from dual   2 /

GET_CURRVAL('MY_SEQ')


                    2

The syntax is better, it can dynamically do SQL and understand that this sql does NOT write to the database state (it can see because of the INTO its a select, not an update). However, in your case, this will not be necessary as the sequence can be used directly.

> "Thomas J. Kyte" wrote:
> >
> > In article <38FF2983.7A53C851_at_uhb.fr>,
> > Joel SEGUILLON <Joel.Seguillon_at_uhb.fr> wrote:
> > > Hi,
> > > I am still fighting with my SQL scripts and i have a new
 problem.
 I'm
> > > just trying to do something like :
> > > Update table1
> > > set field1 = 'myvalue'
> > > where field2 = table2_sequence.CURRVAL;
> > > But SQLplus answers me : ORA-02287 : sequence number not allowed
 here.
> > > I tryed to use something like :
> > > ... where field2 = (select last_number from user_sequences
 where
> > > sequence_name = 'table2');
> > > But it does not work : currval and last_number do not seem to
 be the
> > > same (i had currval = 30 and last_number = 41 :) ).
> > >
> > > If anyone has got an idea...
> > > Thanks.
> > >
> >
> > this is fixed in 8.1 -- you can use the currval directly. Until
 then,
> > you might be able to use something like the following:
> >
> > scott_at_ORA734.WORLD> create table t ( x int, y int );
> > Table created.
> >
> > scott_at_ORA734.WORLD> create sequence s;
> > Sequence created.
> >
> > scott_at_ORA734.WORLD>
> > scott_at_ORA734.WORLD> create or replace function get_s return number
> > 2 as
> > 3 l_s number;
> > 4 begin
> > 5 select s.currval into l_s from dual;
> > 6 return l_s;
> > 7 end;
> > 8 /
> >
> > Function created.
> >
> > scott_at_ORA734.WORLD> insert into t values ( s.nextval, 0 );
> > 1 row created.
> >
> > scott_at_ORA734.WORLD> update t set y = y+1 where x = s.currval;
> > update t set y = y+1 where x = s.currval
> > *
> > ERROR at line 1:
> > ORA-02287: sequence number not allowed here
> >
> > scott_at_ORA734.WORLD> update t set y = y+1 where x = ( select get_s
 from
> > dual );
> >
> > 1 row updated.
> >
> > --
> > Thomas Kyte tkyte_at_us.oracle.com
> > Oracle Service Industries
> > http://osi.oracle.com/~tkyte/index.html
> > --
> > Opinions are mine and do not necessarily reflect those of Oracle
 Corp
> >
> > Sent via Deja.com http://www.deja.com/
> > Before you buy.
>

--
Thomas Kyte                              tkyte_at_us.oracle.com
Oracle Service Industries
http://osi.oracle.com/~tkyte/index.html
--
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 Sat Apr 22 2000 - 00:00:00 CDT

Original text of this message

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