Стиль программирования Джо Селко на SQL
Стиль программирования Джо Селко на SQL
Селко Д.
Стиль программирования Джо Селко на SQL / Пер. с англ. — М.: Издательство «Русская Редакция»; СПб.: Питер, 2006. — 206 стр.: ил.
ISBN 5-469-01396-0 («Питер»)
ISBN 5-7502-0276-3 («Русская Редакция»)
Книга предназначена программистам, работающим с SQL и желающим повысить свою квалификацию. В ней рассматриваются вопросы, связанные с созданием стандартизованных SQL-приложений, не привязанных к конкретным SQL-продуктам, приводятся многочисленные практические рекомендации по созданию наиболее эффективных и универсальных кодов. Рассматриваются правила назначения имен элементам данных, оформления программ, разработки выражений DDL и DML Описано использование представлений и хранимых процедур. Отдельные главы посвящены общим теоретическим вопросам, связанным с теорией измерений и разработкой систем кодирования для элементов баз данных.
Книга состоит из 10 глав, библиографии и приложения, содержащего справочную информацию по различным стандартам, пригодным для использования в различных базах данных.
УДК 004.45
ББК 32.973.26-018.2/С36
ОГЛАВЛЕНИЕ
ВВЕДЕНИЕ. 3
ГЛАВА 1. Имена и элементы данных. 5
ГЛАВА 2. Шрифты, пунктуация и интервалы.. 17
ГЛАВА 3. Язык объявления данных. 27
ГЛАВА 4. Шкалы и измерения. 42
ГЛАВА 5. Схемы кодировки данных. 49
ГЛАВА 6. Выбор подхода к написанию кода. 57
ГЛАВА 7. Представления. 78
ГЛАВА 8. Хранимые процедуры.. 89
ГЛАВА 9. Эмпирические правила кодирования. 100
ГЛАВА 10. Думаем на SQL. 107
ПРИЛОЖЕНИЕ 1. 115
ПРИЛОЖЕНИЕ 2. 117
ВВЕДЕНИЕ В этой книге я вовсе не пытаюсь учить вас программировать на SQL. Хотите — прочитайте предыдущее предложение еще раз. Если вас интересует именно обучение, есть учебники и получше. Эта книга призвана стать вашей второй книгой по SQL, но отнюдь не первой. Я предполагаю, что вы уже обладаете некоторыми навыками программирования на SQL и теперь хотите их усовершенствовать. Чтобы познакомиться с тонкостями SQL, почитайте другую мою книгу — SQLforSmarties (3-е издание, 2005). Я стараюсь ставить в основу обучения логичность и ясность и учить читателя мыслить в декларативных терминах, а не в терминах процедурного или объектно-ориентированного программирования. Вряд ли найдется SQL-программист, не обладающий многолетним стажем работы с каким-либо процедурным или объектно-ориентированным языком. Обыкновенно предлагают освоить один конкретный SQL-продукт, выучив язык методом проб и ошибок или по книге с заголовком наподобие “SQL для идиотов”, “Учим SQL за десять легких или пять трудных уроков”, а то и похуже. Это просто абсурд! Человеку требуется не менее пяти лет, чтобы стать квалифицированным плотником или поваром. Почему же считается, что превратиться в гуру SQL он может за пару дней? За эго время реально стать лишь плохим SQL-программистом, который разговаривает на диалекте SQL из популярного в данном месте SQL-продукта, к тому же с сильным акцентом от известных ему других языков программирования. Чтобы вернуться с облаков на землю, почитайте Teach Yourself Programming in Ten YearsПитера Норвига (Peter Norvig, www.norvig.com/21-days.html) или статью No Silver Bullets Фреда Брукса (Fred Brooks), опубликованную в апреле 1987 г. журналом Computer (№ 20 (4), с. 10-19). Беда еще и в том, что жертвы подобной системы обучения часто не осознают, что являются плохими программистами. Бывает так, что весь коллектив работает по схожим правилам, так что они ничего другого просто не видели. Иные же “лезут в бутылку”, если кто-то пытается указать им на недостатки. Взгляните на сообщения в группах новостей, посвященных SQL, и вы увидите, что большинство программистов желает не расправиться с проблемой всерьез и надолго, а просто получить сиюминутное решение для конкретной ситуации. В группах новостей по изготовлению мебели их вопросы звучали бы так: “Каким камнем лучше всего забивать шурупы в красное дерево?”. Чтобы осчастливить такого программиста, ему достаточно посоветовать большую гранитную глыбу. Но попробуйте рассказать ему об отвертке — вызовете вспышку гнева в свой адрес. Цель книги Как же учились быть хорошими программистами мы, старики, когда Землей правили динозавры? В конце 1970-х, когда в нашу жизнь вошло структурированное программирование, одним из лучших наших помощников стала серия книг “[Pascal | FORTRAN | COBOL | BASIC] with Style: Programming Proverbs”, написанная Генри Ледгардом (Henry Ledgard) и несколькими его коллегами из Массачусетского технологического института. Их обложки оформлялись в духе викторианского романа: с ангелами, свитками, старомодными типографскими элементами. Каждой книге, как викторианскому роману, полагался подзаголовок типа “Основы хорошего программирования с многочисленными примерами для усовершенствования стиля и сноровки”. Эти и другие книги сыграли большую роль в жизни большинства из нас, поскольку научили думать так, как должны думать хорошие программисты. В этом же состоит цель и моей книги — усовершенствовать стиль и качество программирования на SQL Говоря точнее: 1. Помочь отдельному программисту писать программы на стандартном SQL, без акцента и диалекта.Отказаться от старых привычек трудно, но не невозможно. Лучше же всего учиться правильному образу действий с самого начала. Любитель пишет код для себя. Профессионал разрабатывает программу, которую будут использовать и обслуживать другие люди. Мой опыт говорит, что пройдет не меньше года программирования на SQL, прежде чем на вас снизойдет просветление и выувидите триединство мира: логика, модели данных и множества. 2. Предоставить коллективу программистов внутренний стандарт программирования.Каждому правилу я пытался дать продуманное обоснование, а также рассказал об исключениях там, где мне удалось их увидеть. Вы вольны не согласиться с некоторыми из моих предложений, но тогда уж извольте провести исследование и подкрепить свою позицию примерами. Вряд ли можно считать аргументом заявления типа: “Да мы в нашей конторе всегда так программируем, стало быть, такова воля Божья!”. Руководителю коллектива, опирающегося на мои правила, в случае недовольства сотрудников всегда можно будет обвинить во всем книгу (и ее автора). Благодаря ей вы сохраните согласованность действий. Даже если позже окажется, что я в чем-то ошибся, значительно проще исправлять ошибки, сделанные в единой системе. 3. Предоставить программистам необходимые инструменты для оценки решаемой проблемы с точки зрения SQL.He устаю повторять, что требуется не меньше года, чтобы “въехать” в SQL и избавиться от привычек, навязанных процедурным программированием. Благодарности Структура главы о представлениях принадлежит Крейгу Маллинсу (Craig Mullins) (см. статью для www.DBAzine.com). Стиль форматирования позаимствован из моих публикаций за последнее десятилетие в журналах СМР и других. Данные о правилах присвоения имен в реальных продуктах предоставил Питер Гулутзан (Peter Gulutzan) — также в статье для www.DBAzine.com. Правила разработки приставок к именам в главе 1 основаны на внутренних стандартах корпорации Teradata. Масштабы, величины и схемы кодирования фигурировали в нескольких моих старых колонках в журналах DBMS и Database Programming&Design, а затем были объединены в моей книге Data & Database. В тексте я всегда старался упомянуть моих помощников, но в группах новостей участников так много, что я несомненно кого-то пропустил. Разумеется, я благодарен Генри Ледгарду за серию “Programming Proverbs”, которая служила мне источником вдохновения. Особенная благодарность — новичкам-программистам, пишущим плохие программы. Это замечание кажется саркастическим, но таковым не является. Многие из них столкнулись с DBA или SQL по воле руководства, которое не обеспечило их обучением или опытным наставником. Их не в чем обвинить, конечно, если они не упорствовали в своем невежестве. Их ошибки в синтаксисе, семантике и стиле показали мне, как они думают. Правильный диагноз — первый шаг к излечению. Исправления, замечания и последующие издания Исправления и дополнения к будущим изданиям направляйте непосредственно в издательство Morgan-Kaufmann или мне по электронному адресу [email protected]. |
ГЛАВА 1.
Имена и элементы данных
Есть такой старый анекдот. — Когда я был маленьким, у нас было три кошки. — И как их звали? — Кошка, кошка и кошка. — Ерунда какая-то. Как же вы их различали? — А какая разница? Кошки все равно на имена не откликаются! |
Наши данные тоже не придут к вам на зов, если вы не присвоите им четкие и понятные имена. Это важная часть любого проекта базы данных (БД). Неудачные имена для элементов данных приводят к тому, что код бывает трудно, а то и невозможно прочитать.
Невозможность чтения — не шутка. В старину компании, разрабатывавшие программное обеспечение, нарочно искажали имена и удаляли из исходного кода форматирование, чтобы скрыть от покупателей алгоритм. Эта традиция все еще жива, хотя, может быть, изначальное намерение и утрачено. В августе 2004 г. в одной из групп новостей по SQL была опубликована программа, в которой все имена состояли из одной буквы и длинной цепочки цифр.
В настоящее время существуют стандарты метаданных ISO-11179, описывающие правила именования элементов данных и регистрации стандартов. Поскольку это стандарт ISO, его надлежит применять не только в SQL, но и вообще везде.
Стандартизация, немного печатного мастерства и некоторый здравый смысл — вот слагаемые успешной работы.
Имена
В старые добрые времена у каждого программиста были собственные правила назначения имен. К несчастью, зачастую они оказывались весьма замысловатыми. Лично мне особенно нравился парень, который для имен в программах на Коболе выбирал специфическую тему: для одной программы — страны, для другой — цветы и т. д. Это, конечно, чересчур даже для программиста, но вообще системы имен, смысл которых понятен только автору, но не посторонним, встречаются часто.
Скажем, первый Фортран, с которым я работал, допускал имена не длиннее шести символов, поэтому я стал адептом шестибуквенных имен. Программисты, которые начинали со слабо типизированных языков или с языков без типов, испытывают привязанность к венгерской нотации. От старых привычек трудно отказываться.
Когда разработка ПО перестала быть уделом одиночек, каждая фирма создавала собственные правила именования и закрепляла их в своеобразных словарях. Вероятно, наиболее распространены были правила MIL STD 8320.1, разработанные Министерством обороны США, но вне федерального правительства популярными они так и не стали. Разработка фирменных стандартов, безусловно, представляла собой шаг вперед по сравнению с прежней бессистемностью, но в каждой фирме каноны чем-то отличались. В одних действительно создавались формальные правила назначения имен, в других за элементом данных просто закреплялось первое присвоенное ему имя.
Теперь у нас есть стандарты ISO-11179, которые распространяются все шире, стали обязательными для некоторых правительственных заказов и включаются в продукты для работы с хранилищами данных. В этот стандарт встроены инструменты и хранилища стандартизованных схем кодирования. Одним словом, будущее принадлежит ISO-11179 и XML как стандартному формату обмена данными.
Следите за длиной имен
Обоснование
В стандарте SQL-92 длина идентификатора ограничена 18 символами, как это было в старых стандартах Кобола. В современных реализациях SQL допускаются более длинные имена, но на самом деле вряд ли есть что-то, что нельзя выразить 18 символами. Максимальные длины имен наиболее важных объектов схемы SQL в стандартах ISO и некоторых популярных SQL-продуктах приводятся в табл. 1.1.
Табл. 1.1. Длины идентификаторов
SQL-92 | SQL-99 | IBM | MS SQL | Oracle | |
Столбец | |||||
Ограничение | |||||
Таблица |
Числа в таблице выражены в байтах или символах. Максимальная длина в символах может быть меньше максимальной длины в байтах, если вы используете многобайтовый набор символов.
Не увлекайтесь сверхдлинными именами. Людям предстоит их читать, набирать и распечатывать. Им также придется разбираться в их смысле, искать в словаре данных и т.п. Наконец, имена могут использоваться в хост-программах, у которых будут собственные ограничения на их длину.
Но и в другую крайность ударяться тоже не надо. Во времена, когда длина столбца была ограничена 18 байтами, в Bachman — старом средстве разработки баз данных DB2 — иногда логическое имя атрибута преобразовывалось в физическое имя столбца путем удаления из него всех гласных. Вряд ли можно назвать этот подход удачным. В таких “конденсированных” именах можно разобраться только после многодневного исследования.
Исключения
Исключения будут встречаться лишь от случая к случаю, вероятно, в результате столкновения со старыми системами, в которых на имена накладываются другие ограничения.
Табл. 1.2. Символы, допустимые в именах
Стандартный SQL | IBM | Oracle | Microsoft | |
Первый символ | Буква | Буква, $ # @ | Буква | Буква, # @ |
Последующие Символы | Буква, цифра, _ | Буква, цифра, $ # @ _ | Буква, цифра,$ * _ | Буква, цифра,* @ |
Различие верхнего и нижнего регистра | Нет | Нет | Нет | По желанию |
Название | Обычный идентификатор | Идентификатор без кавычек | Регулярный идентификатор |
Как правило, первым символом имени должна быть буква, а остальные символы могут быть буквами, цифрами и символом подчеркивания “_”. В различных СУБД допускается применение также символов $, # или @, но ни в одной СУБД не допускается применение всех трех сразу. Вообще, нет ни одного спецсимвола, который можно было бы спокойно использовать в любом продукте. В ПО Microsoft, например, имена, начинающиеся символами @ или #, имеют особое значение. В Oracle нельзя использовать спецсимволы в именах некоторых объектов.
Да и с буквами все ли ясно? В оригинальном SQL разрешалось использовать только латинские буквы верхнего регистра, что означает 26 вариантов. В наши дни репертуар несколько расширился, но не злоупотребляйте буквами, не входящими в набор символов Latin-1, и вот почему.
1. В продуктах IBM буквы распознаются не всегда корректно.Буквой считается любой многобайтовый символ за исключением пробела. Регистр символа система не определяет.
2. В продуктах IBM и Oracle используется набор символов из БД.При миграции могут возникнуть проблемы с экзотическими буквами. Продукты Microsoft работают с символами Unicode и с этой проблемой не сталкиваются.
В стандарте SQL-92 не разрешается заканчивать идентификатор символом подчеркивания. Не стоит также вставлять в имя несколько подчеркиваний подряд. При современном лазерном качестве печати пересчитать их будет сложновато.
Исключения
Нет.
Табл. 1.3. Символы, допустимые в идентификаторах с ограничителями
Стандартный SQL | IBM | Oracle | Microsoft | |
Ограничители | "" | "" | "" | "" или [ ] |
Первый символ | Любой | Любой | Любой | Любой |
Последующие символы | Любой | Любой | Любой | Любой |
Различие верхнего и нижнего регистра | Да | Да | Да | По желанию |
Название | Идентификатор с ограничителями | Идентификатор с ограничителями | Идентификатор в кавычках | Идентификатор с ограничителями |
Если правила использования символов в именах кажутся вам слишком жесткими, вы вольны обойти их, поместив идентификатор в двойные кавычки. В результате получится так называемый идентификатор с ограничителями (или идентификатор в кавычках, в терминологии Oracle). Идентификатор с ограничителями может начинаться с любого символа и вообще содержать любой символ. Конечно, возникает неясность с использованием внутри идентификатора самого символа ". Стандартный способ — записать его дважды (“Работ""ники”), но в документации он явно описан не всегда.
Поддержка имен с ограничителями практически универсальна, с двумя важными исключениями: 1) продукты IBM допускают использование только букв и цифр для меток и имен переменных в хранимых процедурах; 2) в продуктах Microsoft не разрешается использовать идентификаторы в кавычках при сброшенном флаге QUOTED_IDENTIFIER. Первое исключение связано, вероятно, с тем, что в продуктах IBM процедуры SQL перед компиляцией “переводятся” на другой компьютерный язык.
Рассмотрим в качестве примера создание таблицы с делимитированным идентификатором в качестве имени:
CREATE TABLE "t" ("columni" INTEGER NOT NULL);
Теперь обратимся к таблице так, словно ее имя является обычным идентификатором:
SELECT columni FROM t;
Сработает? Согласно стандарту SQL, не должно, но может сработать в продукте Microsoft. Причины обсуждаются в разделе “Разработайте строгие правила использования прописных букв”.
Идентификаторы в кавычках не особенно хорошо стыкуются с хост-языками, особенно когда в идентификаторе имеются пробелы или спецсимволы. Вот, например, вполне корректное выражение для вставки данных:
INSERT INTO Table ([field with space]) VALUES (value);
Объект ADO сгенерирует следующий код:
INSERT INTO Table (field with space) VALUES (value);
что является синтаксической ошибкой.
Исключения
Иногда нужно поделиться результатом с кем-то, кто не может прочитать или понять имена столбцов с использованием символов из набора Latin-1. В этом случае для форматирования выводимых данных можно применить псевдонимы в кавычках. Мне приходилось делать так для поляков и китайцев.
Я также применял имена в кавычках в документации, чтобы они безошибочно воспринимались как имена объектов схемы, а не как обычные слова в предложениях.
Обычная причина этой ошибки в том, что программист путает имя элемента данных с отображаемым заголовком. В традиционных процедурных языках файл с данными и программа находятся на одном уровне. В SQL база данных полностью отделена от интерфейса, в котором эти данные отображаются.
ISO-11179 для SQL
Обоснование
Формальные стандарты хороши, но слишком общи. Удобно превратить их в набор правил, написанных на языке, понятном разработчику SQL Некоторые из данных здесь формулировок являются результатом консенсуса экспертов и взяты из групп новостей и частной переписки.
Согласно правилам стандарта ISO-11179-4 скалярный элемент данных должен удовлетворять следующим требованиям.
1. Он уникален (в пределах своего словаря данных).
2. Он назван с использованием единственного числа.
3. В имени поясняется, чем является элемент, а не чем он не является.
4. Имя читается, как описательная фраза.
5. Имя содержит только общепринятые сокращения.
6. Имя не содержит вложенных определений других элементов данных или понятий.
7. Таблицы, наборы и другие сборные элементы именуются обобщающими понятиями во множественном числе.
8. В имени процедуры содержится глагол.
9. В имя копии (псевдоним) таблицы включено имя базовой таблицы и причина создания копии.
В теории все это звучит прекрасно, но в реальном мире на имена накладываются дополнительные практические ограничения, например ограничение длины или допустимые символы. Другая проблема состоит в том, что у элемента данных в зависимости от контекста его использования могут быть разные имена. В отчете он назван так, в файле электронного обмена данными (electronic data interchange, EDI) по-другому, причем оба имени могут отличаться от имени в БД. Но в пределах одной БД использовать разные имена для одного элемента не стоит, да и в разных БД одного предприятия этим не стоит злоупотреблять. К сожалению, найти подобные разногласия без хорошего словаря очень трудно. Словарь данных должен включать внешние имена и их контекст.
Исключения
Над всеми нами довлеет проклятие старых БД, старых файловых систем и прочих традиций. Если у элемента имеется устоявшееся и понятное имя, его можно использовать даже вопреки стандарту. Например, для столбца с почтовым индексом формально правильным будет имя “us_postal_code”, но вместо него можно поставить более привычное “zip_code” или даже просто “zip”.
Уровни абстрагирования
Разработка имени начинается на концептуальном уровне. Класс объекта представляет идею, абстракцию или предмет реального мира, например дерево или страну. Свойство, например, высота или идентификатор, описывает все объекты класса. Это позволяет создавать словосочетания типа “высота дерева” или “идентификатор страны”, комбинируя класс и свойство.
Этот уровень — логический. Полное логическое имя элемента данных должно включать способ представления значений из его области определения (набора допустимых значений). Так мы получаем в качестве возможных элементов данных “меру высоты дерева”, “имя идентификатора страны” и “код идентификатора страны”.
Между именем идентификатора и кодом идентификатора имеется различие, правда, столь тонкое, что мы можем не захотеть его моделировать. В этом случае необходимо правило, в соответствии с которым название свойства исключается из имени элемента данных. При этом в структуре элемента свойство сохранится, лишь перестав быть частью его имени.
Некоторые логические элементы данных могут считаться общепринятыми, если они четко определены и применяются многими организациями. Например, названия и коды стран описаны в стандарте ISO-3166 “Codes for the Representation of Names of Countries”, который можно использовать в качестве справочника.
Заметьте, что, по правилам стандарта ISO-11179, это самый высокий уровень, на котором появляются истинные элементы данных: у них есть класс, свойство и способ представления.
Далее идет прикладной уровень. Он обычно реализуется при помощи неких конкретных уточнений, соответствующих поставленной задаче: выделения подмножества из области значений данных, добавления ограничений, гарантирующих, что мы будем иметь дело лишь с допустимыми значениями. Например, мы используем коды стран ISO-3166, но реально работаем только с европейскими государствами. Это означает, что нас интересует подмножество стандарта, которое временным изменениям практически не подвержено. С другой стороны, набор стран, в которых в текущем году выпало больше всего осадков, может на протяжении года меняться неоднократно.
Эти уточнения включаются в имя посредством добавления к логическому имени конкретного квалификатора. Например, если нужно составить список стран, с которыми у некой организации есть торговые соглашения, элемент данных запроса можно назвать “trading_partner_country_name” (название страны-торгового партнера), подчеркнув тем самым его роль. Область значений будет представлять собой подмножество стран из стандарта ISO-3166.
Ниже всего располагается физический уровень. На нем находятся имена, которые фигурируют в заголовках столбцов таблицы, описаниях файлов, разметке EDI-файлов и т.д. Эти имена могут быть, с одной стороны, сокращенными из-за различных ограничений на длину или набор символов, с другой стороны, могут содержать информацию о формате и источнике.
В реестре все имена элементов данных и компоненты имен всегда будут указываться в паре со своим контекстом, чтобы мы легко могли установить их источник и назначение. Цель заключается в возможности проследить за каждым элементом данных от его создания до любого применения, под каким бы именем он ни фигурировал.
Избегайте невнятных имен
Обоснование
В этом есть какая-то скрытая непристойность, а я не выношу скрытости
Гручо Маркс
Крайний вид невнятности — настолько общее имя, что оно не говорит вообще ничего, например “Дата”, “Количество”... Представьте себе столбец “Дата”. Сразу возникает вопрос: дата чего? Приема на работу? Рождения? Встречи? Увольнения? Смерти?
Другая крайность — строка квалификаторов, противоречащих друг другу. Вот типичный для новичка пример: “type_code_id”. Если это идентификатор (id), то он должен быть уникальным для каждой обозначаемой им сущности, как идентификационный номер автомобиля (vehicle identification number, VIN). Если это код (code), то он берется из надежного источника и не должен быть уникальным. Если это тип (type), какой систематике он принадлежит? Чего уж мелочиться — можно и еще один квалификатор добавить: “type _code_id_value”!
А ведь гораздо понятнее было бы написать просто “customer_type”...
Исключения
Нет.
Некорректные имена элементов данных имеют своим источником невежество и объектно-ориентированное программирование (ООП). В частности, объектно-ориентированные программисты обязательно добавляют суффикс “_id” к любому первичному ключу любой таблицы, не понимая, что SQL — сильно типизированный язык, и в нем сущности в ходе выполнения программы своего типа не меняют. Иногда имена бывают просто абсурдными. Взгляните на таблицу цветов:
CREATE TABLE TblColors
(color_value_id INTEGER NOT NULL PRIMARY KEY,
color_value VARCHAR(50) NOT NULL);
Что означает суффикс “_value_id”? Сразу ясно, что создатель не сильно задумывался над именем. Теперь представьте, что мы решили использовать в БД цветовую систему Pantone: у нас есть надежный источник и точное описание, потому что мы все продумали! Выражение будет выглядеть так:
CREATE TABLE Colors
(pantone_nbr INTEGER NOT NULL PRIMARY KEY,
color_description VARCHAR(50) NOT NULL);
Типографика кода
При работе с программами ваши глаза и мозг действуют не так, как действуют они при чтении, счете, работе с картой или разглядывании картинок. Кроме того, имеется масса индивидуальных различий между людьми.
Некоторым нравятся текстовые редакторы, в которых элементы синтаксиса языка программирования отображаются разными цветами. Другие считают это многоцветье поводом для головной боли и предпочитают простой черно-белый текст. Конечно, невозможно было бы, например, читать газету, в которой существительные напечатаны красной краской, глаголы — зеленой и т.п. С другой стороны, разбираться с черно-белой картой значительно сложнее, чем с цветной. Почему? Это связано с различиями в восприятии цвета.
Есть такой тест на предмет выявления повреждений мозга. Проверяющий показывает пациенту карточки, на которых слова напечатаны различными цветами (например, слово “красный”, напечатанное зеленой краской), спрашивает его о смысле слов и записывает время, которое уходит на получение ответа. Время это на протяжении жизни человека само по себе меняется мало, поэтому зафиксированное изменение является симптомом физической или химической перемены. Теперь прочтите следующее:
Война
в Крыму.
Все в
в дыму.
При первом прочтении практически никто не замечает, что один из предлогов “в” напечатан дважды. Это — особенность того, как мы просматриваем блоки слов в вертикальном направлении. Она важна при работе с кодом: при чтении программ глаз совершает множество вертикальных движений, которых нет при чтении простого текста.
Несколько лет назад по Интернету гулял следующий текст:
“Солгсано унёчым из Кмерибжда, внажо, чотбы на сове мтесо в своле пдалопаи паврея и псоелндяя бквуы. Дуигре бувкы мугот сяттоь в бе-сопдярке, но ткест всё рнаво бдеут чтатьися без порлбем. Это сявпазо с тем, что мзог човеекла чтаеит не оыетдльне бвкуы, а цыеле совла”.
Я не уверен, что этот фрагмент действительно имеет своим источником Кембриджский университет, но в качестве иллюстрации он нам подходит. Поскольку компилятор гарантирует отсутствие в коде опечаток, читатель знает, что ему ожидать от следующего слова, с гораздо большей уверенностью, чем при чтении обычного текста. Тут уж слова не просто воспринимаются, как целое, они еще и ожидаемы. Скажем, увидев в программе на Паскале или другом языке из семейства Алгола ключевое слово “IF”, я ожидаю, что выражение закончится ключевым словом “THEN”.
Давайте поговорим о некоторых основных правилах набора программ, которые опираются на то, как люди читают код.
Пробелы
Разделяйте элементы языка пробелами, не давайте им сливаться в непрерывный поток. Пишите, например, “foobar = 21”, а не “foobar=21”, как это часто делается. Многие современные программисты еще застали времена перфокарт, когда длина строки была ограничена и на пробелах приходилось экономить. Программу на языке управления заданиями (job control language, JCL) для семейства IBM/360, скажем, можно написать, вообще не используя пробелы. Современные языки программирования не связаны столь жесткими ограничениями, и мы наконец можем писать программы так, словно люди важнее компьютеров.
Обоснование
В XXI веке пользоваться пробелами можно совершенно свободно. Не забывайте, что перед вами не крохотная перфокарта, а огромный экран.
Исключения
Иногда строки, действительно, получаются уж слишком длинными. Но с компактными языками наподобие SQL эта проблема практически не возникает.
Отступы
Для отступов в языках программирования 3GL лучше всего использовать не менее трех пробелов. Один пробел слишком короток, чтобы разделять что-нибудь помимо слов. Два пробела — уже лучше, но чтобы у читателя создавалось четкое впечатление нового абзаца, наберите их три.
Впрочем, отступы с использованием большого числа пробелов тоже усложняют чтение кода, так как глазу приходится совершать слишком большие перемещения. Использование восьмисимвольного табулятора вообще является пережитком прошлого. В первых телетайпных аппаратах смещение табулятором на восемь символов имело чисто механические причины, но было автоматически перенесено и на электронные терминалы.
Обоснование
В языке управления данными (data manipulation language, DML) нам необходим баланс между отступами и коридорами. Обратите внимание, что каждый подзапрос внутри себя связан коридором, а различные подзапросы выделены отступами:
SELECT DISTINCT pilot
FROM PilotSkills AS PS1
WHERE NOT EXISTS (SELECT *
FROM Hangar
WHERE NOT EXISTS (SELECT *
FROM PilotSkills AS PS2
WHERE PS1.pilot = PS2.pilot
AND PS2.plane = Hangar.plane));
Исключения
Подзапрос всегда заключается в скобки, так что можно считать приоритетным выравнивание парных скобок:
SELECT DISTINCT pilot
FROM PilotSkills AS PS1
WHERE NOT EXISTS (SELECT *
FROM Hangar
WHERE NOT EXISTS (SELECT *
FROM PilotSkills AS PS2
WHERE PS1.pilot = PS2.pilot
AND PS2.plane = Hangar.plane
)
);
Преимущество заключается в том, что вы всегда легко найдете границы подзапроса, правда, за счет появления строк, содержащих один или два символа.
Если в списке оператора SELECT или еще где-нибудь имеется набор взаимосвязанных столбцов, используйте отступы при разбиении этого списка на несколько строк:
SELECT C1.cust.name,
C1.street_address,
C1.city, С1.state,
C1.zip,
P1.payment_1,
P1.payment_2,
P1.payment_3,
P1.payment_4,
P1.payment_5,
P1.payment_6,
P1.payment_7,
P1.payment_8,
P1.payment_9,
payment_10,
FROM Customers AS С1,
Payments AS P1
WHERE C1.cust_id = P1.cust_id;
Здесь все столбцы, относящиеся к самому клиенту, перечислены в первой строке, а 10 платежей разбиты на три строки, выделенные отступами.
Давайте имена ограничениям
Обоснование
Имя ограничения отображается в сообщении об ошибке, когда это ограничение нарушено. С помощью имен ограничений вы сможете создавать понятные сообщения, что существенно облегчает диагностику ошибок.
Синтаксис прост: “CONSTRAINT <имя>”. В качестве имени нужно использовать понятное описание ограничения, например:
CREATE TABLE Prizes (... award_points INTEGER DEFAULT 0 NOT NULL
CONSTRAINT award_point_range
CHECK (award_points BETWEEN 0 AND 100),
... );
Если вы не присвоите ограничению имя, SQL сгенерирует его самостоятельно. Оно будет длинным, нечитаемым и лишенным какой бы то ни было информации о сути проблемы.
Исключения
Имена можно не присваивать ограничениям PRIMARY KEY, UNIQUE и FOREIGN KEY, поскольку при их нарушении большинство SQL-продуктов выдает понятные сообщения об ошибке. Исключение составляет Oracle.
Без имен ограничений можно обойтись на этапе разработки. Помните, однако, что имена ограничений являются глобальными, а не локальными. В противном случае возможны были бы проблемы с выражением CREATE ASSERTION.
Табл. 3.1. Типы ключей
Естественный ключ | Искусственный ключ | Явный физический указатель | Системный суррогатный ключ | |
Строится по реальной модели данных | Да | Нет | Нет | Нет |
Проверяем по реальной модели | Да | Нет, исходит из надежного источника | Нет | Нет |
Проверяем сам по себе | Да | Да, например, по синтаксису, по контрольному разряду | Нет | Нет |
Переносим на другую платформу | Да | Да | Нет | Нет |
Доступен пользователю | Да | Да | Да | Нет, может быть изменен системой |
1. Естественный ключпредставляет собой набор атрибутов из таблицы и действует как уникальный идентификатор. Он виден пользователю.Его можно проверить на корректность как по реальной модели данных,так и сам по себе. Пример, универсальный код продукта UPC можно прочитать на упаковке, проверить сканером, сравнить с данными на Web-узле производителя.
2. Искусственный ключпредставляет собой дополнительный атрибут, специально введенный в таблицу для использования в качестве ключа. Он виден пользователю, не связан напрямую с реальной моделью данных, но может быть проверен сам по себе — по синтаксису, по контрольному разряду. Пример: свободные коды из схемы UPC, которые пользователь может присвоить своему продукту. Корректность кодов можно проверять только в пределах вашей организации. Если вы занимаетесь разработкой ключа самостоятельно, помните, что эго дело не из легких. Подробнее об этом — в главе 5.
3. Явный физический указательне основан на модели данных и доступен пользователю. Предсказать или проверить его значение нельзя. Система вычисляет его, основываясь на физическом хранении данных. Пример: поля IDENTITY в семействе T-SQL, другие нестандартные нереляционные средства автонумерации, указатели, основанные на номерах цилиндра и дорожки жесткого диска в Oracle. Технически, это вообще не ключи, так как к логической модели данных они не имеют никакого отношения. Удобны для ленивых, не желающих думать программистов-“чайников”. Наихудший способ программирования на SQL
4. Системный суррогатный ключгенерируется системой для замещения реального ключа на основе атрибутов из таблицы; пользователю недоступен. Пример: алгоритмы хэширования Teradata. Определяющее значение имеет тот факт, что пользователь ни при каких обстоятельствах не видит суррогатный ключ, не может использовать его в командах DELETE и UPDATE или создать командой INSERT. Если бы он мог это сделать, то немедленно повредил бы целостность данных, нарушив соответствие между реальными и суррогатными ключами. Суррогатные ключи поддерживаются системой.
Обратите внимание, что суррогатные ключи иногда путают с физическими указателями; на самом же деле они концептуально различны.
Файлы — не таблицы
Если попытаться выразить эту мысль максимально просто, речь идет о различии между физическим и логическим представлением данных, хотя на самом деле все сложнее. Файловая система — это просто собрание файлов, далеко не все из которых реально нужны. База данных — это единый блок информации, в котором целое предприятие представлено в виде таблиц, ограничений и пр.
Файлы независимы друг от друга, а таблицы базы данных взаимосвязаны. Вы открываете БД целиком, а не отдельные таблицы в ней, тогда как файлы открываются по отдельности. Действие в отношении одного файла не затрагивает другие файлы, таблицы же взаимодействуют друг с другом посредством DRI, процедур-триггеров и т.д. <