{"id":91823,"date":"2021-07-14T19:26:48","date_gmt":"2021-07-14T19:26:48","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=91823"},"modified":"2025-10-31T11:52:48","modified_gmt":"2025-10-31T11:52:48","slug":"typical-uses-oracle-sequences","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/oracle-databases\/typical-uses-oracle-sequences\/","title":{"rendered":"Typical uses of Oracle sequences"},"content":{"rendered":"<p><strong>The series so far:<\/strong><\/p>\n<ol>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sql\/oracle\/oracle-sequences-the-basics\/\">Oracle sequences: The basics<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sql\/oracle\/oracle-sequences-rac\/\">Oracle sequences: RAC<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/oracle-databases\/typical-uses-oracle-sequences\/\">Typical uses of Oracle sequences<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/oracle-databases\/oracle-sequences-12c-features-including-identity\/\">Oracle sequences \u2013 12c features including \u201cidentity\u201d<\/a>\u00a0<\/li>\n<\/ol>\n\n<p>So far, in this mini-series on sequences, I have described the basic mechanics of sequences in single-instance and multi-instance (RAC) systems. I\u2019ve explained the significance of setting the <strong><em>cache<\/em><\/strong> size in both cases and the <strong><em>order<\/em><\/strong> option for RAC. I\u2019ve demonstrated how using sequences as synthetic\/surrogate keys can lead to contention on the <em>\u201cright-hand\u201d<\/em>\/<em>\u201chigh-value\u201d<\/em> block of supporting indexes unless you take defensive actions. I\u2019ve also shown how one of the typical strategies has been embedded in recent versions of Oracle in the <strong><em>scale<\/em><\/strong> and <strong><em>extend<\/em><\/strong> options. In this article, I\u2019ll cover the most typical uses of Oracle sequences and highlight a couple of details of their behaviour that can cause some confusion.<\/p>\n<h2>Basic options<\/h2>\n<p>There are essentially only two things you can do with a sequence \u2013 you can ask for the \u201cnext value\u201d by referencing {sequence}.<code>nextval<\/code> or ask for the \u201ccurrent value\u201d by referencing {sequence}.<code>currval<\/code><strong><em>. <\/em><\/strong>By making a statement that simple, I\u2019ve already introduced a trap. The <code>nextval<\/code> for a sequence is a system-level request, the <code>currval<\/code> for a sequence is a session-level request. While <code>nextval<\/code> is a request for Oracle to generate the next available value according to the sequence definition, <code>currval<\/code> is a request to repeat the most recent value that the current session got on its most recent call to <code>nextval<\/code>. So, for example, this is what happens if you start a new SQL*Plus session and immediately call for {sequence}.<code>currval<\/code>:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SQL&gt; select s1.currval from dual;\nselect s1.currval from dual\n       *\nERROR at line 1:\nORA-08002: sequence S1.CURRVAL is not yet defined in this session<\/pre>\n<p>The session hasn\u2019t yet called (and saved locally) <code>s1.nextval<\/code>, which is why it says that <code>s1.currval<\/code> is not yet defined. (Personally, I think the error message could have been more explicit \u2013 e.g. commenting that there has been no previous call to <code>s1.nextval<\/code> in the session.) Reconnect, do a couple of calls for <code>s. nextval<\/code><strong><em>,<\/em><\/strong> then a couple for <code>s1.currval<\/code><strong><em>,<\/em><\/strong> and this is what happens:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SQL&gt; select s1.<strong>next<\/strong>val from dual;\n   NEXTVAL\n----------\n         3\n1 row selected.\nSQL&gt; select s1.<strong>next<\/strong>val from dual;\n   NEXTVAL\n----------\n         4\n1 row selected.\nSQL&gt; select s1.<strong>curr<\/strong>val from dual;\n   CURRVAL\n----------\n         4\n1 row selected.\nSQL&gt; select s1.<strong>curr<\/strong>val from dual;\n   CURRVAL\n----------\n         4\n1 row selected.<\/pre>\n<p>I\u2019ve used a <code>select from dual<\/code> to get a single sequence value but you can do multi-row selects to get a stream of sequence values, and you can also use simple assignments to get a value, e.g:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SQL&gt; declare\n  2          n1 number(6,0);\n  3  begin\n  4          n1 := s1.nextval;\n  5          dbms_output.put_line(n1);\n  6  end;\n  7  \/\n<strong>5<\/strong>\nPL\/SQL procedure successfully completed.<\/pre>\n<p>If you enable tracing on this anonymous pl\/sql block, though, you will find that behind the scenes, Oracle will have executed a simple <code>select s1.nextval from dual<\/code> to acquire the value.<\/p>\n<p>The basic rule of sequences is that you write code to generate a \u201crowsource\u201d, and the sequence generator is called once per row; this produces results that aren\u2019t always quite what you anticipate. Consider the position where I start a new session and continue using sequence <code>s1<\/code> just after the point where I ended in the previous example, and execute the following three statements:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SQL&gt; select s1.currval, s1.nextval from dual;\nSQL&gt; select s1.nextval, s1.currval from dual;\nSQL&gt; select s1.nextval, s1.nextval, s1.nextval from dual;<\/pre>\n<p>Looking at the first statement, which (apparently) calls <code>currval<\/code> before it calls <code>nextval<\/code><strong><em>,<\/em><\/strong> you might expect it to fail with the ORA-08002 error, but it doesn\u2019t.<\/p>\n<p>Looking at the second statement, you might expect the call to <code>currval<\/code> to report the previous value acquired by this session while <code>nextval<\/code> reports the next value from the global cache, but it doesn\u2019t.<\/p>\n<p>Looking at the last statement, you might expect to see three consecutive sequence values, but you won\u2019t.<\/p>\n<p>The results of the three statements are as following:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SQL&gt; select s1.currval, s1.nextval from dual;\n   CURRVAL    NEXTVAL\n---------- ----------\n         6          6\nSQL&gt; select s1.nextval, s1.currval from dual;\n   NEXTVAL    CURRVAL\n---------- ----------\n         7          7\nSQL&gt; select s1.nextval, s1.nextval, s1.nextval from dual;\n   NEXTVAL    NEXTVAL    NEXTVAL\n---------- ---------- ----------\n         8          8          8<\/pre>\n<p>There is one call to the sequence generator for each row which is why 8 appears three times. If you include both <code>currval<\/code> and <code>nextval<\/code> in the select list, then <code>nextval<\/code> is called, and the return value used for both the <code>nextval<\/code> and the <code>currval<\/code>.<\/p>\n<p>Some of the questions people ask about the \u201cunexpected\u201d behaviour of sequences can be answered very easily once the connection between <em>\u201crows selected\u201d<\/em> and <em>\u201ccalls to nextval\u201d<\/em> is clear. However, this doesn\u2019t mean that \u201cif you can write a select clause you can select a sequence\u201d; there are cases where your code will run into the exception: <em>ORA-02287: sequence number not allowed here<\/em>, for example:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SQL&gt; create or replace view v1 \n  2  as\n  3  select object_name, owner, s1.nextval\n  4  from t1\n  5  \/\nselect object_name, owner, s1.nextval\n                              *\nERROR at line 3:\nORA-02287: sequence number not allowed here<\/pre>\n<p>There are also cases where adding a sequence to the select list has a much greater effect than just being \u201canother column.\u201d Distributed queries, for example, may change their execution plan quite dramatically because the addition of a sequence has changed a query from \u201cremote only\u201d to genuinely distributed.<\/p>\n<h2>Sequences and DML<\/h2>\n<p>The most common use of a sequence is probably as the source of a surrogate (or synthetic) key, so you may see code like the following in an ETL or other large batch process:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">insert into production_table \nselect  s1.nextval, \u2026\nfrom    staging_table\nwhere\t   ...<\/pre>\n<p>An important point to be aware of when you do this type of thing is that sequences and parallelism don\u2019t co-operate very well. It would be very easy to decide that you needed to increase the speed at which you were generating data and that simply using parallel execution would help and write something like:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">insert  \/*+ parallel(6) *\/ into production_table \nselect  s1.nextval, \u2026\nfrom    staging_table\nwhere\t   ...<\/pre>\n<p>A common mistake that people make at this point is to forget that parallel DML is not enabled by default, so if you want the insert to operate with DOP (degree of parallelism) 6, then you also need to execute<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">alter session enable parallel dml;<\/pre>\n<p>(and don\u2019t forget to disable it afterwards).<\/p>\n<p>However, having flagged up this reminder on parallel DML, I\u2019m now going to point out that if your code uses sequences, you might be in exactly the position where you want the select to run parallel, but the insert to run serially. Remember that <code>sequence.nextval<\/code> has to update a specific row in the <code>seq$<\/code> table from time to time, and (more importantly) every call to <code>nextval<\/code> has to access the dictionary cache entry for that particular sequence. That means competition for dictionary cache mutexes (or latches for older versions of Oracle). You may find that the nominal benefit of parallel execution disappears in hugely increased CPU consumption due to contention.<\/p>\n<h3>End-user DML<\/h3>\n<p>In high-precision code (typically end-user facing( you may do something which requires re-use of a primary key as a foreign key to another table: <strong><em>orders<\/em><\/strong> and <strong><em>order_lines,<\/em><\/strong> for example, and there have been a few variations in method over the years. For example:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">select s1.nextval into :local_variable from dual;\ninsert into orders (id, \u2026) values(:local_variable, \u2026);\ninsert into order_lines(id_ord, line, \u2026) values(:local_variable, \u2026)<\/pre>\n<p>Of course, this type of approach might have been necessary when it wasn\u2019t possible to use a sequence <code>nextval<\/code> as the default for a column. But now we can, so we could have something like:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk \">create sequence s1 start with 1e6 cache 1e3;\ncreate table orders (\n        id number(8,0) default s1.nextval primary key, \n        date_made date not null\n);\ncreate table order_lines(\n        id_ord     number(8,0) not null references orders, \n        line#      number(4,0) not null, \n        id_product number(8,0) not null\n);\ninsert into orders     (date_made) values (sysdate);\ninsert into order_lines(id_ord, line#, id_product) \n                                   values(s1.currval, 1, 999);<\/pre>\n<p>This does require the programmer to know that the orders table has its primary key generated by a call to a sequence called <strong><em>s1. <\/em><\/strong>Be aware of Oracle\u2019s syntax, which allows you to call <code>sequence.currval<\/code> after (even implicitly) you\u2019ve called <code>sequence.nextval<\/code>. A slightly more generic, or programmer-friendly, variant might return the generated id to the client code:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode:true\">variable m_id number\ninsert into orders (date_made) values (sysdate) returning id into :m_id;\ninsert into order_lines(id_ord, line#, id_product) values(:m_id, 1, 999);<\/pre>\n<p>If you start using the 12c \u201cidentity\u201d type, you probably have to adopt this approach to retrieve the value you\u2019ve inserted. You\u2019re not supposed to know that, under the covers, Oracle is simply using a sequence to supply a value, and you certainly should not assume you can work out the name of that sequence and call for its <code>currval<\/code>.<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">create table orders (\n        id number(8,0) \n                generated always as identity start with 1e6 cache 1e3\n                primary key,\n        date_made date not null\n);<\/pre>\n<h3>The Merge Command<\/h3>\n<p>An increasingly popular strategy for updating one table from another is to use the <code>merge<\/code> command, which has the following skeleton:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">merge into target \nusing source\non target.cols = source.cols\nwhen matched then \n\tupdate set {target_columns} = {source columns} where \u2026\n\tdelete where \u2026\nwhen not matched then\n\tInsert ({target columns}) values({source columns}) where \u2026<\/pre>\n<p>A couple of points to watch out for in general with the merge command:<\/p>\n<ul>\n<li>Performance: rather than using table names for the <strong><em>source<\/em><\/strong> and <strong><em>target<\/em><\/strong> data sets, see if you can use in-line views with the minimum number of columns selected from the source and target. There is an oddity with the merge command that (unlike other SQL statements) it doesn\u2019t automatically project only the columns that will be used \u2013 this means that it may carry far more intermediate data than it needs to. (See, for example, this <a href=\"https:\/\/jonathanlewis.wordpress.com\/2016\/06\/06\/merge-precision\/\">post<\/a>.)<\/li>\n<li>Determinism: you should view the merge command in much the same way as you would updateable join views. The <code>ON<\/code> clause has a uniqueness requirement \u2013 there should be at most one row in the <strong><em>source<\/em><\/strong> table for any row in the <strong><em>target<\/em><\/strong> table, though there can be many rows in the target table for each row in the source table. If you don\u2019t meet this requirement, updateable join views will raise a parse-time error of <strong><em>ORA-01779<\/em><\/strong> relating to <em>\u201cnon key preserved table\u201d<\/em>. With the equivalent data, the merge command may work, or it may raise a run-time error of <em>\u201cORA-30926: unable to get a stable set of rows in the source tables\u201d<\/em>). The effect is not deterministic. (Side note: in Oracle 21c, the parse-time error has been removed, and updateable join views also follow the run-time mechanism.)<\/li>\n<\/ul>\n<p>The key reason for picking the merge command is that it\u2019s a nice example of how unpredictable the results of using a sequence might be \u2013 and it has also appeared a couple of times quite recently on various Oracle forums for exactly this reason.<\/p>\n<p>Here\u2019s a little script to create a small demonstration data set. I\u2019m going to have a <em>new data<\/em> table which is going to be merged with an <em>old data<\/em> table. The old data will consist of just 50 rows with odd-numbered IDs between 1 and 99; the new data will consist of 100 rows with IDs (both odd and even) from 1 to 100. I\u2019ll be updating based on matching IDs and inserting where there is no match.<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">create sequence s1 minvalue 1001 start with 1001 cache 1000;\ncreate table old_data\nas\nwith generator as (\n        select \n                rownum id\n        from dual \n        connect by \n                level &lt;= 1e4\n)\nselect\n        2 * rownum - 1                  id,\n        'OLD'                           status,\n        cast(0 as number(4,0))          seq_value,\n        lpad('x',100,'x')               padding\nfrom\n        generator       v1\nwhere\n        rownum &lt;= 50\n;\nalter table old_data add constraint od_pk primary key(id);\ncreate table new_data\nas\nwith generator as (\n        select \n                rownum id\n        from dual \n        connect by \n                level &lt;= 1e4\n)\nselect\n        rownum                          id,\n        'NEW'                           status,\n        cast(0 as number(4,0))          seq_value,\n        lpad('x',100,'x')               padding\nfrom\n        generator       v1\nwhere\n        rownum &lt;= 100\n;\nalter table new_data add constraint nd_pk primary key(id);<\/pre>\n<p>I\u2019ll run three separate tests: in one, I\u2019ll use only the <code>when matched update<\/code> clause, in the second, I\u2019ll use only the <code>when not matched insert<\/code> clause, and finally, I\u2019ll run a test with both clauses. To keep things simple, I won\u2019t use the <code>where<\/code> or <code>delete<\/code> clauses. Here\u2019s the statement with both clauses:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">merge into\n        old_data od\nusing   new_data nd\non      (nd.id = od.id)\nwhen matched then\n        update set seq_value = s1.nextval, status ='UPD'\nwhen not matched then\n        insert (id, status, seq_value, padding)\n        values (nd.id, 'NEW',  s1.nextval, nd.padding)\n;<\/pre>\n<p>In this case, I have 50 rows in the old data that will match and 50 that will not match. I expect to update 50 rows with <code>s1.nextval<\/code> and insert 50 rows with <strong><em>s1.nextval<\/em><\/strong> as the inserted <code>sql_value<\/code> column. Since the sequence <strong><em>s1<\/em><\/strong> starts with 1,001, I expect to get to 1,100 by the end of this <code>merge<\/code><strong><em>, <\/em><\/strong>and that\u2019s exactly what happens.<\/p>\n<p>The question is: can I say anything about the order in which the sequence values have been used? Will I have 1001 \u2013 1050 in the \u2018UPD\u2019 rows and 1051 \u2013 1100 in the \u2018NEW\u2019 rows, or will the value alternate between the two? A simple query to <code>select id, status, seq_value from old_data order by id<\/code> supplies the (initial) answer:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91824\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-20.png\" alt=\"The results of old_data\" width=\"244\" height=\"158\" \/><\/p>\n<p>The pattern continues through the entire ordered data set \u2013 and if you check the execution plan for the query, you may be able to infer why that appears to be true in this case:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91825\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-21.png\" alt=\"Execution plan \" width=\"764\" height=\"251\" \/><\/p>\n<p>The underlying mechanism of the merge command is to join the old and new data sets. If there\u2019s a <code>when not matched<\/code> clause, it must be an outer join. In this case, Oracle has decided to do a \u201cright outer\u201d hash join, which means it has used the (smaller) <code>old_data<\/code> data set as the <code>build<\/code> table and a table scan of the <code>new_data<\/code> table to probe the build table. Since every row from <code>new_data<\/code> survives the probe, the sequence numbers are applied in order to the rows in the <code>new_data<\/code> table (which, thanks to my original CTAS) gives the impression that the sequence and the id values are in sync.<\/p>\n<p>But what would happen if Oracle decided to do the outer join the other way round? I checked the outline Information for this plan and changed a <code>swap_join_Inputs()<\/code> hint to a <code>no_swap_join_inputs()<\/code> hint to make this happen, changing the last three lines of the plan to:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91826\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-22.png\" alt=\"Last three lines of the plan \" width=\"682\" height=\"65\" \/><\/p>\n<p>And this is how the updated data looked:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91827\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-23.png\" alt=\"Image showing the updated data\" width=\"211\" height=\"155\" \/><\/p>\n<p>There is still a pattern. The odd IDs, when ordered, produce the sequence values 1001 to 1050 in order; again the apparent lock-step is a side effect of the original CTAS. However, the newly inserted even IDs show a random ordering of the <code>seq_value<\/code> column because of how the outer hash join works when the build table is generated from the preserved table.<\/p>\n<p>The key feature here is that there\u2019s a degree of unpredictability of how your newly arriving data may end up with sequence numbers that don\u2019t seem to match the order of arrival very well. In a relational database, this shouldn\u2019t really come as a surprise, but if it seems to have behaved \u201cnicely\u201d for a long time, it can be a big shock when things suddenly change simply because of a barely noticeable change in the execution plan.<\/p>\n<p>There\u2019s more, though, because sequence numbers get lost. Again, the many variations of the merge command (with <code>where<\/code> and <code>delete<\/code> clauses, in particular) can show several different ways in which values disappear. The simplest option is simply to create a merge command without a <code>when matched<\/code> clause.<\/p>\n<p>Running the test using only the <code>when not matched<\/code> clause, the resulting output from the ordered result from the <code>old_data<\/code> table as follows:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-91828\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-24.png\" alt=\"ordering the results of old_data\" width=\"228\" height=\"172\" \/><\/p>\n<p>The pattern continues through the entire data set. Only the even sequence values have been used, and the odd sequence values are \u201clost\u201d. Going back to my earlier comment: <em>\u201cyou write code to generate a \u201crow source\u201d, and the sequence generator is called once per row.\u201d<\/em> However, it is just a little more subtle than that. In this case, the critical \u201crow source\u201d is the output from the hash join, and the sequence <code>nextval<\/code> is generated as each row is passed up from the hash join. Then the merge command splits the row source into two parts, the update stream and the insert stream and (in this example) discards the update stream losing half the sequence numbers.<\/p>\n<h2>Remote queries<\/h2>\n<p>Another older example of the surprises you can get if you treat sequences as if they were \u201cjust another column\u201d is the trap of moving data from one database to another. For example, you might have some code that does a fairly simple:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">insert into local table\nselect  {list of columns}\nfrom    {list of remote tables}\nwhere   {join and filter conditions}\n;<\/pre>\n<p>After a little tweaking, you find that you have a good execution plan, and the query runs efficiently as a \u201cfully remote\u201d query. Your next step is to add a (local) sequence number to the select list, but the performance takes a catastrophic nose-dive because the query is now a distributed query, and the optimizer has to optimize it locally and fails to come up with a plan that includes a remote join. An example I created for a recent note on my blog showed a plan that started efficiently like this (notice the zero selected in the second line of the statement):<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">insert into t3 (id1, id2, n0, n1, n2, v1, v2) select  t1.id,  t2.id,\n0,  t1.n1,  t2.n2,  t1.v1,  t2.v2 from  t1@orclpdb@loopback t1,\nt2@orclpdb@loopback t2 where  t2.id = t1.id<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"589\" height=\"190\" class=\"wp-image-91829\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-25.png\" \/><\/p>\n<p>but changed to the following when the zero was replaced by a call to a local sequence:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">insert into t3 (id1, id2, n0, n1, n2, v1, v2) select  t1.id,  t2.id,\ns1.nextval,  t1.n1,  t2.n2,  t1.v1,  t2.v2 from  t1@orclpdb@loopback\nt1,  t2@orclpdb@loopback t2 where  t2.id = t1.id<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"710\" height=\"305\" class=\"wp-image-91830\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/07\/word-image-26.png\" \/><\/p>\n<p>There are workarounds to this problem, but if you don\u2019t look carefully at the things that change when you introduce a sequence, you may find that a test case on a small development system simply isn\u2019t acceptable for a full-scale production system.<\/p>\n<h2>Typical uses of Oracle sequences<\/h2>\n<p>I\u2019ve covered a few of the commoner examples of using sequences and highlighted four general points;<\/p>\n<p>First, all you can ever do is, essentially, select the <code>nextval<\/code> and\/or the <code>currval<\/code> of a sequence. If a statement includes a row source that uses a sequence, then <code>nextval<\/code> will be actioned before <code>currval<\/code><em>,<\/em> and <code>nextval<\/code> will only be actioned once per row in that row source.<\/p>\n<ul>\n<li>There are row sources that do not permit the use of sequences.<\/li>\n<li>For complex execution plans, a change in the plan may give the appearance of randomizing the order of sequence values in the final output, and some plans may even give the impression that sequence values have \u201cgone missing\u201d.<\/li>\n<li>Finally, the presence of a sequence in a query may dictate the overall strategy of the execution plan, with the particular example of a \u201cfully remote\u201d query changing to a \u201cdistributed\u201d query.<\/li>\n<\/ul>\n<p>A sequence is not just another column or function \u2013 it carries some special baggage.<\/p>\n<p>In the final article in this mini-series, I\u2019ll finish with a few more comments on the latest features of sequences from 12c onwards.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Oracle sequences supply unique numbers that can be used when populating tables. In this article, Jonathan Lewis explains the typical uses of Oracle sequences.&hellip;<\/p>\n","protected":false},"author":101205,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[53,143533],"tags":[145415,124952],"coauthors":[39048],"class_list":["post-91823","post","type-post","status-publish","format-standard","hentry","category-featured","category-oracle-databases","tag-oracle-sequences","tag-redgate-deploy"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/91823","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/101205"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=91823"}],"version-history":[{"count":8,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/91823\/revisions"}],"predecessor-version":[{"id":107794,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/91823\/revisions\/107794"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=91823"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=91823"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=91823"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=91823"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}