I have a table that I use to keep track of customer usage. I track the number of hits the user does per day, so I have a table that looks like this:
CustID (uniqueidentifier, not null)
UseDate (smalldatetime, not null)
NumHits (smallint, not null)
I use this SQL in a stored proc to insert a row for today (if needed), or to increment the counter for today:
declare @today datetime
set @today = getdate()
/* Try to bump it by one if an entry for today exists */
if (
select count(*) from CustomerUsage
where CustID = @cust_guid and year(UseDate) = year(@today) and month(UseDate) = month(@today) and day(UseDate) = day(@today)
) = 0
insert into CustomerUsage (CustID, UseDate, NumHits) values (@cust_guid, getdate(), 1)
else
update CustomerUsage set NumHits = NumHits + 1
where CustID = @cust_guid and year(UseDate) = year(@today) and month(UseDate) = month(@today) and day(UseDate) = day(@today)
Is there a better way to do this?
Also, I want to move to an environment where multiple web servers can call the stored proc for the same customer. I think this code might be vulnerable to multithreading issues.
Thanks!
You can do like this.
First insert a row with
NumHits = 0. The insert checks if there already exists a row for thatCustIDon thatUseDateand only inserts if necessary.After the insert always increment
NumHitsby 1.This is basically the same idea as Thomas non merge answer but I do the insert before the update.
Edit 1 Added Table Hints to the insert statements
where not existspart.serializableis needed to prevent primary key constraint violation andupdlockis needed to avoid deadlocks.