Home All Groups Group Topic Archive Search About

Reserving Identity values

Author
14 Jul 2005 1:16 AM
GMG
Is it possible to reserve a number of identity values before inserting into
a table in a multiuser environment ?

Author
14 Jul 2005 2:28 AM
Louis Davidson
Not in a good way.  You could insert some rows and delete them, but that
would be really wierd.  Identity values shouldn't be used as meaningful
values that you care about the value of.

They are just good surrogates for keys that are optimized for multiple
people to insert and not get duplicates.

--
----------------------------------------------------------------------------
Louis Davidson - http://spaces.msn.com/members/drsql/
SQL Server MVP


Show quote
"GMG" <nospam@nospam.com> wrote in message
news:uojbvHBiFHA.1204@TK2MSFTNGP12.phx.gbl...
> Is it possible to reserve a number of identity values before inserting
> into
> a table in a multiuser environment ?
>
>
Author
14 Jul 2005 3:12 AM
GMG
The issue is I want to avoid using a cursor in a trigger that inserts in 2
dependent tables:

declare cursor
.....

WHILE @@FETCH_STATUS = 0
BEGIN

insert audit
...

get @@identity

insert audit_detail
....

FETCH NEXT FROM ...

END

The fact that I need the identity value before I insert into the
AUDIT_DETAIL table is the reason for using the cursor.
Is there any other way around it ?

P.S.: the purpose is to use set theory to speed up the trigger


Show quote
"Louis Davidson" <dr_dontspamme_sql@hotmail.com> wrote in message
news:%23%236j0uBiFHA.2424@TK2MSFTNGP09.phx.gbl...
> Not in a good way.  You could insert some rows and delete them, but that
> would be really wierd.  Identity values shouldn't be used as meaningful
> values that you care about the value of.
>
> They are just good surrogates for keys that are optimized for multiple
> people to insert and not get duplicates.
>
> --
> --------------------------------------------------------------------------
--
> Louis Davidson - http://spaces.msn.com/members/drsql/
> SQL Server MVP
>
>
> "GMG" <nospam@nospam.com> wrote in message
> news:uojbvHBiFHA.1204@TK2MSFTNGP12.phx.gbl...
> > Is it possible to reserve a number of identity values before inserting
> > into
> > a table in a multiuser environment ?
> >
> >
>
>
Author
14 Jul 2005 3:44 PM
Louis Davidson
The best way to do this is to use the natural key to get the identity rows.
You know the rows you created and you should be able to associate them with
the audit rows some how.  I don't know your data:

I often use a guid as a batch key, like:

insert into audit (key value from table, batchGuid)

insert into audit_detail
select audit.identity
from audit
where key_values from audit (key of table from inserted, batch guid)

It can be a bit tricky, but it is much better than using a trigger.  If this
doesn't make sense I will see if I can find some code I have written in the
past to do this.

--
----------------------------------------------------------------------------
Louis Davidson - http://spaces.msn.com/members/drsql/
SQL Server MVP


Show quote
"GMG" <nospam@nospam.com> wrote in message
news:%23$l9zICiFHA.3436@tk2msftngp13.phx.gbl...
> The issue is I want to avoid using a cursor in a trigger that inserts in 2
> dependent tables:
>
> declare cursor
> ....
>
> WHILE @@FETCH_STATUS = 0
> BEGIN
>
> insert audit
> ...
>
> get @@identity
>
> insert audit_detail
> ....
>
> FETCH NEXT FROM ...
>
> END
>
> The fact that I need the identity value before I insert into the
> AUDIT_DETAIL table is the reason for using the cursor.
> Is there any other way around it ?
>
> P.S.: the purpose is to use set theory to speed up the trigger
>
>
> "Louis Davidson" <dr_dontspamme_sql@hotmail.com> wrote in message
> news:%23%236j0uBiFHA.2424@TK2MSFTNGP09.phx.gbl...
>> Not in a good way.  You could insert some rows and delete them, but that
>> would be really wierd.  Identity values shouldn't be used as meaningful
>> values that you care about the value of.
>>
>> They are just good surrogates for keys that are optimized for multiple
>> people to insert and not get duplicates.
>>
>> --
>> --------------------------------------------------------------------------
> --
>> Louis Davidson - http://spaces.msn.com/members/drsql/
>> SQL Server MVP
>>
>>
>> "GMG" <nospam@nospam.com> wrote in message
>> news:uojbvHBiFHA.1204@TK2MSFTNGP12.phx.gbl...
>> > Is it possible to reserve a number of identity values before inserting
>> > into
>> > a table in a multiuser environment ?
>> >
>> >
>>
>>
>
>
Author
14 Jul 2005 3:00 AM
Brian Selzer
That's not how identity works.  You shouldn't need to reserve the values
before hand.

Here's what I do when I need to insert more than one row into more than one
related table.

Assuming you have the following tables:
CREATE TABLE parent
(
pk int identity(1,1) NOT NULL
  PRIMARY KEY CLUSTERED,
nk int not null
  UNIQUE NONCLUSTERED
)
CREATE TABLE child
(
pk int identity(1, 1) NOT NULL
  PRIMARY KEY CLUSTERED,
fk int NOT NULL REFERENCES parent(pk),
ck int NOT NULL,
UNIQUE NONCLUSTERED (fk, ck)
)


create these temp tables from the client app:

CREATE TABLE #parent (pk int NOT NULL, nk int not null)
CREATE TABLE #child (pk int NOT NULL, fk INT NOT NULL, ck int not null)

then insert these rows from the client app:
INSERT #parent (pk, nk) VALUES (1, 3)
INSERT #child (pk, fk, ck) VALUES (1, 1, 9)
INSERT #child (pk, fk, ck) VALUES (2, 1, 7)
INSERT #child (pk, fk, ck) VALUES (3, 1, 3)
INSERT #parent (pk, nk) VALUES (2, 6)
INSERT #child (pk, fk, ck) VALUES (4, 2, 11)
INSERT #child (pk, fk, ck) VALUES (5, 2, 1)
INSERT #parent (pk, nk) VALUES (3, 1)
INSERT #child (pk, fk, ck) VALUES (6, 3, 4)
INSERT #child (pk, fk, ck) VALUES (7, 3, 3)
INSERT #child (pk, fk, ck) VALUES (8, 3, 2)
INSERT #parent (pk, nk) VALUES (4, 8)
INSERT #child (pk, fk, ck) VALUES (9, 4, 5)

Then execute this procedure from the client app:

CREATE PROCEDURE InsertBoth AS
BEGIN
DECLARE @_ERROR INT

BEGIN TRANSACTION

INSERT parent (nk)
  SELECT nk
   FROM #parent
SELECT @_ERROR = @@ERROR
IF @_ERROR != 0 GOTO ERROR

UPDATE #child
  SET fk = parent.pk
     FROM parent
   JOIN #parent
    ON (#parent.nk = parent.nk)
     WHERE #child.fk = #parent.pk
SELECT @_ERROR = @@ERROR
IF @_ERROR != 0 GOTO ERROR

UPDATE #parent
  SET pk = parent.pk
  FROM parent
  WHERE #parent.nk = parent.nk
SELECT @_ERROR = @@ERROR
IF @_ERROR != 0 GOTO ERROR

INSERT child (fk, ck)
  SELECT fk, ck
   FROM #child
SELECT @_ERROR = @@ERROR
IF @_ERROR != 0 GOTO ERROR

UPDATE #child
  SET pk = child.pk
  FROM child
  WHERE #child.fk = child.fk
   AND #child.ck = child.ck
SELECT @_ERROR = @@ERROR
IF @_ERROR != 0 GOTO ERROR

COMMIT TRANSACTION
RETURN 0

ERROR:
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION
RETURN -1
END
GO

finally read the new identity values from the temp tables into the client
app.

if you need more control, you're going to have to roll your own surrogate
generator.  It can get tricky, however, because of the locks.  I've seen
surrogate generators that included dummy columns in the surrogate table so
that the table would have one row per page, but that was on 6.5 when row
level locking didn't exist.


Show quote
"GMG" <nospam@nospam.com> wrote in message
news:uojbvHBiFHA.1204@TK2MSFTNGP12.phx.gbl...
> Is it possible to reserve a number of identity values before inserting
into
> a table in a multiuser environment ?
>
>
Author
14 Jul 2005 5:07 AM
Uri Dimant
Hi
As others have aleready mentioned there is no a 'proper' way to do that
CREATE TABLE it
(
col INT NOT NULL IDENTITY(1,1)
)
INSERT it DEFAULT VALUES
GO
DBCC CHECKIDENT (it)
GO
INSERT it DEFAULT VALUES

DROP TABLE it

As well you may want to take a look at INSTEAD OF TRIGGER command in the
BOL.


Show quote
"GMG" <nospam@nospam.com> wrote in message
news:uojbvHBiFHA.1204@TK2MSFTNGP12.phx.gbl...
> Is it possible to reserve a number of identity values before inserting
into
> a table in a multiuser environment ?
>
>

AddThis Social Bookmark Button