Имитировать перечисления в TSQL? - PullRequest
11 голосов
/ 08 июня 2009

Я недавно случайно написал действительно уродливый хранимый процесс, где я хотел, чтобы у меня были перечисления,

Например.

CREATE PROCEDURE Proc_search_with_enum @user int, @account_category {enum}

Я понимаю, что в SQL 2000 нет перечислений в качестве конструкции языка первого класса, какие соглашения о кодировании вы используете для имитации перечислений или иным образом для решения той же проблемы?

Или я обречен на использование VARCHAR и IF @ account_category = 'cat1'?

РЕДАКТИРОВАТЬ: T-SQL и C # являются языками клиента.

РЕДАКТИРОВАТЬ: Спасибо всем! Множество полезных советов, я хотел бы принять несколько ответов, я проголосовал за всех -

Сводка ответов

  • Опираться на перечисление C #, используя int. Хорошо для кода клиента C #, делает клиент TSQL Код менее читабелен.
  • Используйте Char / Varchar. Плохо для клиентского кода C # (не подходит для локализации), делает Код TSQL более читабелен.
  • Используйте код проверки параметров для ограничения параметр, или используйте ограничение на столбец таблицы или внешний ключ, если параметр будет вставлен в стол.

Ответы [ 9 ]

11 голосов
/ 08 июня 2009

Вы можете взглянуть на ответ на этот вопрос . Насколько я знаю, типы enum не являются частью SQL Server.

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

В C # по умолчанию каждое значение перечисления соответствует целому числу, начиная с 0. Вы можете даже приводить между ними, так что это правильный код:

public enum MyEnum
{
    FirstEnumValue,
    SecondEnumValue
}

...

// Assuming you have opened a SqlDataReader.
MyEnum enumValue = (MyEnum) reader["account_category"];

И LINQtoSQL также поддерживает это. Если у вас есть свойство типа enum и столбец вашей базы данных имеет целочисленный тип, преобразование выполняется автоматически.

2 голосов
/ 08 июня 2009

Я обычно предпочитаю вызывать параметр @account_category_code и делать его CHAR (3), если есть только несколько значений перечисления, и все они могут быть четко выражены тремя буквами. Затем для домена применяется ограничение проверки. Если имеется более нескольких значений (более 4 или 5), я обычно переключаюсь на tinyint / smallint с именем @account_category_type_id и имею таблицу доменов, на которую можно ссылаться. У нас нет жестких правил в моей организации, но я считаю, что это хорошо работает.

2 голосов
/ 08 июня 2009

В PostgreSql я просто использую VARCHAR с прикрепленными ограничениями ...

CREATE TABLE movie_clip (        
    type VARCHAR(40) NULL CHECK(type IN ('trailer', 'commercial')),
);

#=> insert into movie_clip (type) values ('trailer');
INSERT 0 1
#=> insert into movie_clip (type) values ('invalid value');
ERROR:  new row for relation "movie_clip" violates check constraint "movie_clip_type_check"

#=> \d movie_clip
....
"movie_clip_type_check" CHECK (type::text = ANY (ARRAY['trailer'::character varying, 'commercial'::character varying]::text[]))

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

Подробнее об ограничениях для Postgres см. Здесь: http://www.postgresql.org/docs/8.1/static/ddl-constraints.html

1 голос
/ 08 июня 2009

Вы можете создать представление для имитации Enum. Смотрите эту статью http://www.olegsych.com/2008/07/t4-template-for-generating-sql-view-from-csharp-enumeration/

1 голос
/ 08 июня 2009

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

1 голос
/ 08 июня 2009

Будьте предельно осторожны при использовании типа CHAR для enum и вообще избегайте его, если хотите, чтобы ваш app / db выходил на международный уровень.
Не путайте DATA с его представлением: как следует из слов, enum (eration) - это число, его описание - совершенно другое дело. Короче говоря, используя переменную / поле CHAR для перечисления, вы привязываете себя к определенному языку для их описания: например, вы можете забыть о интернационализации. Вы можете себе представить, что означает слово «Weltmeisterschaft», на каком языке и, более того, сколько может быть неправильного написания? На самом деле, (крошечный) int имеет обратную сторону значений, не являющихся автоматически описательными: я не говорил, что это идеальное решение!

1 голос
/ 08 июня 2009

Иногда тип CHAR более удобен, чем INT - символ фиксированного размера не занимает много места в памяти, и вы можете видеть «перечисляемые» значения непосредственно в полях базы данных. Без разницы со стороны кода, но большой прогресс при работе непосредственно с инструментами SQL.

0 голосов
/ 16 мая 2012

Вы можете использовать оператор CASE .

Чтобы создать пример enum-esque из набора результатов, вы можете сделать что-то вроде этого:

SELECT
    FirstName,
    LastName,
    CASE JobTitle WHEN 0 THEN 'Software Developer' WHEN 1 THEN 'Software Architect' WHEN 2 THEN 'President' ELSE 'Staff' END AS 'Job Title',
    Salary
FROM
    Employees

Вы в основном запускаете целое число через что-то вроде оператора SWITCH. Поместите его в свою хранимую процедуру, чтобы вам не приходилось писать один и тот же код снова и снова. Надеюсь, это поможет. enter code here

0 голосов
/ 06 мая 2012

Самый простой способ сделать это в Transact-SQL - использовать ограничение CHECK. Вы можете прочитать больше об этом здесь или здесь . Это ограничение также доступно в PostgreSQL и Oracle.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...