dbTalk Databases Forums  

update/insert

comp.databases.sybase comp.databases.sybase


Discuss update/insert in the comp.databases.sybase forum.



Reply
 
Thread Tools Display Modes
  #1  
Old   
Brian Dick
 
Posts: n/a

Default update/insert - 08-17-2004 , 12:21 PM






I have procedure code something like the following.

update t
set ...
where k = @k

if @@rowcount = 0
insert into t ...

This code is executed by a multithreaded application. On occassion two
threads will simultaneously have the same value for @k, and the insert fails
with message something like the following.

Msg 2601, Level 14, State 1:
Server 'foo', Procedure 'p_foo', Line 35:
Attempt to insert duplicate key row in object 't' with unique index 'pkt'

I understand why the above code doesn't work.

Does anyone have a good solution for making an update/insert work without
error?

Later,
BEDick



Reply With Quote
  #2  
Old   
Pablo Sanchez
 
Posts: n/a

Default Re: update/insert - 08-17-2004 , 02:59 PM






"Brian Dick" <bdick (AT) cox (DOT) net> wrote in
news:J3rUc.15$Nq3.38 (AT) news-srv1 (DOT) fmr.com:

Quote:
I have procedure code something like the following.

update t
set ...
where k = @k

if @@rowcount = 0
insert into t ...

snipped

Does anyone have a good solution for making an update/insert work
without error?
Have you wrapped the unit of work in a transaction?

BEGIN TRANSACTION

update ....

if @@rowcount ...

COMMIT TRANSACTION

The above will ensure the lock is held by the first thread to make
the UPDATE and blocking the other. The other thread will unblock at
the COMMIT and will find nothing and won't execute the INSERT.

HTH
--
Pablo Sanchez - Blueoak Database Engineering, Inc
http://www.blueoakdb.com


Reply With Quote
  #3  
Old   
Brian Dick
 
Posts: n/a

Default Re: update/insert - 08-18-2004 , 07:17 AM



Yes, the code is in a transaction. The problem is that the update can't lock
a row that doesn't exist (i.e. @@rowcount = 0).

"Pablo Sanchez" <honeypot (AT) blueoakdb (DOT) com> wrote

Quote:
"Brian Dick" <bdick (AT) cox (DOT) net> wrote in
news:J3rUc.15$Nq3.38 (AT) news-srv1 (DOT) fmr.com:

I have procedure code something like the following.

update t
set ...
where k = @k

if @@rowcount = 0
insert into t ...

snipped

Does anyone have a good solution for making an update/insert work
without error?

Have you wrapped the unit of work in a transaction?

BEGIN TRANSACTION

update ....

if @@rowcount ...

COMMIT TRANSACTION

The above will ensure the lock is held by the first thread to make
the UPDATE and blocking the other. The other thread will unblock at
the COMMIT and will find nothing and won't execute the INSERT.

HTH
--
Pablo Sanchez - Blueoak Database Engineering, Inc
http://www.blueoakdb.com



Reply With Quote
  #4  
Old   
Sara Law
 
Posts: n/a

Default Re: update/insert - 08-18-2004 , 04:54 PM



I'm not sure if my message took ...

I'll try again ...

What if ya do this:

begin tran

insert t
where not exists (select 1
from t
where k = @k)

if @@rowcount = 0
update t
set ...
where k = @k

commit tran


I assume "t" is indexed on "k" for the "not exists" clause to perform.

Cheers,

Sara ...

"Brian Dick" <bdick (AT) cox (DOT) net> wrote

Quote:
Yes, the code is in a transaction. The problem is that the update can't lock
a row that doesn't exist (i.e. @@rowcount = 0).

"Pablo Sanchez" <honeypot (AT) blueoakdb (DOT) com> wrote in message
news:Xns9548A29B43EE1pingottpingottbah (AT) 130 (DOT) 133.1.4...
"Brian Dick" <bdick (AT) cox (DOT) net> wrote in
news:J3rUc.15$Nq3.38 (AT) news-srv1 (DOT) fmr.com:

I have procedure code something like the following.

update t
set ...
where k = @k

if @@rowcount = 0
insert into t ...

snipped

Does anyone have a good solution for making an update/insert work
without error?

Have you wrapped the unit of work in a transaction?

BEGIN TRANSACTION

update ....

if @@rowcount ...

COMMIT TRANSACTION

The above will ensure the lock is held by the first thread to make
the UPDATE and blocking the other. The other thread will unblock at
the COMMIT and will find nothing and won't execute the INSERT.

HTH
--
Pablo Sanchez - Blueoak Database Engineering, Inc
http://www.blueoakdb.com

Reply With Quote
  #5  
Old   
Mariano Corral
 
Posts: n/a

Default Re: update/insert - 08-18-2004 , 06:16 PM



"Brian Dick" <bdick (AT) cox (DOT) net> wrote:
Quote:
I have procedure code something like the following.

update t
set ...
where k = @k

if @@rowcount = 0
insert into t ...

This code is executed by a multithreaded application. On occassion two
threads will simultaneously have the same value for @k, and the insert fails
with message something like the following.

Msg 2601, Level 14, State 1:
Server 'foo', Procedure 'p_foo', Line 35:
Attempt to insert duplicate key row in object 't' with unique index 'pkt'

I understand why the above code doesn't work.

Does anyone have a good solution for making an update/insert work without
error?
You may code it the other way round: first try to insert,
then check for a 2601 error; if the error arose (duplicate
key insert), then update. I mean,

insert into t ...
if @@error = 2601
update ...

Beware this approach is probably more "lock-prone" than
the original. Also, it may be less efficient if updates
are more frequent than inserts.

Regards,
Mariano Corral


Reply With Quote
  #6  
Old   
Brian Dick
 
Posts: n/a

Default Re: update/insert - 08-19-2004 , 07:49 AM



I tried that and it's slow.

"Mariano Corral" <corral (AT) iname (DOT) com> wrote

Quote:
"Brian Dick" <bdick (AT) cox (DOT) net> wrote:
I have procedure code something like the following.

update t
set ...
where k = @k

if @@rowcount = 0
insert into t ...

This code is executed by a multithreaded application. On occassion two
threads will simultaneously have the same value for @k, and the insert
fails
with message something like the following.

Msg 2601, Level 14, State 1:
Server 'foo', Procedure 'p_foo', Line 35:
Attempt to insert duplicate key row in object 't' with unique index
'pkt'

I understand why the above code doesn't work.

Does anyone have a good solution for making an update/insert work
without
error?

You may code it the other way round: first try to insert,
then check for a 2601 error; if the error arose (duplicate
key insert), then update. I mean,

insert into t ...
if @@error = 2601
update ...

Beware this approach is probably more "lock-prone" than
the original. Also, it may be less efficient if updates
are more frequent than inserts.

Regards,
Mariano Corral



Reply With Quote
  #7  
Old   
Brian Dick
 
Posts: n/a

Default Re: update/insert - 08-19-2004 , 08:34 AM



That's not a valid insert command. However, I tried the following variation
of your suggestion and the preliminary results look good.

insert into t
select @k, ...
where not exists (select 1 from t where k = @k)

"Sara Law" <saradba (AT) hotmail (DOT) com> wrote

Quote:
I'm not sure if my message took ...

I'll try again ...

What if ya do this:

begin tran

insert t
where not exists (select 1
from t
where k = @k)

if @@rowcount = 0
update t
set ...
where k = @k

commit tran


I assume "t" is indexed on "k" for the "not exists" clause to perform.

Cheers,

Sara ...

"Brian Dick" <bdick (AT) cox (DOT) net> wrote

Yes, the code is in a transaction. The problem is that the update can't
lock
a row that doesn't exist (i.e. @@rowcount = 0).

"Pablo Sanchez" <honeypot (AT) blueoakdb (DOT) com> wrote in message
news:Xns9548A29B43EE1pingottpingottbah (AT) 130 (DOT) 133.1.4...
"Brian Dick" <bdick (AT) cox (DOT) net> wrote in
news:J3rUc.15$Nq3.38 (AT) news-srv1 (DOT) fmr.com:

I have procedure code something like the following.

update t
set ...
where k = @k

if @@rowcount = 0
insert into t ...

snipped

Does anyone have a good solution for making an update/insert work
without error?

Have you wrapped the unit of work in a transaction?

BEGIN TRANSACTION

update ....

if @@rowcount ...

COMMIT TRANSACTION

The above will ensure the lock is held by the first thread to make
the UPDATE and blocking the other. The other thread will unblock at
the COMMIT and will find nothing and won't execute the INSERT.

HTH
--
Pablo Sanchez - Blueoak Database Engineering, Inc
http://www.blueoakdb.com



Reply With Quote
  #8  
Old   
Brian Ceccarelli
 
Posts: n/a

Default Re: update/insert - 08-24-2004 , 09:14 PM



Consider putting a timestamp column on your table.


"Brian Dick" <bdick (AT) cox (DOT) net> wrote

Quote:
I tried that and it's slow.

"Mariano Corral" <corral (AT) iname (DOT) com> wrote in message
news:78516de.0408181435.3b94df74 (AT) posting (DOT) google.com...
"Brian Dick" <bdick (AT) cox (DOT) net> wrote:
I have procedure code something like the following.

update t
set ...
where k = @k

if @@rowcount = 0
insert into t ...

This code is executed by a multithreaded application. On occassion two
threads will simultaneously have the same value for @k, and the insert
fails
with message something like the following.

Msg 2601, Level 14, State 1:
Server 'foo', Procedure 'p_foo', Line 35:
Attempt to insert duplicate key row in object 't' with unique index
'pkt'

I understand why the above code doesn't work.

Does anyone have a good solution for making an update/insert work
without
error?

You may code it the other way round: first try to insert,
then check for a 2601 error; if the error arose (duplicate
key insert), then update. I mean,

insert into t ...
if @@error = 2601
update ...

Beware this approach is probably more "lock-prone" than
the original. Also, it may be less efficient if updates
are more frequent than inserts.

Regards,
Mariano Corral





Reply With Quote
Reply




Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.3
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.