对于具有默认约束的表的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
答案 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