Есть ли смысл в типе данных SQL VARCHAR (1)? - PullRequest
19 голосов
/ 02 февраля 2011

Я столкнулся со многими полями VARCHAR (1) в базе данных, с которой мне недавно приходилось работать.Я закатил глаза: очевидно, дизайнер не имел ни малейшего понятия.Но, возможно, мне нужно чему-то научиться.Есть ли какая-либо мыслимая причина использовать тип данных VARCHAR (1), а не CHAR (1)?Я думаю, что RDMS автоматически преобразует одну в другую.

База данных - MS SQL 2K5, но эволюционировала из Access в тот же день.

Ответы [ 3 ]

16 голосов
/ 02 февраля 2011

Да, в этом есть смысл.

  • Легче быть определяемым на языке. Последовательно и легче определить varchar, чтобы разрешить 1-8000, чем сказать, что оно должно быть от 2+ или от 3+ до 8000.

  • Аспект VARying CHARacter в VARCHAR (1) именно такой. Может быть не оптимальным для хранения, но передает конкретное значение, что данные являются либо 1 символом (код класса), либо пустым (внешняя деятельность) вместо NULL (неизвестно / еще не классифицировано).

Хранилище играет в этом очень незначительную роль - глядя на схему базы данных для CHAR (1), вы почти ожидаете, что она всегда должна иметь значение 1 символ, например, кредитные карты должны иметь 16 цифр. Это просто не относится к некоторым данным, где они могут быть единичными или необязательно никакими.

Существуют также различия в использовании комбинации VARCHAR (1) и CHAR (1) + NULL для тех, кто говорит о трех состояниях [1-char | 0-символ | NULL] совершенно бесполезно. Это позволяет для операторов SQL, таких как:

select activity + '-' + classroom
from  ...

, что в противном случае было бы сложнее, если бы вы использовали char (1) + NULL, который может передавать ту же информацию, но имеет небольшие различия.

10 голосов
/ 02 февраля 2011

AFAIK, №

a VARCHAR(1) требует хранения 3 байта (Размер хранилища - это фактическая длина введенных данных + 2 байта. Ссылка .

CHAR(1) требуется 1 байт.

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

AПричина, по которой следует избегать varchar (1) (кроме того факта, что они передают плохие рассуждения о дизайне, IMO), заключается в использовании Linq2SQL: LINQ to SQL и поля varchar (1)

5 голосов
/ 06 октября 2012

A varchar(1) может хранить строку нулевой длины («пустую»).char(1) не может, так как он будет дополнен одним пробелом.Если это различие важно для вас, вы можете отдать предпочтение varchar.

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

Изменение типа данных фиксированной длины с char(1) на char(2) означает, что необходимо обновить все строки таблицы и все индексы или ограничения, которые обращаются к этому столбцу, удаляются первыми.

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

Изменить столбец с varchar(1) на varchar(2) гораздо проще, поскольку онизменение только метаданных (ограничения FK, которые ссылаются на столбец, должны быть удалены и воссозданы, но нет необходимости перестраивать индексы или обновлять страницы данных).

Более того, сохранение 2 байтов в строке не всегда может произойти.Если определение строки уже довольно длинное, это не всегда влияет на количество строк, которые могут поместиться на странице данных.Другой случай был бы, если при использовании функции сжатия в Enterprise Edition способ хранения данных полностью отличается от упомянутого в ответе Митча в любом случае.И varchar(1), и char(1) в конечном итоге будут храниться одинаково в короткой области данных.

@ Thomas - например, попробуйте это определение таблицы.

CREATE TABLE T2
(
Code VARCHAR(1),
Foo datetime2,
Bar int,
Filler CHAR(4000),
PRIMARY KEY CLUSTERED (Code, Foo, Bar)
)

INSERT INTO T2
SELECT TOP 100000 'A', 
                  GETDATE(), 
                  ROW_NUMBER() OVER (ORDER BY (SELECT 0)),
                  NULL
FROM master..spt_values v1,  master..spt_values v2

CREATE NONCLUSTERED INDEX IX_T2_Foo ON T2(Foo) INCLUDE (Filler);
CREATE NONCLUSTERED INDEX IX_T2_Bar ON T2(Bar) INCLUDE (Filler);

Для varchar тривиально изменить определение столбца с varchar(1) на varchar(2).Это изменение только метаданных.

ALTER TABLE T2 ALTER COLUMN Code VARCHAR(2) NOT NULL

Если изменение от char(1) до char(2), должны быть выполнены следующие шаги:

  1. Удалите PK из таблицы.Это преобразует таблицу в кучу и означает, что все некластеризованные индексы необходимо обновить с помощью RID, а не ключа кластеризованного индекса.
  2. Измените определение столбца.Это означает, что все строки в таблице обновлены, поэтому Code теперь сохраняется как char(2).
  3. Добавьте обратно кластерное ограничение PK.Наряду с перестройкой самого CI это означает, что все некластеризованные индексы необходимо снова обновить с помощью ключа CI в качестве указателя строки, а не RID.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...