【问题标题】:SQL Server: Insert if Current Date > endDateSQL Server:如果当前日期 > endDate 则插入
【发布时间】:2011-12-13 22:27:17
【问题描述】:

基本上我需要做的是插入表ReservationvehicleIDstartDateendDate

我可以做到这一点,但我想验证它,以便如果当前日期是 <= endDate,则不能为 vehicleID 插入它,因为目前我可以继续添加到 Reservation 表上同样vehicleID

这只是简单的插入 SQL 语句。

strInsert = String.Format("Insert into Reservation (VehicleID, startDate, enddate) VALUES ('{0}','{1}','{2}')", vID, now, now5)

问候。

【问题讨论】:

  • 我希望您不会在不清理数据输入的情况下部署该字符串格式化程序。你应该改用 SQLParameters,否则你可能已经成熟了 SQL 注入攻击。
  • 哦不,这不会有任何商业需求,它只是在内网上工作。
  • 不过,这不是使用不良做法的借口。

标签: asp.net sql-server vb.net


【解决方案1】:

如果今天的日期小于您要插入的结束日期,不尝试插入会怎样?

If Date.Today <= now5 Then
   Throw New Exception("Invalid Date")
Else
  strInsert = String.Format("Insert into Reservation (VehicleID, startDate, enddate) VALUES ('{0}','{1}','{2}')", vID, now, now5)
End If

更新

如果您在 SQL 中实现这一切,那么我建议使用存储过程,但无论哪种情况,逻辑都是相同的。检查今天是否存在任何重叠的预留,如果存在,则从 SQL 中引发异常。

请注意,GETDATE() 使用的值并不完全正确,因为它返回当前时间戳,但在不知道这些值是如何存储的情况下,它被用作近似值,以后可以清理。

CREATE PROCEDURE s_AddReservation
    @VehicleID   INT ,
    @StartDate   DATETIME ,
    @EndDate     DATETIME
AS
    IF EXISTS(SELECT 1
                FROM Reservation
               WHERE VehicleID = @VehicleID
                 AND StartDate <= GETDATE()
                 AND EndDate >= GETDATE())
      BEGIN
        RAISERROR('This care has already been rented', 16, 1);
      END
    ELSE
      BEGIN
        Insert into Reservation (VehicleID, startDate, enddate) VALUES (@VehicleID, @StartDate, @EndDate)
      END
GO

从您的代码中调用此存储过程:

var oCommand = new SqlCommand('s_AddReservation', conn);
oCommand.CommandType = CommandType.StoredProcedure;
oCommand.Parameters.AddWithValue("@VehicleID", vID);
oCommand.Parameters.AddWithValue("@StartDate", now);
oCommand.Parameters.AddWithValue("@EndDate", now5);

oCommand.ExecuteNonQuery();

【讨论】:

  • if/else 不是必需的,因为异常会中断循环。
  • @MatthewPK:是的,但我喜欢这样构造它,以防万一没有完全注意的人在路上改变了实现(据我所知,这种情况已经发生了几十次)。例如,如果你想在方法调用中设置一个 byref errormessage 参数,你可以将 throw 异常改为一组参数,剩下的代码不会被意外执行。
  • 感谢您的帮助,但 now 和 now5 是 datetime.now 和 datetime.now.addminutes(5) 因此它总是会抛出该异常。我需要的是一个 SQL 语句,它首先搜索 Reservation 表以检查 VehicleID 的最后一次预订,并查看 datetime.now > endDate。谢谢!
  • @CraigWilliams:使用 SQL 实现更新答案。我有它的存储过程格式,但如果你愿意,你可以将它展平为动态 sql。
  • 感谢您的快速回复。我以前没用过存储过程,我用你在更新中放的代码创建一个吗?
【解决方案2】:

如果您使用select 而不是values,则可以使用where 强制执行条件:

insert  Reservation 
        (VehicleID, startDate, enddate) 
select  '{0}', '{1}', '{2}'
where   getdate() > '{2}'

【讨论】:

  • 大家好,感谢您的帮助。基本上我需要做的是首先检查预订表,看看是否已经有 VehicleID 的预订,然后对 endDate 进行 GETDATE() 检查以确认 GETDATE() 大于 enddate。
【解决方案3】:

您可以使用约束和触发器来完成此操作,因此无论您如何插入或更新数据,数据库都会执行您的逻辑。

CREATE TABLE dbo.Reservation(
    Id int IDENTITY(1,1) NOT NULL,
    VehicleId int NOT NULL,
    StartDate datetime NOT NULL,
    EndDate datetime NULL,
 CONSTRAINT pk_dbo_reservation PRIMARY KEY NONCLUSTERED (Id ASC),
 CONSTRAINT uq_dbo_reservation UNIQUE CLUSTERED (VehicleId ASC, StartDate ASC)
)
GO
ALTER TABLE dbo.Reservation WITH CHECK ADD CONSTRAINT ck_dbo_reservation_startdate_before_enddate CHECK (StartDate < EndDate)
GO
ALTER TABLE dbo.Reservation ADD CONSTRAINT df_dbo_reservation_startdate DEFAULT (GETDATE()) FOR StartDate
GO
---------------------------------------
CREATE TRIGGER dbo.trg_insupd_ReservationNoOverlap ON dbo.Reservation
AFTER INSERT, UPDATE
AS
SET NOCOUNT ON
IF EXISTS (
    -- reservation is already active during the new time frame
    SELECT b.VehicleId
    FROM   dbo.Reservation b
           INNER JOIN inserted ins
             ON b.VehicleId = ins.VehicleId
                AND b.Id <> ins.Id
    WHERE  ( b.StartDate <= ins.StartDate
             AND ( b.EndDate IS NULL
                    OR b.EndDate > ins.StartDate ) )
            OR ( b.StartDate > ins.StartDate
                 AND ( ins.EndDate IS NULL
                        OR ins.EndDate > b.StartDate ) )
)
BEGIN
RAISERROR ('Dates cannot overlap for vehicle reservation.', 16, 1) WITH SETERROR;
ROLLBACK TRANSACTION;
RETURN
END
GO

测试用例:

INSERT INTO dbo.Reservation (VehicleId, StartDate, EndDate) VALUES (1, '12/01/2011', '12/06/2011') -- ok
INSERT INTO dbo.Reservation (VehicleId, StartDate, EndDate) VALUES (1, '12/06/2011', '12/08/2011') -- ok
INSERT INTO dbo.Reservation (VehicleId, StartDate, EndDate) VALUES (1, '12/03/2011', '12/04/2011') -- not ok (overlaps)

INSERT INTO dbo.Reservation (VehicleId, StartDate, EndDate) VALUES (1, '12/08/2011', NULL) -- ok (open-ended)
INSERT INTO dbo.Reservation (VehicleId, StartDate, EndDate) VALUES (1, '11/20/2011', '11/26/2011') -- ok
INSERT INTO dbo.Reservation (VehicleId, StartDate, EndDate) VALUES (1, '11/28/2011', NULL) -- not ok (overlaps)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-23
    • 1970-01-01
    • 2018-04-13
    • 1970-01-01
    相关资源
    最近更新 更多