Auto-Generated Sequences in Tables

advertisement
SQL Sequence Numbers
Database Projects
Auto-Generated Sequences in Tables:

SQL provides a syntax for the create table statement that allows
for auto-generation of values.
>>-CREATE--TABLE--table-name------------------------------------>
>--+-| element-list |----------------------------+--*----------->
...
element-list:
.-,--------------------------.
V
|
|--(----+-| column-definition |------+-+--)---------------------|
...
column-definition:
|--column-name--+--------------------+-------------------------->
|
(2) |
'-| data-type |-----'
>--+--------------------+---------------------------------------|
'-| column-options |-'
Database Projects
Auto-Generated Sequences in Tables:

SQL provides a syntax for the create table statement that allows
for auto-generation of values.
column-options:
.------------------------------------------------------.
V
|
|----+-----------------------------------------------+-+--|
+-NOT NULL------------------------------+
...
+-| generated-column-spec |------------+
...
generated-column-spec:
|--+-| default-clause |-----------------------------------------------+--|
+-GENERATED--+-ALWAYS-----+--AS IDENTITY--+----------------------+-+
|
'-BY DEFAULT-'
'-| identity-options |-' |
'-GENERATED ALWAYS AS--(--generation-expression--)-----------------'
Database Projects
Auto-Generated Sequences in Tables:

SQL provides a syntax for the create table statement that allows
for auto-generation of values.
identity-options:
|--+---------------------------------------------------------+--|
| .------------------------------------------------------------------. |
| V (1)
.-1-------------------------. | |
'-(-----------+-START WITH--+-numeric-constant-+---+-+--)-'
|
.-1--------------------------. |
+-INCREMENT BY--+-numeric-constant-+-+
| .-NO MINVALUE-------------------------.
|
+-+-MINVALUE--numeric-constant-+-----+
| .-NO MAXVALUE-------------------------.
|
+-+-MAXVALUE--numeric-constant-+-----+
| .-NO CYCLE-.
|
+-+-CYCLE----+-----------------------+
| .-CACHE 20--------------------.
|
+-+-NO CACHE----------------+--------+
| '-CACHE--integer-constant-'
|
| .-NO ORDER-.
|
'-+-ORDER----+-----------------------'
Database Projects
Examples:
create table MyTable (
ID INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY,
...
create table MyTable (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY
(START WITH 10 INCREMENT BY 2),
...
Database Projects
IDENTITY Columns:


IDENTITY columns are used when you do not want to provide
values for that column and want the DBMS to provide them
instead.
They are referred to as “auto-generated” columns
create table MyTable(
ID INT GENERATED ALWAYS AS IDENTITY,
Desc VARCHAR(20));
insert into MyTable (Desc) values ('a first value');
insert into MyTable (Desc) values ('a second value');
select * from MyTable;
ID
DESC
----------- -------------------1 a first value
2 a second value
Database Projects
DB2 Says:



“GENERATED ALWAYS is the recommended value unless data
propagation or unload and reload operations are being done.”
This is because the column is a primary key column and so
likely to be a secondary key elsewhere.
If you try to upload the secondary key table using a LOAD or
IMPORT statement, you will not know the correct secondary
key values since they were not determined by you or your
script.
Example: Suppose the borrowerid column in Cardholder is
GENERATED ALWAYS and we now try to IMPORT the
Borrows table. We can not provide the Borrows.borrowerid
values because we do not know what they are.
Database Projects
Alternative:





Use GENERATED BY DEFAULT instead.
This allows the user to specify values if so desired and the
values are auto-generated only as an default alternative.
If you use a value that the auto-generated mechanism might
otherwise use then you could end up with duplicate values
Create a unique index on the column and this won't happen.
“BY DEFAULT is the recommended value when using data
propagation or performing an unload and reload operation.”
Database Projects
DB2 Documentation Link:
http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp
?topic=/com.ibm.db2.udb.doc/admin/r0000927.htm
Database Projects
User Alternative:

What if you do not want to use auto-generated columns?

How can you guarantee column values are unique?

You can maintain your own unique identifier mechanism.
Database Projects
NextSeqNum Mechanism

Problem 1: Create a table that contains the next available
sequence number (ID).
CREATE TABLE NextSeqNum (
TableName varchar(30),
ColumnName varchar(30),
SeqNum INTEGER);


TableName: The name of the table that last used this
mechanism.
ColumnName: The name of the column that last used this
mechanism.

SeqNum: The next available value.

This table has one row for each (TableName,ColumnName) pair
Database Projects
NextSeqNum Mechanism:

Problem 2: Spec out a stored procedure that will allow us to
manage acquiring a sequence number that has not been
previously used.
This stored procedure manages the NextSeqNum table.
NextSeqNum [ TableName, ColumnName, SeqNum ]
The table contains a row for each TableName.ColumnName
column updated by this mechanism..
The SeqNum column contains the next available SeqNum
that can be used in TableName.ColumnName.
Database Projects
NextSeqNum Permitted Calls:
NextSeqNum ('RESET',null, null, null, v_NextSeqNum)
This call resets the value of NextSeqNum.SeqNum
to be 1 more than the largest value in the column
of every table managed by this procedure
Returns 0 if successful, in which case p_SeqNum contains the next
value available.
NextSeqNum ('RESET',v_TabName, v_ColName, null, v_NextSeqNum)
This call resets the value of NextSeqNum.SeqNum
to be 1 more than the largest value in the column
of columns v_TabName.v_ColName
Returns 0 if successful, in which case p_SeqNum contains the next
value available.
Database Projects
NextSeqNum Permitted Calls:
NextSeqNum ('GET','<TableName>', '<ColumnName>', <block_size>, v_NextSeqNum)
This call asks the user to specify a table name, column name and block size
and returns the next available sequence number that can be used by that
table on that column. In fact the table is authorized to use a sequence of
numbers: v_NextSeqNum, v_NextSeqNum+1, ..., v_NextSeqNum+block_size-1
Returns:
0 - success; p_SeqNum is valid
1 - NextSeqNum table is unexplainably empty
2 - an attempt to update NextSeqNum failed.
Exceptions:
SQLSTATE = '80000': negative blocksize
SQLSTATE = '80003': Bad message sent
SQLSTATE = '80004': illegal TableName:ColumnName pair
Database Projects
NextSeqNum Header:
create procedure NextSeqNum
(IN p_Msg varchar(30),
IN p_TableName varchar(30),
IN p_ColumnName varchar(30),
IN p_BlockSize int, OUT p_SeqNum int)
SPECIFIC NextSeqNum
MODIFIES SQL DATA
CALLED ON NULL INPUT
LANGUAGE SQL
Database Projects
NextSeqNum Declarations:
BEGIN ATOMIC
DECLARE errmsg varchar(50);
DECLARE v_RowCount INT;
DECLARE v_ReturnValue INT DEFAULT 0;
DECLARE v_NameList varchar(1000) ;
DECLARE v_SearchTerm, v_TabName, v_ColName varchar(40);
DECLARE v_SeqNum, v_Ndx, v_MaxValue, v_Length, v_OldNdx INT;
DECLARE v_QueryString VARCHAR(500);
DECLARE v_Statement STATEMENT;
DECLARE c_MaxValCursor CURSOR FOR v_Statement;
DECLARE CONTINUE HANDLER FOR SQLSTATE '80001'
SET v_ReturnValue = 1;
DECLARE CONTINUE HANDLER FOR SQLSTATE '80002'
SET v_ReturnValue = 2;
SET p_TableName = UPPER(p_TableName);
SET p_ColumnName = UPPER(p_ColumnName);
Database Projects
NextSeqNum Initial Values
-- A list of all acceptable ,TableName:ColumnName, pairs
-- bracketed by commas(,) and separated by colons(:)
-- must be updated each time you want to allow a
-- new table to use this mechanism
-- always put ‘,’ at the beginning and end
SET v_NameList=',MYTABLE1:ID,MYTABLE2:SERIALNUM,';
SET p_SeqNum = -99;
Database Projects
NextSeqNum RESET Message:
IF (p_Msg = 'RESET') THEN
IF (p_TableName is null or p_ColumnName is null) THEN
SET v_OldNdx = 1;
REPEAT
SET v_Ndx = LOCATE(‘,’,substr(v_NameList,v_OldNdx+1));
SET v_SearchTerm = substr(v_NameList,v_OldNdx+1,v_Ndx – v_OldNdx);
SET v_TabName = substr(v_SearchTerm,1,LOCATE(v_SearchTerm,’:’)-1);
SET v_ColName = substr(v_SearchTerm,LOCATE(v_SearchTerm,’:’)+1);
SET v_QueryString = ‘Update NextSeqNum set SeqNum = ‘ ||
‘(select max(‘ || v_ColName || ‘ + 1 from ‘ || v_TabName || ‘)’ ||
‘ where TableName = ‘ || p_TableName || ‘ and ColumnName = ‘ ||
p_ColumnName ;
EXECUTE IMMEDIATE v_QueryString;
SET v_OldNdx = v_Ndx;
UNTIL ( v_OldNdx = v_Length)
END REPEAT;
ELSE -- reset just one table
Database Projects
NextSeqNum RESET Message:
IF (p_Msg = 'RESET') THEN
-- previous slide
ELSE -- reset just one table
SET v_QueryString = ‘Update NextSeqNum set SeqNum = ‘ ||
‘(select max(‘ || p_ColumnName || ‘ + 1 from ‘ || p_TableName || ‘)’ ||
‘ where TableName = ‘ || p_TableName || ‘ and ColumnName = ‘ ||
p_ColumnName ;
EXECUTE IMMEDIATE v_QueryString;
END IF;
END IF;
Database Projects
NextSeqNum GET Message:
IF (p_Msg = 'GET' ) THEN
SET v_SearchTerm = ',' || p_TableName || ':' || p_ColumnName || ',';
SET v_Ndx = LOCATE(v_SearchTerm,v_NameList);
IF (v_Ndx > 0 ) THEN
IF ( p_BlockSize <= 0 ) THEN
SET errmsg = 'Illegal BlockSize = ' || char(p_BlockSize) ;
-- unhandled error
SIGNAL SQLSTATE VALUE '80000' SET message_text = errmsg;
END IF;
...
Database Projects
NextSeqNum GET Message:
select SeqNum into p_SeqNum
from NextSeqNum
where TableName = p_TableName,
ColumnName = p_ColumnName;
update NextSeqNum
set SeqNum = SeqNum + p_BlockSize
where TableName = p_TableName,
ColumnName = p_ColumnName;
-- ROLLBACK automatically on failure
GET DIAGNOSTICS v_RowCount = ROW_COUNT;
IF (v_RowCount = 0) THEN
SIGNAL SQLSTATE VALUE '80002' ;
END IF;
RETURN v_ReturnValue;
END IF; -- table name, column name pair exist
Database Projects
NextSeqNum Unrecognized Table/Message and Return:
ELSE -- TableName:ColumnName pair not in list
SET errmsg = 'Illegal Table/Column Name';
-- unhandled error
SIGNAL SQLSTATE VALUE '80004' SET message_text = errmsg;
END IF;
ELSE -- Not RESET and not GET
SET errmsg = 'Bad Message Sent';
SIGNAL SQLSTATE VALUE '80003' ;
END IF;
RETURN v_ReturnValue;
END @
Database Projects
Download