Systems Engineering and RDBMS

  • Click Here for Decipher's Homepage


  • Categories

  • Questions?

    Please send your wish list of things that you would like us to write about or if you have suggestions to help improve this blog site. You can send all questions/suggestions to: Blog Support
  • Archives

  • Blog Stats

    • 7,604,276 Views

Archive for July 25th, 2007

Re-sequencing a number column in Oracle

Posted by decipherinfosys on July 25, 2007

This post explains how one can re-sequence a number column in Oracle. Let’s take a hypothetical example and walk through it. Suppose that a big departmental store has its own stocking facility and each shelf in the facility is identified as a location (STORE_LOCN_ID) in which more than one item can be stored. Whenever a new item is added to the shelf, a new record is created in the table by increasing the value in the locn_seq column by 1. Whenever actual quantity (actl_qty) for the item decreases to 0, record is deleted from the table. Following is the table structure to hold the data of the items in the facility.

CREATE TABLE STORE_STOCK
(
STORE_STOCK_ID NUMBER(9) NOT NULL,
STORE_LOCN_ID VARCHAR2(10) NOT NULL,
LOCN_SEQ NUMBER(3) NOT NULL,
ITEM_NO VARCHAR2(10) NOT NULL,
ACTL_QTY NUMBER(10) DEFAULT 0 NOT NULL,
MAX_QTY NUMBER(10) DEFAULT 0 NOT NULL,
CONSTRAINT PK_STORE_STOCK PRIMARY KEY(STORE_STOCK_ID)
)
/

There is also a unique index on STORE_LOCN_ID + LOCN_SEQ column combination since that forms the business key to this table. Please note that the LOCN_SEQ column has been defined as NUMBER(3) in this example to demonstrate how to re-sequence the numbers. In an actual design, you may want to increase the length of that column. The example is so chosen to illustrate the req-sequencing using analytic function in Oracle.

And for this example, this is how a set of data looks like in this table:

STORE_STOCK_ID STORE_LOCN LOCN_SEQ
————– ———- ———-
1 A100000001 5
4 A100000001 11
2 A100000001 18
6 A100000001 35
3 A100000001 99
5 A100000001 245
7 A100000001 803
8 A100000001 922
9 A100000001 945
10 A100000001 999
11 A100000002 1
12 A100000002 2
13 A100000002 15
14 A100000002 411
15 A100000002 999
16 A100000003 1
17 A100000004 1
18 A100000004 3
19 A100000004 5
20 A100000005 999

Now, suppose that because of frequent movement of items, we reached the maximum limit (999) of locn_seq for a particular store_locn_id. But, there are few more items that need to be stocked. Since the max value for LOCN_SEQ has been reached, any attempt to insert another record with a LOCN_SEQ value of 1000 will result into ORA-1401 error. We can thus re-sequence the values so that for a given STORE_LOCN_ID, the LOCN_SEQ values are sequenced and any gaps that resulted via deletion of records could be re-used again. Let us see how we can resolve this using analytical function.

We will create temporary table using CTAS (Create Table AS) to store the data. A key thing to note is that we are using the Row_Number() and the partition clauses of the analytic functions,. Since we want to initialize locn_seq to 1 for each store_locn_id, we will partition by store_locn_id and order by locn_seq.

SQL>create table temp_store_stock
as select store_stock_id, store_locn_id,locn_seq,
Row_number() over(partition by store_locn_id order by locn_seq) new_seq
from store_stock
order by store_locn_id, locn_seq;

The data in this table is shown below: You will notice that new_seq number is in the continuous order without any gap.

SQL> select * from temp_store_stock;

STORE_STOCK_ID STORE_LOCN LOCN_SEQ NEW_SEQ
————– ———- ———- ———-
1 A100000001 5 1
4 A100000001 11 2
2 A100000001 18 3
6 A100000001 35 4
3 A100000001 99 5
5 A100000001 245 6
7 A100000001 803 7
8 A100000001 922 8
9 A100000001 945 9
10 A100000001 999 10
11 A100000002 1 1
12 A100000002 2 2
13 A100000002 15 3
14 A100000002 411 4
15 A100000002 999 5
16 A100000003 1 1
17 A100000004 1 1
18 A100000004 3 2
19 A100000004 5 3
20 A100000005 999 1

Now we will update original table with new_seq_nbr from temp_store_distro table.

SQL>update store_stock
set locn_seq = (select new_seq
from temp_store_Stock
where temp_store_stock.store_stock_id = store_stock.store_stock_id)
where exists (select 1
from temp_store_stock
where temp_store_stock.store_stock_id = store_stock.store_stock_id);
SQL> commit;

The results of the above update are shown below: You can see that, locn_seq is now re-aligned and we can add some more records.

SQL> select store_stock_id,store_locn_id,locn_seq from store_stock
2 order by store_locn_id,locn_seq;

STORE_STOCK_ID STORE_LOCN LOCN_SEQ
————– ———- ———-
1 A100000001 1
4 A100000001 2
2 A100000001 3
6 A100000001 4
3 A100000001 5
5 A100000001 6
7 A100000001 7
8 A100000001 8
9 A100000001 9
10 A100000001 10
11 A100000002 1
12 A100000002 2
13 A100000002 3
14 A100000002 4
15 A100000002 5
16 A100000003 1
17 A100000004 1
18 A100000004 2
19 A100000004 3
20 A100000005 1

We can now drop the temporary table.

SQL> drop table temp_store_stock;

If you want to dig into the Row_Number() and the partition by logic, you can search this web-site for more information on those functions or look up Oracle docs. Oracle has a very rich set of analytic functions which can be very useful for development as well as troubleshooting purposes. We had also covered one of those in a post few days ago – you can access it here.

Posted in Oracle | Leave a Comment »