Как определить сложный ComputedColumn в SQL Server?

Вопрос для начинающих по SQL Server:

Я пытаюсь ввести вычисляемый столбец в SQL Server (2008). В дизайнере таблиц SQL Server Management Studio я могу это сделать, но дизайнер предлагает мне только одну ячейку редактирования, чтобы определить выражение для этого столбца. Поскольку мой вычисляемый столбец будет довольно сложным (в зависимости от нескольких полей базы данных и с некоторыми различиями в регистре), я хотел бы иметь более удобный и удобный способ ввода определения столбца (включая разрывы строк для форматирования и т. д.).

Я видел, что есть возможность определять функции в SQL Server (функции скалярного значения или табличного значения). Возможно, лучше определить такую ​​функцию и использовать ее в качестве спецификации столбца? А что за функция (скалярное значение, табличное значение)?

Чтобы сделать упрощенный пример:

У меня есть два столбца базы данных:

DateTime1 (smalldatetime, NULL)
DateTime2 (smalldatetime, NULL)

Теперь я хочу определить вычисляемый столбец «Статус», который может иметь четыре возможных значения. На фиктивном языке:

if (DateTime1 IS NULL and DateTime2 IS NULL)
    set Status = 0
else if (DateTime1 IS NULL and DateTime2 IS NOT NULL)
    set Status = 1
else if (DateTime1 IS NOT NULL and DateTime2 IS NULL)
    set Status = 2
else
    set Status = 3

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

Это вообще возможно? Или как лучше всего работать со «сложными» определениями вычисляемых столбцов?

Спасибо за советы заранее!


person Slauma    schedule 07.04.2010    source источник


Ответы (3)


Вы можете сделать это в операторе alter table:

alter table my_table_name
  add Status as 
    case 
      when (DateTime1 IS NULL and DateTime2 IS NULL) then 0
      when (DateTime1 IS NULL and DateTime2 IS NOT NULL) then 1
      when (DateTime1 IS NOT NULL and DateTime2 IS NULL) then 2
      else 3
    end

Отредактировано, чтобы исправить глупую синтаксическую ошибку копирования и вставки.

person Ray    schedule 07.04.2010
comment
Спасибо, работает нормально! Но что мне делать, если я захочу позже изменить формулу, скажем, добавить дополнительный случай? Нужно ли удалять столбец Статус из таблицы и снова запускать такой сценарий изменения таблицы? - person Slauma; 08.04.2010

Вы также всегда можете использовать для этого определяемую пользователем функцию - оберните свой "сложный" код в UDF и используйте его для определения вычисляемого столбца:

CREATE FUNCTION dbo.GetStatus(@DateTime1 DATETIME, @DateTime2 DATETIME)
RETURNS INT
AS BEGIN
    DECLARE @Result INT

    IF (@DateTime1 IS NULL AND @DateTime2 IS NULL)
       SET @Result = 0
    ELSE IF (@DateTime1 IS NULL AND @DateTime2 IS NOT NULL)
       SET @Result = 1
    ELSE IF (@DateTime1 IS NOT NULL AND @DateTime2 IS NULL)
       SET @Result = 2
    ELSE
       SET @Result = 3

    RETURN @Result
END

а затем вы определяете свой вычисляемый столбец как:

ALTER TABLE dbo.YourTable
    ADD Status AS dbo.GetStatus(DateTime1, DateTime2)
person marc_s    schedule 08.04.2010
comment
Спасибо за ответ! Но мне всегда нужны поля моей базы данных (от которых зависят значения вычисляемого столбца) в качестве входных параметров функции, верно? Нельзя ли работать в функции напрямую с полями строки (как члены объекта)? Например: вместо параметра @DateTime1 можно ли использовать что-то вроде dbo.MyTable.DateTime1? - person Slauma; 08.04.2010
comment
@Slauma: да, вы можете прочитать значения для своих строк внутри функции, но вам все равно нужно что-то передать, чтобы идентифицировать столбец, над которым вы работаете. Кроме того, если вы выполняете доступ к таблице внутри функции, вы не сможете сделать результирующий вычисляемый столбец PERSISTED, что в некоторых случаях желательно. - person marc_s; 08.04.2010
comment
Фактически, возможность сохранения вычисляемого столбца важна для моей цели (нужны быстрые запросы и индекс для столбца). Я начал следовать предложению Рэя, но полезно знать на будущее, что пользовательские функции также возможны для определения вычисляемого столбца. - person Slauma; 08.04.2010

Вы можете использовать триггер, чтобы обеспечить значение столбца при вставке или обновлении.

person Pablo Santa Cruz    schedule 07.04.2010
comment
Но триггер — это не вычисляемый столбец, не так ли? (Возможно, мне следовало выделить вопрос SQL Server для начинающих жирным шрифтом.) - person Slauma; 08.04.2010
comment
Ни в коем случае - триггер и вычисляемые столбцы - это две совершенно разные концепции - триггер вам здесь не поможет. - person marc_s; 08.04.2010