Во всех случаях, кроме самых простых внутренних ситуаций, я рекомендую всегда использовать суррогатный ключ.
Он дает вам варианты в будущем и защищает вас от неизвестных.
Нет причин, по которым дополнительные ключи, такие как SKU, нельзя сделать ненулевыми для их принудительного применения, но, по крайней мере, удалив свою зависимость от третьих сторон, вы даете себе возможность выбирать, а не иметь он забрал у вас и перенес мучительную переписку на более поздней стадии.
Если вы выберете целочисленное значение с автоинкрементом или сами определите следующий первичный ключ, то возникнут сложности. С помощью метода автоинкремента вы можете легко вставить запись и позволить ей назначить свой собственный ключ, но у вас могут возникнуть проблемы с определением, какой именно ключ был предоставлен вашей записи (и получение ключа max не гарантирует возврат вашего).
Я склоняюсь к самоназначенному ключу, потому что у вас больше контроля, и на сервере sql вы можете извлечь свой ключ из таблицы центральных ключей и убедиться, что никто другой не получит тот же ключ, все в одном выражении:
DECLARE @Key INT
UPDATE KeyTable
WITH (rowlock)
SET @Key = LastKey = LastKey + 1
WHERE KeyType = 'Product'
В таблице записан последний использованный ключ. Приведенный выше sql увеличивает этот ключ непосредственно в таблице и возвращает новый ключ, обеспечивая его уникальность.
Почему следует избегать буквенно-цифровых первичных ключей:
Три основные проблемы: производительность, сопоставление и пространство.
Производительность - производительность стоит, хотя, как и в случае с Раззи, я не могу цитировать любые цифры, но индексировать буквенно-цифровые числа менее эффективно, чем цифры.
Сопоставление - ваши разработчики могут создавать один и тот же ключ с разными сопоставлениями в разных таблицах (это бывает), что приводит к постоянному использованию команд 'collate' при объединении этих таблиц в запросах, что очень быстро устаревает.
Пробел - 9-символьный SKU, такой как у David, занимает девять байт, а целое - только четыре (2 для smallint, 1 для tinyint). Даже bigint занимает всего 8 байтов.