SQL默认值 - 最佳实践?

时间:2011-07-11 13:48:33

标签: sql-server sql-server-2008 default parameter-passing constraints

对于具有默认约束的表的CREATE和UPDATE存储过程,最好的做法是什么?

当我为表创建一个新列时,我尝试设置一个propper默认值(默认约束)。

示例:

CREATE TABLE Orders
(
   O_ID INT NOT NULL
  ,State INT DEFAULT 0 --  0 => Not Verified, 1 => Verified, 2 => Processing ....
  ,P_ID INT
  ,OrderDate DATE DEFAULT GETDATE()
 )

在此表的CREATE和UPDATE存储过程中,最好的做法是什么? 使用与约束相同的默认值?

CREATE PROCEDURE UpdateOrder
(
   @O_ID INT
  ,@State INT = 0
  ,@P_ID INT
  ,@OrderDate DATE
)
AS

UPDATE
   Orders
SET
   State = @State
  ,P_ID = @PID
  ,OrderDate = @OrderDate
WHERE
  O_ID = @O_ID

4 个答案:

答案 0 :(得分:1)

这会有点重复,因为它已经在桌面上违约了。

另一方面,它允许您的参数是可选的。我会说你的选择是将它们默认为与表(如你所建议的)相同,或者将它们默认为null,表格将填入默认值。第二种方式是重复性较低且容易出错。

答案 1 :(得分:0)

如果您希望在UPDATE期间更新OrderDate,则需要将其包含在UPDATE语句中并使用getdate()代替@OrderDate

UPDATE     
Orders 
SET     
State = @State   ,
P_ID = @PID   ,
OrderDate = getdate()
WHERE   O_ID = @O_ID 

答案 2 :(得分:0)

要遵守DRY,一种解决方法是将默认值存储在表格中:

CREATE TABLE dbo.MyDefaults
(
    OrderState INT
);
INSERT dbo.MyDefaults(OrderState) SELECT 0;

你不能用GETDATE()来做到这一点,所以让我们保持原样 - 不管怎样你都不会改变。所以现在我们可以从表中提取默认值,而不是硬编码。让我们创建一个标量函数,因为我们不能在默认约束中使用子查询:

CREATE FUNCTION dbo.DefaultOrderState()
RETURNS INT
AS
BEGIN
    RETURN (SELECT TOP (1) OrderState FROM dbo.MyDefaults);
END
GO

(如果你有很多这些,你可以考虑使用EAV方法而不是专用列。)

所以现在我们可以使用Orders表,并注意永远不会提到常量“0”:

CREATE TABLE dbo.Orders
(
    O_ID INT NOT NULL,
    [State] INT NOT NULL DEFAULT (dbo.DefaultOrderState()),
    P_ID INT,
    OrderDate DATE NOT NULL DEFAULT (SYSDATETIME())
);
GO

我们的更新程序也可以获取默认值(除非您尚未定义是否确实要将状态重置为0,如果它当前不为0并且没有为该过程提供值)。同样没有提到“0”常数。

CREATE PROCEDURE dbo.UpdateOrder
    @O_ID INT,
    @State INT = NULL,
    @P_ID INT,
    @OrderDate DATE = NULL
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE dbo.Orders
        SET [State] = COALESCE(@State, dbo.DefaltOrderState()),
        P_ID = @P_ID,
        OrderDate = COALESCE(@OrderDate, OrderDate, SYSDATETIME())
    WHERE
        O_ID = @O_ID;
END
GO

答案 3 :(得分:0)

对于更新,您可以为“无变化”发送空值(如果列可以为空,则发送另一个标记)。类似的方法适用于插入。

CREATE PROCEDURE UpdateOrder
(
   @O_ID INT
  ,@State INT
  ,@P_ID INT = -1
  ,@OrderDate DATE
)
AS

UPDATE
    Orders
SET
   State = IsNull(@State,State)
  ,P_ID = case when @P_ID < 0 then P_ID else @P_ID end  -- assuming this int is not nullable and something like -1 is the default value
  ,OrderDate = COALESCE(@OrderDate,OrderDate)
WHERE
  O_ID = @O_ID