Какой тип данных использовать: Character или Integer

СУБД

Раньше, когда для хранения числовых данных в FoxPro существовали только поля типа Numeric перевес в аргументации склонялся в пользу использования полей типа Character, но с появлением полей типа Integer все стало не так однозначно

При сравнении способа хранения ключевого поля в символьном или числовом формате выдвигаются 3 аргумента

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

Числовые поля легче формировать

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

Замечу еще, что не стоит для генерации нового значения ключа использовать именно определение максимального значения в текущей таблице. Это хорошо в однопользовательском режиме, но в многопользовательском Вы рискуете получить 2 одинаковых значения ключа при одновременном добавлении новой записи двумя пользователями одновременно. Обычно используют специальную служебную таблицу, хранящуюю значение последнего использованного (или первого не использованного) значения ключа. Примеры использования такой таблицы приведены в стандартных проектах примеров FoxPro: Solution.pjx (форма NewID.scx) и TasTrade.pjx. А в 8 версии FoxPro появились автоинкрементные поля, которые совсем упростили данную задачу.

Символьные поля «экономичнее», т.е. можно уместить больше значений в том же размере

Начнем с вопроса, а сколько вообще необходимо значений для идентификации вообщех всех записей таблицы?

Из системных ограничений известно, что предельно допустимое количество записей в DBF-таблице — это 1 миллиард записей (1 billion). Т.е. это единица и девять нулей

Поле типа Integer может принимать знаячение в диапазоне от -2,147,483,647 до 2,147,483,647. Ну, отрицательные значения как правило не используются, но и положительные значения в 2 раза больше, чем максимально возможное количество записей. С учетом возможного удаления записей — в самый раз.

Поскольку поле типа Integer физически занимает 4 байта (4 символа), то посмотрим, сколько же значений может быть присвоено при таком же размере для символьного поля

В одном байте может быть записано 256 значений, т.е. это составит 256**4=4,294,967,296. Но поскольку некоторые значения нельзя использовать по ряду соображений (например, символ перевода строки, Esc и т.п.), то получается, что в смысле количества значений поля типа Integer ничуть не уступает полю типа Caracter(4), даже пожалуй несколько превосходит

Замечание

Следует заметить, что в FoxPro поля типа Numeric храняться как символьные поля, т.е. для хранения каждой цифры нужен один байт. Это значит, что если предполагаемое количество значений в данной таблице не превышает тысячи (меньше 4 символов), то возникает искушение «сэкономить» и вместо типа Integer ввести скажем поле типа N(2)

Так вот, я бы не советовал этого делать по следующим соображениям:

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

Символьные поля «универсальнее» при так назваемых задачах репликации

Репликация — это объединение информации из двух не связанных между собой баз данных, например, из двух филиалов одной организации территориально удаленных друг от друга

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

Здесь не место для обсуждения данной проблемы в связи с ее обширностью, поэтому замечу только, что для очень большого круга задач сама задача репликации не актуальна. Либо используется файл-серверная технология, либо объединение необходимо только в одну сторону для получения справок и отчетов
Вывод не столь категоричен, как в случае с суррогатными ключами:

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

Надо ли использовать ключевое поле во всех без исключения таблицах

На первый взгляд, вопрос может показаться странным. Разве можно без ключевого поля? Оказывается, в некоторых случаях можно.

Например, для организации связи много-ко-многим стандартным способом является создание таблицы-посредника. Что имеется в виду?

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

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

Однако я настоятельно рекомендовал бы Вам вводить-таки собственное ключевое поле для всех таблиц базы данных. Почему? Ну потому, что любая программа имеет «привычку» развиваться.

Если вернуться к примеру с контрагентами и банками, то легко заметить, что я обошел вниманием тот момент, что один контрагент может иметь несколько счетов в одном и том же банке. Этот самый реквизит (счет контрагента в банке) невозможно прицепить ни к банку, ни к контрагенту. Но он очень удачно подходит к этой таблице-посреднику. Если бы для идентификации записи в этой таблице Вы опирались бы на пару: код банка — код контрагента, то Вам пришлось бы серьезно переделывать значительную часть программы. А в случае существования собственного кода записи никаких проблем. Ну добавили еще одно поле, ну и что?

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