Каковы некоторые из ваших самых полезных стандартов баз данных?
У меня есть некоторые идеи, которые я накопил за какое-то время, но я действительно хочу знать, что заставляет вас работать гладко при моделировании базы данных:
- Имя таблицы соответствует имени первичного ключа и ключу описания
- Схемы по функциональным областям
- По возможности избегайте составных первичных ключей (используйте уникальные ограничения)
- Имена таблиц Case Camel и имена полей
- Не ставьте таблицы с префиксом tbl_ или процы с SP_ (без венгерской нотации)
- OLTP базы данных должны быть как минимум в BCNF / 4NF
30 ответов
Собираем вклад каждого в один список.
Стандарты именования
- Схемы названы по функциональной области (Продукты, Заказы, Доставка)
- Нет венгерской нотации: нет имен типов в именах объектов (без strFirstName)
- Не используйте зарегистрированные ключевые слова для имен объектов
- В именах объектов не должно быть пробелов или каких-либо специальных символов (разрешены только буквы алфавита + подчеркивание)
- Называйте объекты естественным образом (FirstName вместо NameFirst)
- Имя таблицы должно совпадать с полем "Имя первичного ключа" и полем "Описание" (SalesType - SalesTypeId, SalesTypeDescription)
- Не используйте префикс tbl_ или sp_
- Код имени по имени объекта (CustomerSearch, CustomerGetBalance)
- Имена объектов базы данных CamelCase
- Имена столбцов должны быть единственными
- Имена таблиц могут быть множественными
- Присвойте названия предприятия всем ограничениям (MustEnterFirstName)
Типы данных
- Используйте один и тот же тип переменной для разных таблиц (почтовый индекс - числовой в одной таблице и varchar в другой не очень хорошая идея)
- Используйте nNVarChar для информации о клиенте (имя, адрес (а)) и т. Д., Вы никогда не знаете, когда вы можете стать многонациональным
В коде
- Ключевые слова всегда в верхнем регистре
- Никогда не используйте подразумеваемые объединения (синтаксис запятых) - всегда используйте явное INNER JOIN / OUTER JOIN
- Один JOIN на строку
- Одно предложение WHERE на строку
- Нет циклов - замените логикой на основе набора
- Используйте короткие формы имен таблиц для псевдонимов, а не A, B, C
- Избегайте триггеров, если нет выхода
- Избегайте таких курсоров, как чума (читайте http://www.sqlservercentral.com/articles/T-SQL/66097/)
Документация
- Создать диаграммы базы данных
- Создать словарь данных
Нормализация и ссылочная целостность
- Максимально используйте первичные ключи в одном столбце. Используйте уникальные ограничения, где это необходимо.
- Ссылочная целостность всегда будет соблюдаться
- Избегайте УДАЛИТЬ КАСКАД
- OLTP должен быть не менее 4NF
- Оцените каждое отношение "один ко многим" как потенциальное отношение "многие ко многим"
- Первичные ключи, не созданные пользователем
- Построить Вставка на основе моделей вместо обновления на основе
- От PK до FK должно быть то же имя (Employee.EmployeeId - это то же поле, что и EmployeeSalary.EmployeeId)
- За исключением случаев двойного соединения (Person.PersonId соединяется с PersonRelation.PersonId_Parent и PersonRelation.PersonId_Child)
Обслуживание: запускайте периодические скрипты, чтобы найти
- Схема без таблицы
- Сиротские записи
- Таблицы без первичных ключей
- Таблицы без индексов
- Недетерминированный UDF
- Резервное копирование, Резервное копирование, Резервное копирование
Будь хорошим
- Быть последовательным
- Исправьте ошибки сейчас
- Прочитайте Стиль программирования SQL Джо Селко (ISBN 978-0120887972)
- Назовите одинаковые целевые хранимые процессы с одинаковым префиксом, например, если у вас есть 3 хранимые процедуры для Person. Таким образом, все для человека сгруппировано в одном месте, и вы можете легко найти их, не просматривая все свои процедуры, чтобы найти их.
- PersonUpdate
- PersonDelete
- PersonCreate
- Делайте аналогичные вещи для таблиц, когда у вас есть группы таблиц со связанными данными. Например:
- InvoiceHeaders
- InvoiceLines
- InvoiceLineDetails
- Если у вас есть выбор схем в вашей базе данных, используйте их. Гораздо приятнее видеть:
- Invoice.Header
- Invoice.Line.Items
- Invoice.Line.Item.Details
- Person.Update
- Person.Delete
- Person.Create
- Не используйте триггеры, если нет другого разумного подхода для достижения этой цели.
- Дайте именам полей значимый префикс, чтобы вы могли определить, из какой таблицы они приходят, без объяснения причин. Таким образом, когда вы видите имя поля, на которое ссылаются, вы можете легко определить, из какой таблицы оно происходит.
- Используйте согласованные типы данных для полей, содержащих сходные данные, т.е. не храните телефонный номер как числовой в одной таблице и varchar в другой. На самом деле, не храните его как числовой, если я найду отрицательный номер телефона, я сойду с ума.
- Не используйте пробелы или другие непонятные символы в именах таблиц / полей. Они должны быть полностью буквенно-цифровыми - или, если бы у меня были мои барабанщики, полностью алфавитными, за исключением подчеркивания. В настоящее время я работаю над унаследованной системой, где имена таблиц и полей содержат пробелы, вопросительные и восклицательные знаки. Заставляет меня хотеть убивать дизайнера ежедневно!
- Не используйте синтаксические ключевые слова в качестве имен объектов, это вызовет головную боль при попытке извлечь из них данные. Я ненавижу оборачивать имена объектов как [index], это два ненужных символа, которые мне не нужно было печатать, черт побери!
Одна вещь, которую я еще не видел, упоминается:
Никогда не используйте ключевые слова базы данных в качестве имен объектов. Вы не хотите получать их каждый раз, когда используете их
Если вы что-то неправильно написали при создании, исправьте это, как только заметите. Не тратьте годы на то, чтобы помнить, что в этой таблице UserName действительно Usernmae. Это намного легче исправить, когда против него написано не так много кода.
Никогда не используйте подразумеваемые объединения (синтаксис запятых), всегда указывайте объединения.
Мои стандарты для Oracle:
- Ключевые слова всегда в верхнем регистре;
- Имена объектов базы данных всегда в нижнем регистре;
- Символы подчеркивания заменят пробелы (т. Е. Не будет никаких соглашений о верблюдах, распространенных, скажем, на SQL Server);
- Первичные ключи почти всегда будут называться "id";
- Ссылочная целостность будет обеспечена;
- Целочисленные значения (включая идентификаторы таблиц) обычно всегда будут НОМЕР (19,0). Причина этого заключается в том, что это будет соответствовать 64-разрядному целому числу со знаком, что позволит использовать длинный тип Java вместо более неудобного BigInteger;
- Несмотря на неправильное добавление "_number" к некоторым именам столбцов, тип таких столбцов будет VARCHAR2, а не числовой тип. Числовые типы зарезервированы для первичных ключей и столбцов, по которым вы выполняете арифметику;
- Я всегда использую технические первичные ключи; а также
- Каждая таблица будет иметь свою последовательность генерации ключей. Имя этой последовательности будет _seq.
В SQL Server единственной модификацией является использование верблюда для имен объектов базы данных (т. Е. PartyName вместо party_name).
Запросы, как правило, пишутся многострочно с одним предложением или условием на строку:
SELECT field1, field2, field2
FROM tablename t1
JOIN tablename2 t2 ON t1.id = t2.tablename_id
WHERE t1.field1 = 'blah'
AND t2.field2 = 'foo'
Если предложение SELECT достаточно длинное, я разделю его по одному полю на строку.
Не забывайте регулярно делать резервные копии ваших баз данных.
Если база данных предназначена для конкретного приложения, имейте таблицу версий, чтобы выпуски базы данных можно было проверять по версиям кода (среди прочих причин).
Не используйте имена типов в именах полей. Старшие парни будут помнить старый стандарт MS lpszFieldName и последовавшую за этим глупость.
Используйте описательные имена полей, которые соответствуют обычным языковым соглашениям. Например, "FirstName" вместо "NameFirst"
Каждое слово в имени поля пишется с большой буквы
Без подчеркивания
Не используйте обычные ключевые слова, такие как "Индекс"
НИЧЕГО не ставьте перед типом объекта префикс. Например, мы НЕ используем tblCustomers или spCustomersGet. Они не учитывают хорошую сортировку и обеспечивают нулевое значение.
Используйте схемы для определения отдельных областей базы данных. Такие как продажи. Клиенты и сотрудники. Это избавит от большинства префиксов, которые используют люди.
Любые петли следует рассматривать с подозрением. Там обычно лучший способ на основе набора.
Используйте представления для сложных объединений.
Избегайте сложных соединений, когда это возможно. Может быть более эстетично иметь таблицу CustomerPhoneNumbers; но, честно говоря, сколько телефонных номеров нам действительно нужно хранить? Просто добавьте поля в таблицу клиентов. Ваши запросы к БД будут быстрее, и их будет намного легче понять.
Если одна таблица вызывает поле "EmployeeId", то КАЖДЫЙ ОДИН СТОЛ, который ссылается на нее, должно использовать это имя. Его не нужно называть CustomerServiceRepId только потому, что он находится в таблице расширений.
Почти все таблицы имеют окончание "s". Например: клиенты, заказы и т. Д. Ведь в таблице содержится много записей...
Оценивайте свои запросы, индексы и отношения с внешними ключами с помощью инструмента анализа. Даже те, которые могут быть созданы для вас. Вы можете быть удивлены.
Связывающие таблицы, которые поддерживают отношения "многие ко многим", имеют в названии обе связанные таблицы. Например, SchoolsGrades. По названию таблицы очень легко определить, что она делает.
Быть последовательным. Если вы начнете идти по одному пути с вашими соглашениями, не меняйте лошадей на полпути, если вы не готовы реорганизовать всю предыдущую работу. Это должно затормозить любые идеи "не было бы замечательно, если…", которые в итоге приводят к путанице и огромному количеству переделок.
Подумайте, прежде чем печатать. Вам действительно нужна эта таблица, поле, sproc или view? Вы уверены, что это не покрыто где-то еще? Получить консенсус, прежде чем добавить его. И если по какой-то причине вы должны его снять, сначала поговорите с вашей командой. Я был в тех местах, где администраторы баз данных ежедневно вносили изменения, не обращая внимания на разработчиков. Это не весело.
Я всегда стараюсь не использовать тип в имени поля - "sFirstName", "sLastName" или "iEmployeeID". Хотя они сначала совпадают, если что-то изменится, они будут не синхронизированы, и позже поменять эти имена будет огромной головной болью, так как вам также придется менять зависимые объекты.
Intellisense и инструменты GUI упрощают определение типа столбца, поэтому я не считаю это необходимым.
Убедитесь, что каждый выбор varchar/nvarchar подходит.
Убедитесь, что каждый выбор столбца NULLable подходит - избегайте столбцов NULLable, где это возможно - разрешение NULL должно быть оправданной позицией.
Независимо от любых других правил, которые вы можете использовать из приведенных здесь предложений, я бы создал хранимую процедуру в базе данных, которую можно запускать на регулярной основе, чтобы определить работоспособность системы для любых ваших правил или стандартов, которые у вас есть (некоторые из них - немного SQL-Сервер специфичен):
Ищите потерянные записи в тех случаях, когда ссылочная целостность системы СУБД не может быть использована по какой-либо причине (в моей системе у меня есть таблица процессов и таблица тестов - так что мой system_health SP ищет процессы без тестов, поскольку у меня есть только односторонние отношения FK)
Ищите пустые схемы
Ищите таблицы без первичных ключей
Ищите таблицы без каких-либо индексов
Ищите объекты базы данных без документации (мы используем расширенные свойства SQL Server, чтобы поместить документацию в базу данных - эта документация может быть такой же гранулированной, как столбец).
Ищите системные проблемы - таблицы, которые необходимо архивировать, исключения, которые не являются частью обычной ежемесячной или ежедневной обработки, определенные общие имена столбцов со значениями по умолчанию или без них (скажем, CreateDate).
Ищите недетерминированные UDF
Ищите комментарии TODO, чтобы гарантировать, что код в БД не имеет непроверенного или предварительного выпуска кода.
Все это может быть автоматизировано, чтобы дать вам общую картину состояния системы.
Предложение WITH действительно помогает разбивать запросы на управляемые части.
Это также помогает повысить эффективность планов выполнения запросов.
Каждый пишет SQL-запросы (представления, хранимые процедуры и т. Д.) В одном базовом формате. Это действительно помогает усилиям по разработке / обслуживанию в будущем.
Несколько любит и не любит.
Мое мнение, что приставки ужасны во всех аспектах. В настоящее время я работаю в системе, в которой таблицы имеют префикс, а столбцы в таблицах имеют двухбуквенные аббревиатуры с именами таблиц. Я трачу не менее 30 минут каждый день на работу с этой базой данных, потому что аббревиатура не логична. Если вы хотите обозначить что-то префиксом, используйте вместо этого владельца схемы.
Использование NVarchar с самого начала проекта, если есть даже небольшой намек на то, что в дальнейшем текстовые данные должны будут поддерживать многоязычные символы. Обновление больших баз данных из-за отсутствия перспективного планирования и мышления - это боль и пустая трата времени.
Разделение каждого условия в предложении where на новую строку для удобочитаемости (а не в операторах, заключенных в квадратные скобки и вкладки.) Я думаю, что это важный стандарт для меня.
Я работал в одной компании, где стандартом было то, что запятые всегда должны помещаться в начале строки при выполнении объявлений параметров или переменных. Это, очевидно, сделало его более читабельным, однако я нашел его полным кошмаром.
Согласованные стандарты именования. Присутствие всех на одной странице, использование одного и того же формата (будь то Camel Case, конкретные префиксы и т. Д.) Помогает точно поддерживать систему.
Некоторые другие (пусть и небольшие) комментарии бросать к стене...
Схемы базы данных SQL Server могут быть полезны как для организации таблиц и хранимых процедур, так и для контроля безопасности.
Каждая транзакционная таблица должна всегда отслеживать, кто и когда создавал запись, а также обновлять запись в отдельных столбцах. Я видел реализацию, которая просто использовала "дату обновления", что может привести к проблемам с аудитом в будущем.
Используйте GUID для идентификаторов строк для всех строк в проектах с требованиями офлайн / синхронизации.
Табличный форматированный SQL.
select a.field1, b.field2
from any_table a
inner join blah b on b.a_id = a.a_id
inner join yet_another y on y.longer_key = b.b_id
where a.field_3 > 7
and b.long_field_name < 2;
Часть этого заключается в использовании одинаково длинных псевдонимов (в данном примере a, b и y имеют длину 1).
С помощью этого вида форматирования я могу быстрее ответить на распространенные вопросы, такие как "какая таблица имеет псевдоним" a "?" и "какие поля присоединяют таблицу T к запросу?" Структура не занимает много времени, чтобы применить или обновить, и я считаю, что это экономит много времени. Мы тратим больше времени на чтение кода, чем на его написание.
В дополнение к нормализации до 3NF или BCNF (подробнее об этом в этом вопросе), я нашел следующее полезным:
- Назовите таблицы как существительные во множественном числе
- Назовите столбцы как сигулярные
Таким образом, у таблицы People есть столбец PersonID.
- В составных ключах нет ничего плохого, если правила 3NF или BCNF остаются в силе. Во многих случаях (например, в случае "многие ко многим") это совершенно желательно.
- Избегайте повторения имени таблицы в именах столбцов. В любом случае peoplePersonID лучше записать как table.column, и он гораздо более читабелен и поэтому самодокументирован. People.PersonID лучше, мне как минимум.
- НА УДАЛЕННОМ КАСКАДЕ следует использовать очень осторожно.
- Помните, что NULL означает одно из двух: либо оно неизвестно, либо не применимо.
- Помните также, что значения NULL оказывают интересное влияние на объединения, поэтому попрактикуйтесь во внешних соединениях LEFT, RIGHT и FULL.
- Таблицы названы в единственном числе, в нижнем регистре, без подчеркивания, без префикса
- Поля также строчные, без подчеркивания, без префикса
- Хранимые процедуры с префиксом "st_" (сортирует красиво)
- Представления, которые обрабатываются как таблицы, не имеют префикса
- Представления, созданные для специальных отчетов и т. Д., Имеют префикс "v"
- Индексированные представления, созданные для повышения производительности, имеют префикс ixv
- Все индексы имеют целевые имена (без автоматического именования)
- Настоятельно предпочитайте uniqueidentifier (с последовательным приращением) вместо int IDENTITY для суррогатных ключей
- Не искусственно ограничивайте поля VARCHAR/NVARCHAR 100 или 255. Дайте им пространство для дыхания. Это не 1980-е годы, поля не хранятся с добавлением их максимальной длины.
- Минимальный стандарт 3NF
- Предпочитают объединять таблицы с внешними ключами на уровне столбцов: многие предположения 1:m оспариваются по мере роста системы с течением времени.
- Всегда используйте суррогатные ключи, а не естественные ключи, в качестве первичного ключа. Все предположения о "естественных" ключах (SSN, имена пользователей, номера телефонов, внутренние коды и т. Д.) В конечном итоге будут оспорены.
Принимая "базу данных" в значении "продукт SQL", я отвечаю: "Слишком много, чтобы упомянуть. Вы можете написать целую книгу по этому вопросу". К счастью, у кого-то есть.
Мы используем стиль программирования SQL Джо Селко (ISBN 978-0120887972): "Эта книга представляет собой набор эвристик и правил, советов и приемов, которые помогут вам улучшить стиль и мастерство программирования на SQL, а также для форматирования и написания переносимых, читаемых, поддерживаемых" SQL-код."
Преимущества этого подхода включают в себя:
- парень знает больше о таких вещах, чем я (есть еще одна книга по эвристике SQL?!);
- работа уже сделана, например, я могу дать книгу кому-то из команды, чтобы она прочитала ее и сослалась на нее;
- если кому-то не нравится мой стиль кодирования, я могу винить кого-то другого;
- Недавно я получил много повторений на SO, порекомендовав еще одну книгу Celko:)
На практике мы отклоняемся от рецептов Книги, но на удивление редко.
В MS-SQL у меня всегда были объекты, принадлежащие dbo., И я добавляю вызовы к этим объектам с помощью dbo.
Слишком много раз я видел, как наши разработчики удивлялись, почему они не могут назвать свои объекты, которыми они случайно владели.
Документировать все; Документация типа вики проста в настройке и программное обеспечение бесплатно.
Сначала убедитесь, что вы понимаете интерфейс, а затем создаете базу данных. В большинстве случаев гораздо лучше знать, как должны работать данные, которые вы собираетесь использовать, а затем проектировать базу данных. В большинстве случаев плохой дизайн БД происходит по мере того, как вещи развиваются не заранее.
Затем определите стандарт и версию базы данных, с которой вы собираетесь работать. Определить стандарты для элементов кода (представления, функции и т. Д.), Именования баз данных; соглашения об именах столбцов, таблиц; условные обозначения для столбцов; шаблоны кодирования.
Потратьте время на изучение того, как вы определяете типы, имеющие стандартные типы баз данных для полей или заказные типы, - это хорошая вещь, чтобы разобраться заранее.
В качестве части вашей документации включите список того, что нужно и что нельзя делать для приложения, в том числе ваши любимые ненавистные функциональные курсоры, триггеры.
Проверяйте это регулярно.
Имя таблицы соответствует имени первичного ключа и ключу описания
Я только недавно, после нескольких лет согласия с этим, прыгнул с корабля, и теперь у меня есть столбец "ID" на каждой таблице.
Да, я знаю, при связывании таблиц это сложно! Но то же самое относится и к привязке ProductID к ProductID.
Это:
SELECT p.Name, o.Quantity FROM Products p, Orders o WHERE o.ProductID = p.ID
Это немного лучше, чем это:
SELECT p.Name, o.Quantity FROM Products p, Orders o WHERE o.ProductID = p.ProductID
Обратите внимание, что оба будут требовать префиксов таблиц или псевдонимов. Но я не только набираю немного меньше (умножьте это на десятки таблиц с длинными описательными именами, и это быстро складывается в приложении, интенсивно использующем данные), но также помогает легче узнать, какая таблица является родительской таблицей в каждом соединении, которое, при объединении 8-10 таблиц в запросе может помочь совсем немного.
Избегайте глупых соглашений о сокращениях, таких как исчерпывающие словари сокращений, которые активно поощряют чудовищ, таких как EMP_ID_CONV_FCTR_WTF_LOL_WAK_A_WAK_HU_HU. Это правило вдохновлено реальным набором рекомендаций, которые я видел раньше.
Здесь я придерживаюсь тех же самых соглашений, что и другие, но я хотел сказать несколько вещей, которые еще не были сказаны.
Независимо от того, любите ли вы множественные или единственные имена для ваших таблиц, будьте последовательны. Выберите один или другой, но не используйте оба.
Первичный ключ в таблице имеет то же имя, что и таблица, с суффиксом _PK. Внешние ключи имеют то же имя, что и соответствующий первичный ключ, но с суффиксом _FK. Например, первичный ключ таблицы Product называется Product_PK; в таблице "Заказ" соответствующий внешний ключ - Product_FK. Я подхватил эту привычку у другого друга из DBA, и мне она пока нравится.
Всякий раз, когда я делаю INSERT INTO...SELECT, я псевдоним всех столбцов в части SELECT, чтобы соответствовать именам столбцов из части INSERT INTO, чтобы упростить обслуживание и посмотреть, как все совпадает.
Самый важный стандарт: нет базы данных по умолчанию. Я нахожу слишком много разработчиков, собирающих базу данных для проектов, где жизнь была бы намного проще без нее (по крайней мере, пока). Это просто инструмент в наборе инструментов, и не каждая проблема - это гвоздь.
Неправильное использование базы данных приводит к анемичным моделям доменов, плохо тестируемому коду и ненужным проблемам с производительностью.
13- Оцените ваши запросы
Это правда. Иногда вы не получаете то, что хотели.
Для меня всегда полезно называть таблицы и поля с их точным содержимым и (для нас) на чистом испанском языке с использованием Upper Camel Case, без пробелов:
Имя пользователя: NombreUsuario
Имя: АпеллидоПатерно
Вторая Фамилия: АпеллидоМатерно
и т. д.
Мне нравится наше соглашение об именах таблиц:
People Table
PEO_PersonID
PEO_FirstName
...
Что помогает сделать большие запросы немного более читабельными. и объединения имеют больше смысла:
Select * -- naughty!
From People
Join Orders on PEO_PersonID = ORD_PersonID
--...
Я предполагаю, что согласованность именования заключается не в том, что такое соглашение об именах.
Я согласен почти со всем, что вы положили туда, кроме #5. Я часто использую префиксы для таблиц и хранимых процедур, потому что системы, которые мы разрабатываем, имеют множество различных функциональных областей, поэтому я буду стремиться ставить префиксы таблицам и sprocs с помощью идентификатора, который позволит им красиво группироваться в Management Studio в зависимости от того, в какой области они принадлежат.
Пример: cjso_Users, cjso_Roles, а затем у вас есть routing_Users, routing_Roles. Это может звучать как репликация данных, но на самом деле две разные таблицы пользователей / ролей предназначены для совершенно отдельных функций системы (cjso будет для приложения электронной коммерции на основе клиентов, в то время как маршрутизация будет означать сотрудников и дистрибьюторов, которые используют маршрутизацию система).