我们有预订解决方案,可以预订设施。我们必须确保设施不是双重预订。虽然到目前为止我们还没有任何双重预订,但我不相信当前的实施可以确保这一点。
如果有人可以提供最好的建议就是这样做,我们将不胜感激。我想要一个解决方案,避免做插入,然后不得不做另一次读取检查时间没有重叠。
编辑:因为看起来需要更多细节。在显示的查询中,我们执行SELECT,然后执行INSERT。我假设在SELECT(说时间可用)和INSERT(预订时间)之间有可能另一个用户可以进行INSERT,从而以双重预订结束。我假设有一些方法可以在事务中包装SELECT和INSERT(尽管我还不了解隔离级别是如何工作的)。另一个因素是这是一个多租户的解决方案,所以我担心如果在事务中包装SELECT和INSERT将需要一个表锁定,这将导致其他性能问题。
目前我们使用以下SQL进行插入。我们基本上做一个选择以查看时间是否可用,如果是,则执行插入,然后返回更改了多少行以查看插入是否成功。
INSERT INTO Bookings (TenantId, FacilityId, UnitId, StartDateTime, EndDateTime, ...)
SELECT @TenantId, @FacilityId, @UnitId, @StartDateTime, @EndDateTime, ...
WHERE (SELECT COUNT(*) FROM Bookings WHERE TenantId = @TenantId AND FacilityId = @FacilityId AND
((StartDateTime >= @StartDateTime AND StartDateTime < @EndDateTime) OR (EndDateTime > @StartDateTime AND StartDateTime < @StartDateTime))) = 0; SELECT @@Identity AS [Identity], @@RowCount AS [RowCount]";
答案 0 :(得分:0)
我认为,使用子查询总是会减慢查询运行时间。 说实话,我不确定你要做什么,但我可以改变这样的查询。
INSERT INTO Bookings (TenantId, FacilityId, UnitId, StartDateTime, EndDateTime, ...)
SELECT @TenantId, @FacilityId, @UnitId, @StartDateTime, @EndDateTime, ...
LEFT JOIN Bookings b ON b.TenantId = @TenantId AND b.FacilityId = @FacilityId
WHERE
(
(StartDateTime >= @StartDateTime AND StartDateTime < @EndDateTime) OR (EndDateTime > @StartDateTime AND StartDateTime < @StartDateTime)
) AND b.TenantId IS NULL
但是,如果我理解正确,我将不会使用此代码,我将首先检查而不是直接使用插入查询。 例如,使用此选择查询而不是插入,如果它不为零,则不必运行插入查询。
SELECT COUNT(*)
FROM Bookings
WHERE
TenantId = @TenantId AND FacilityId = @FacilityId AND
(
(StartDateTime >= @StartDateTime AND StartDateTime < @EndDateTime) OR
(EndDateTime > @StartDateTime AND StartDateTime < @StartDateTime)
)
答案 1 :(得分:0)
您可以使用NOT EXISTS进行验证。这比使用COUNT检查存在更快。
IF NOT EXISTS (SELECT * FROM dbo.Bookings as b WHERE b.FacilityID = @FacilityId
AND ((StartDateTime >= @StartDateTime AND StartDateTime < @EndDateTime) OR (EndDateTime > @StartDateTime AND StartDateTime < @StartDateTime)) )
BEGIN
INSERT dbo.Bookings (TenantId, FacilityId, UnitId, StartDateTime, EndDateTime, ...)
SELECT @TenantId, @FacilityId, @UnitId, @StartDateTime, @EndDateTime, ...;
END
ELSE
PRINT 'Facility is already booked for this duration.';