Во-первых, вы можете преобразовать текущую дату и время в значение Только дата, используя:
DateAdd(d, DateDiff(d, 0, CURRENT_TIMESTAMP), 0)
Одним из решений является использование двух операторов. Однако для защиты от фантомного чтения вам нужно будет обернуть операторы в транзакции и установить уровень изоляции на Serializable или Snapshot (если реализовано). Очевидно, что это повредит параллелизму, но обеспечит последовательность.
Declare @Today datetime
Set @Today = DateAdd(d, DateDiff(d, 0, CURRENT_TIMESTAMP), 0)
Set Transaction Isolation Level Serializable;
Set Xact_Abort On;
Begin Tran;
Update CustomerUsage
Set NumHits = NumHits + 1
Where CustID = @cust_guid
And UseDate >= @Today
And UseDate < DateAdd(d, 1, @Today)
Insert CustomerUsage( CustId, UseDate, NumHits )
Select @CustId, CURRENT_TIMESTAMP, 1
From ( Select 1 As Value ) As Z
Where Not Exists (
Select 1
From Customer_Usage
Where CustID = @cust_guid
And UseDate >= @Today
And UseDate < DateAdd(d, 1, @Today)
)
Commit Tran;
Поскольку каждый оператор сам по себе является транзакцией, вы избежите проблем с одновременными вызовами. Если вы используете SQL Server 2008, вы можете использовать тип данных Date
и оператор Merge
для достижения того же:
Declare @Today date
Set @Today = Cast( CURRENT_TIMESTAMP As date )
Merge CustomerUsage As target
Using (
Select CustId, UseDate
From CustomerUsage
Where CustID = @cust_guid
And UseDate >= @Today
And UseDate < DateAdd(d, 1, @Today)
Union All
Select @cust_guid, CURRENT_TIMESTAMP
From ( Select 1 As Value ) As Z
Where Not Exists (
Select 1
From CustomerUsage
Where CustID = @cust_guid
And UseDate >= @Today
And UseDate < DateAdd(d, 1, @Today)
)
) As source
On source.CustID = target.CustID
And source.UseDate = target.UseDate
When Matched Then
Update Set NumHits = NumHits + 1
When Not Matched Then
Insert ( CustId, UseDate, NumHits )
Values( source.CustId, source.UseDate, 1 )
Окончательное добавление
Хотя я понимаю, что ответ был выбран, мне приходит в голову, что есть лучшее решение. Нет необходимости обновлять счетчик посещений в день. Просто сделайте вставку, которая регистрирует попадание (то есть только вставку без отслеживания NumHits), и на стороне отчетности сворачивайте «попадания в день».