3

I'm trying to see if exists something to create a sequence with partition logic. I need a sequence number that depend on other primary key ex:

id_person   sequence id
        1 | 1
        1 | 2
        2 | 1
        3 | 1
        1 | 3

so the sequence must depend on the id_person partition. Is there something like this on oracle or i must implement it by myself on the application level?

thank you.


Hi have create this PLSQL package one function and procedure:

PROCEDURE INIT_SEQUENCE(NAME varchar2, pkColumnNameList PARTITIONED_SEQUENCE_PK_COLUMN);
FUNCTION GET_NEXT_SEQUENCE_VALUE(NAME varchar2, pkPartitionColValue PARTITIONED_SEQUENCE_COL_VALUE) RETURN NUMBER;

INIT_SEQUENCE - get in input the name to associate at the sequence and a list of column name that are the fixed primary key part that vincolate the sequence Ex:'ID_PERSON'

the work of this procedure is to create the table that will manage the increment of sequence according to pkColumnNameList column.

GET_NEXT_SEQUENCE_VALUE- get the name of sequence to increment and the value of pkColumnNameList primary key and make the next step: 1) Create dynamically the sql to work 2) dbms_lock.allocate_unique(); to lock the table 3) check if is present a record in the table for pk value in input 4) if a record is present update the record with max + 1 in the sequence column 5) if a record is not present insert the new record with the 1 in the sequence column 6) return new id;

i would like to receive comment about this thanks in advance...

Juergen
  • 12,378
  • 7
  • 39
  • 55
Macdeveloper
  • 91
  • 1
  • 8
  • Can you detail for what is the sequence id column? – FerranB Feb 15 '10 at 15:59
  • 1
    How many person ID's will you have 1-10 or 100,000's... Can there be gaps? If there are only going to be a few people ID's just make n sequences - that is, if you are allowed gaps. Pay no attention to the people spouting concurrency issues, clearly this isn't a serious app with hundreds of simultaneous connections inserting into this table. Is it? – Stephanie Page Feb 15 '10 at 16:53
  • 1
    Ok slight bit of sarcasm there but in general I'm serious. People start ranting about concurrency before asking how many inserts you're expecting. If you have 10 inserts per hour, wtf cares? – Stephanie Page Feb 15 '10 at 23:37
  • person_id is only for example. it's my opinion to optimize the sequence number id'like to have, like in above example, the sequence ordered by fir part primary key partition, in the example the partition is governed by id_person, but is only an example. – Macdeveloper Feb 16 '10 at 11:26

3 Answers3

5

Is the actual requirement that the secondary sequence be gap free? If so, you've got a giant serialization/scalability issue.

If you need to present a gap-free sequence for human consumption, you could use an actual sequence (or a timestamp, for that matter) as Nick Pierpont suggests and preserve scalability, you could use analytic functions.

Dataset (t1):

 ID_PERSON SEQUENCE_ID
---------- -----------
         1           1
         2           2
         3           3
         1           4
         1           5
         1           6
         2           7
         3           8
         1           9

SQL:

select * 
  from 
  (select id_person, 
          sequence_id as orig_sequence_id,         
          rank () 
            over (partition by id_person 
                  order by sequence_id) 
            as new_sequence_id
     from t1
  )
 order by id_person, new_sequence_id;

Result:

ID_PERSON  ORIG_SEQUENCE_ID NEW_SEQUENCE_ID
---------- ---------------- ---------------
         1                1               1
         1                4               2
         1                5               3
         1                6               4
         1                9               5
         2                2               1
         2                7               2
         3                3               1
         3                8               2
Adam Musch
  • 13,286
  • 2
  • 28
  • 32
  • 1
    +1, good solution. Avoids storing secondary sequence and it's attendant maintenance/performance issues. – DCookie Feb 15 '10 at 18:54
  • 1
    Giant? a GIANT serialization issue... with 10 records inserted per day? Where does that number come from? I made it up, just as you would have to to determine if there is *really* a concurrency problem in the offing. He may or may not have a concurrency issue. – Stephanie Page Feb 15 '10 at 23:36
  • 2
    @Stephanie Page: Designs which introduce serialization do not scale. Either it's a toy application or eventually, serialization will bite designs which use a "select max(column) + 1" "pattern". Far easier to not introduce the serialization in the first place. – Adam Musch Feb 16 '10 at 04:00
0

I'm afraid you have to do it like this:

INSERT INTO t
(
  id_person,
  sequence_id
)
VALUES
( 
  <your_person_id>,
  ( SELECT 1 + NVL( MAX( sequence_id ), 0 )
    FROM t
    WHERE t.id_person = <your_person_id>
  )
)
Peter Lang
  • 54,264
  • 27
  • 148
  • 161
  • thank for the idea, i'm trying to implement a package pl-sql to make this kind of sequence – Macdeveloper Feb 15 '10 at 12:11
  • 1
    You'll need to handle the situation where 2 users try the insert at the same time - one will fail due to a PK violation. – Tony Andrews Feb 15 '10 at 13:03
  • Why not just use a normal sequence and not have it dependent on the person? You can still present a person-dependent order number to the client application if required. – Nick Pierpoint Feb 15 '10 at 14:00
  • @Tony Andrews: Definitely right. I tried to avoid this problem by putting the `INSERT` into a procedure and call it recursively in the `DUP_VAL_ON_INDEX`-exception handling block. As the second `INSERT` is being blocked by the first transaction, the second attempt succeeds. Nothing to be proud of, though... Any suggestions? – Peter Lang Feb 15 '10 at 20:38
  • @nick if i can choice I prefer to put ordered sequence, also in in insert is a little bit slow, but in read i can have more simple select – Macdeveloper Feb 16 '10 at 07:28
  • @Peter: yes, handling the DUP_VAL_ON_INDEX exception is good for most situations. Obviously, if the system were handling many inserts per second on this table for the same parent there would be a lot of these exceptions to handle, but probably that isn't the case; if it is the case, then the best bet would be to just use a sequence. – Tony Andrews Feb 16 '10 at 10:14
0

What you are looking for is not a sequence, as the Oracle Documentation claims: "The sequence generator provides a sequential series of numbers".

You are looking for a calculated field depending on another, in this case the primary key. As other suggested you need to add the logic on your code. It means in a procedure or in the insert sentence.

FerranB
  • 35,683
  • 18
  • 66
  • 85
  • I have created a olsql package that manage this kind od sequence and use dbms_lock to perform control over concurency. Every kind of that sequence has a table cor calculation. Late in this day i'll post the code in this post i would to' like to shareware this idea and see if it is well designed – Macdeveloper Feb 16 '10 at 07:25