SQL по умолчанию - лучшая практика? - PullRequest
1 голос
/ 11 июля 2011

Что лучше всего сделать в хранимых процедурах CREATE и UPDATE для таблицы с ограничениями по умолчанию?

Когда я создаю новый столбец для таблицы, я пытаюсь установить значение пропппера по умолчанию (по умолчаниюограничение).

Пример:

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 ]

1 голос
/ 11 июля 2011

Это было бы как бы повторяющееся, так как оно уже установлено по умолчанию в таблице.

С другой стороны, это позволяет вашим параметрам быть необязательными.Я бы сказал, что вы можете выбрать для них значение по умолчанию, равное таблице (как вы предлагаете), или значение по умолчанию, равное нулю, и таблица заполнит значения по умолчанию.Второй способ менее повторяющийся и подвержен ошибкам.

0 голосов
/ 11 июля 2011

Для обновления вы можете отправить пустое значение для «Без изменений» (или для другого стража, если столбец обнуляем).Аналогичный подход будет работать для вставок.

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
0 голосов
/ 11 июля 2011

Чтобы соответствовать 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
0 голосов
/ 11 июля 2011

Если вы хотите, чтобы OrderDate обновлялся во время UPDATE, вам нужно включить его в инструкцию UPDATE и использовать getdate () вместо @OrderDate

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