【问题标题】:How can I close an auction when the closing time is reached?到了结束时间,我如何结束拍卖?
【发布时间】:2019-04-25 17:41:15
【问题描述】:

我正在为一个学校项目开发一个实时拍卖网站。我们无法对数据库的设计进行任何更改。 'Item' 表有一列表示到期日期(拍卖到期的日期)和到期时间(拍卖到期的确切时间)。它还有一个列,指示拍卖是打开还是关闭。此 [AuctionClosed?] 列需要在到期日期和时间到期时更新,这必须实时发生。

我们使用的是 SQL Server 数据库,网站在 PHP7 上运行。我发现的唯一可能的解决方案是每秒运行一次作业,但这开销太大。

这是我想用来检查列的函数:

CREATE FUNCTION dbo.fn_isAuctionClosed (@Item BIGINT)
RETURNS BIT
AS
BEGIN
  DECLARE @expirationDay DATE = (SELECT expirationDate FROM Item WHERE itemId = @Item)
  DECLARE @expirationTime TIME = (SELECT expirationTime FROM Item WHERE itemId = @Item)

  IF 
  DATE(GETDATE()) = @expirationDay AND TIME(GETDATE()) >= @expirationTime
  OR
  DATE(GETDATE()) > @expirationDay
  RETURN 1

  RETURN 0
END

这是更新列的过程:

CREATE PROCEDURE updateAuctionClosed @Item BIGINT
AS
UPDATE Item
SET [AuctionClosed?] = fn_isAuctionClosed(@Item)
WHERE itemId = @Item

【问题讨论】:

  • 改用计算列。达到特定时间时,您无法使 SP 运行。
  • 但是这个计算出来的列不会实时更新吧?您是指 DEFAULT 约束吗?
  • 由于该列会依赖GETDATE(),所以不能使用PERSISTED属性,每次引用该列时都会在运行时计算。
  • 好的,我要试试这个,非常感谢!那么我应该为此使用 DEFAULT 约束吗?
  • 您的dbo.fn_isAuctionClosed 函数无论如何都不正确。如果拍卖在 4 月 1 日 17:00 结束,并在 4 月 2 日 09:00 查询该函数,则表示拍卖仍在进行中,因为时间较少

标签: sql-server tsql


【解决方案1】:

更具体地说,您真正需要的是计算列。就像我在 cmets 中所说的那样,由于该列将依赖于当前日期和时间,因此该列将不是确定性的。这意味着它不能是PERSISTED,而是会在每次引用该列时计算(PERSISTED 列实际上存储了它的值,并在该行以某种方式受到影响并恢复时计算)。即便如此,也可以这样计算:

ALTER TABLE Item DROP COLUMN [AuctionClosed?]; --You can't alter a column to a computed column, so we have to DROP it first

ALTER TABLE Item ADD [AuctionClosed?] AS CASE WHEN CONVERT(datetime,expirationDate) + CONVERT(datetime, expirationTime) > GETDATE() THEN 1 ELSE 0 END;

附带说明,我建议不要在对象名称中使用特殊字符。仅使用字母数字字符和(如果必须的话)下划线 (_),因为这些不会强制对象被分隔标识。

【讨论】:

  • 我同意特殊字符部分,不幸的是我们必须坚持设计中的表格/列名:(
  • 以这种方式添加时 [AuctionClosed?] 列将使用哪种数据类型?它会自动使用 BIT 吗?
  • 这将是上面的int,因为这是 SQL Server 中文字整数值的默认数据类型。如果您特别希望它是 bit,请将整个表达式包装在 CONVERT/CASTbit
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多