Стандарты форматирования SQL - PullRequest
53 голосов
/ 06 февраля 2009

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

Мне интересно узнать, что другие люди используют для стандартов форматирования SQL. В отличие от большинства других сред программирования, я не нашел для них консенсуса в Интернете.

Чтобы охватить основные типы запросов:

select
    ST.ColumnName1,
    JT.ColumnName2,
    SJT.ColumnName3
from 
    SourceTable ST
inner join JoinTable JT
    on JT.SourceTableID = ST.SourceTableID
inner join SecondJoinTable SJT
    on ST.SourceTableID = SJT.SourceTableID
    and JT.Column3 = SJT.Column4
where
    ST.SourceTableID = X
    and JT.ColumnName3 = Y

Были некоторые разногласия по поводу перевода строки после select, from и where. Цель строки выбора - разрешить другим операторам, таким как "top X", не изменять макет. Исходя из этого, простое поддержание согласованного перевода строки после ключевых элементов запроса, казалось, привело к хорошему уровню читабельности.

Сброс перевода строки после from и where будет понятной ревизией. Однако в таких запросах, как update ниже, мы видим, что перевод строки после where дает нам хорошее выравнивание столбцов. Аналогичным образом, перевод строки после group by или order by делает наши макеты столбцов четкими и легкими для чтения.

update
    TargetTable
set
    ColumnName1 = @value,
    ColumnName2 = @value2
where
    Condition1 = @test

Наконец, insert:

insert into TargetTable (
    ColumnName1,
    ColumnName2,
    ColumnName3
) values (
    @value1,
    @value2,
    @value3
)

По большей части они не сильно отличаются от того, как MS SQL Server Managements Studio / анализатор запросов записывает SQL, однако они do отличаются.

Я с нетерпением жду возможности увидеть консенсус в сообществе Stack Overflow по этой теме. Я постоянно удивляюсь, как много разработчиков могут придерживаться стандартного форматирования для других языков и внезапно становятся настолько случайными при обращении к SQL.

Ответы [ 29 ]

2 голосов
/ 06 февраля 2009

Я использую формат, аналогичный вашему, за исключением того, что я помещаю ключевое слово ON в ту же строку, что и соединение, и помещаю операторы AND и OR в конце строк, чтобы все мои соединения / выбор критерии выстраиваются красиво.

Хотя мой стиль похож на стиль Джона Сэнсома, я не согласен с тем, чтобы включить критерии объединения в предложение WHERE. Я думаю, что это должно быть с объединенной таблицей, чтобы она была организована и ее легко было найти.

Я также стараюсь ставить круглые скобки в новые строки, выравнивая их по строке над ней, а затем вставляя отступ в следующую строку, хотя для коротких операторов я могу просто оставить скобки в исходной строке. Например:

SELECT
     my_column
FROM
     My_Table
WHERE
     my_id IN
     (
          SELECT
               my_id
          FROM
               Some_Other_Table
          WHERE
               some_other_column IN (1, 4, 7)
     )

Для операторов CASE я даю новую строку и отступ для каждого WHEN и ELSE и выравниваю END обратно * CASE:

CASE
     WHEN my_column = 1 THEN 'one'
     WHEN my_column = 2 THEN 'two'
     WHEN my_column = 3 THEN 'three'
     WHEN my_column = 4 THEN 'four'
     ELSE 'who knows'
END
2 голосов
/ 19 декабря 2018

Это мое личное руководство по стилю SQL . Он основан на нескольких других, но имеет несколько основных стилистических особенностей - строчные ключевые слова, отсутствие посторонних ключевых слов (например, outer, inner, asc) и «река».

Пример SQL выглядит следующим образом:

-- basic select example
select p.Name as ProductName
     , p.ProductNumber
     , pm.Name as ProductModelName
     , p.Color
     , p.ListPrice
  from Production.Product as p
  join Production.ProductModel as pm
    on p.ProductModelID = pm.ProductModelID
 where p.Color in ('Blue', 'Red')
   and p.ListPrice < 800.00
   and pm.Name like '%frame%'
 order by p.Name

-- basic insert example
insert into Sales.Currency (
    CurrencyCode
    ,Name
    ,ModifiedDate
)
values (
    'XBT'
    ,'Bitcoin'
    ,getutcdate()
)

-- basic update example
update p
   set p.ListPrice = p.ListPrice * 1.05
     , p.ModifiedDate = getutcdate()
  from Production.Product p
 where p.SellEndDate is null
   and p.SellStartDate is not null

-- basic delete example
delete cc
  from Sales.CreditCard cc
 where cc.ExpYear < '2003'
   and cc.ModifiedDate < dateadd(year, -1, getutcdate())
2 голосов
/ 12 апреля 2016

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

Select column1
   ,column2
   ,column3
   ,column4
   ,Column5 ...ect

В противоположность:

Select column1,
   column2,
   column3, ect...

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

1 голос
/ 06 февраля 2009

Если я делаю изменения в уже написанном T-SQL, то я следую уже используемому соглашению (если оно есть).

Если я пишу с нуля или нет соглашения, то я склонен следовать вашему соглашению, данному в вопросе, за исключением того, что я предпочитаю использовать заглавные буквы для ключевых слов (просто личное предпочтение для удобства чтения).

Я думаю, что при форматировании SQL, как и при других соглашениях о формате кода, важно иметь соглашение, а не то, чем оно является (конечно, в рамках здравого смысла!)

1 голос
/ 21 марта 2009

Я использую Red Gate SQL ReFactor в SSMS, но еще одним инструментом, который выполняет переформатирование (и заменяет SSMS), является Редактор SQL Apex . Если вы хотите опубликовать код в режиме онлайн, есть Префиксатор SQL Simple-Talk .

1 голос
/ 13 ноября 2014

От всей души согласен с вашими усилиями по стандартизации форматирования SQL в рамках вашего проекта и в целом.

Я также очень согласен с вашим выбором форматирования. Я придумал почти то же самое, за исключением того, что я делаю отступ для операторов «join», а с ними для «on» еще один отступ.

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

Очень похоже на то, что вы используете небольшие отступы (4). Я иду с (3).

Я использую термины «внутренний» и «внешний», так как в этом нет необходимости.

Вот как отформатировал бы ваш оператор выбора:

select
   st.ColumnName1,
   jt.ColumnName2,
   sjt.ColumnName3
from 
   SourceTable st
   join JoinTable jt on jt.SourceTableID = st.SourceTableID
   join SecondJoinTable sjt on
      st.SourceTableID = sjt.SourceTableID and
      jt.Column3 = sjt.Column4
where
   st.SourceTableID = X
   and jt.ColumnName3 = Y
;

Спасибо за обсуждение.

1 голос
/ 24 октября 2018

Мой ответ будет аналогичен принятому ответу John Sansom answered Feb 6 '09 at 11:05. Тем не менее, я продемонстрирую некоторые варианты форматирования с использованием плагина SQLInForm в NOTEPAD ++ , в отличие от его ответа с помощью SQL Prompt от Red Gate.

Плагин SQLInForm имеет 5 различных профилей, которые вы можете настроить. В профиле доступно множество настроек как в бесплатной, так и в платной версиях. Полный список приведен ниже, и вы можете увидеть их plugin-help-general-options онлайн.

Вместо того, чтобы рассуждать о моих предпочтениях, я подумал, что было бы полезно представить доступные параметры SQLInForm. Некоторые из моих предпочтений также отмечены ниже. В конце моего поста приведен отформатированный код SQL, использованный в оригинальном посте (original VS format1 VS format2).

Прочтите здесь другие ответы ... Кажется, я в меньшинстве в паре вещей. Мне нравится leading commas ( Короткое видео здесь ) - IMO, намного легче читать, когда выбирается новое поле. А также мне нравится мой Column1 with linebreak, а не рядом с SELECT.


Вот краткий обзор с некоторыми из моих замечаний по предпочтениям, с учетом оператора SELECT. Я бы добавил скриншоты всех 13 разделов; Но это много скриншотов, и я просто рекомендую вам бесплатную версию - сделайте несколько скриншотов и протестируйте элементы управления форматом. Я скоро опробую Pro Edition; Но, основываясь на опциях, похоже, что это будет действительно полезно и всего за 20 долларов.

SQLInForm Notepadd ++: параметры и предпочтения

1. Общее (бесплатно)

БД: любой SQL, DB2 / UDB, Oracle, MSAccess, SQL Server, Sybase, MYSQL, PostgreSQL, Informix, Teradata, Netezza SQL

[Умный отступ] = ЛОЖЬ

2. Цвета (бесплатно)

3. Ключевые слова (PRO)

[Upper / LowerCase]> Ключевые слова

4. Переводы строк> Списки (бесплатно)

[До запятой] = ИСТИНА 5

[Переместить запятую на 2 столбца влево] = ЛОЖЬ

5. Разрывы строк> Выбрать (PRO)

[JOIN> После JOIN] = FALSE

[JOIN> До ВКЛ.] = ЛОЖЬ

(без изменений) -> [JOIN> Отступ JOIN]; [JOIN> После ВКЛ]

6. Разрывы строк> Ins / Upd / Del (PRO)

7. Разрывы строк> Условия (PRO)

CASE Statement -> [WHEN], [THEN], [ELSE]… конечно, хотят играть с этими настройками и выберите хороший

8. Выравнивание (PRO)

(без изменений) -> [JOIN> Отступ JOIN]; [JOIN> После ВКЛ]

9. Пробелы (PRO)

(изменить?) Пустые строки [Удалить все] = ИСТИНА; [Сохранить все]; [Keep One]

10. Комментарии (PRO)

(изменить?) Строка и блок -> [Строка до / после блока Комментарии] = TRUE; [Изменить комментарии строки в блок]; [Блок в линию]

11. Сохраненный Proc (PRO)

12. Продвинутый (PRO)

(может быть полезно) Извлечь SQL из программного кода -> [ExtractSQL]

13. Лицензия


Код SQL

Исходный формат запроса.

select
    ST.ColumnName1,
    JT.ColumnName2,
    SJT.ColumnName3
from 
    SourceTable ST
inner join JoinTable JT
    on JT.SourceTableID = ST.SourceTableID
inner join SecondJoinTable SJT
    on ST.SourceTableID = SJT.SourceTableID
    and JT.Column3 = SJT.Column4
where
    ST.SourceTableID = X
    and JT.ColumnName3 = Y

ПРЕДПОЧТИТЕЛЬНЫЙ ФОРМАТ КОНВЕРСИИ (опция № 1: ПРИСОЕДИНИТЬСЯ без разрыва строки)

SELECT
    ST.ColumnName1
    , JT.ColumnName2
    , SJT.ColumnName3
FROM
    SourceTable ST
    inner join JoinTable JT 
        on JT.SourceTableID = ST.SourceTableID
    inner join SecondJoinTable SJT
        on ST.SourceTableID = SJT.SourceTableID
        and JT.Column3      = SJT.Column4
WHERE
    ST.SourceTableID   = X
    and JT.ColumnName3 = Y

ПРЕДПОЧТИТЕЛЬНЫЙ ФОРМАТ КОНВЕРСИИ (опция № 2: СОЕДИНЕНИЕ с разрывом строки)

SELECT  
    ST.ColumnName1
    , JT.ColumnName2
    , SJT.ColumnName3
FROM
    SourceTable ST
    inner join
        JoinTable JT
        on JT.SourceTableID = ST.SourceTableID
    inner join
        SecondJoinTable SJT
        on ST.SourceTableID = SJT.SourceTableID
        and JT.Column3      = SJT.Column4
WHERE
    ST.SourceTableID   = X
    and JT.ColumnName3 = Y

Надеюсь, это поможет.

1 голос
/ 17 мая 2014

Мне нравится:

SELECT ST.ColumnName1, JT.ColumnName2, SJT.ColumnName3 --leave all selected columns on the same line
FROM 
    SourceTable ST
INNER JOIN JoinTable JT ON JT.SourceTableID = ST.SourceTableID
INNER JOIN SecondJoinTable SJT --only splitting lines when more than 1 condition
    ON ST.SourceTableID = SJT.SourceTableID
    AND JT.Column3 = SJT.Column4
WHERE
    ST.SourceTableID = X
    and JT.ColumnName3 = Y

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

1 голос
/ 08 октября 2016

Никто еще не сделал общие табличные выражения (CTE). Ниже включены его вместе с некоторыми другими стилями, которые я использую:

declare @tableVariable table (
    colA1 int,
    colA2 int,
    colB1 int,
    colB2 nvarchar(255),
    colB3 nvarchar(255),
    colB4 int,
    colB5 bit,
    computed int
);

with

    getSomeData as (

        select        st.colA1, sot.colA2
        from          someTable st
        inner join    someOtherTable sot on st.key = sot.key

    ),

    getSomeOtherData as (

        select        colB1, 
                      colB2, 
                      colB3,
                      colB4,
                      colB5,
                      computed =    case 
                                    when colB5 = 1 then 'here'
                                    when colB5 = 2 then 'there'
                                    end
        from          aThirdTable tt
        inner hash 
         join         aFourthTable ft
                      on tt.key1 = ft.key2
                      and tt.key2 = ft.key2
                      and tt.key3 = ft.key3

    )

    insert      @tableVariable (
                    colA1, colA2, colA2, 
                    colB1, colB2, colB3, colB4, colB5, 
                    computed 
                )
    select      colA1, colA2, 
                colB1, colB2, colB3, colB4, colB5, 
                computed 
    from        getSomeData data1
    join        getSomeOtherData data2

Несколько моментов в формате CTE:

  • В моих CTE "с" находится на отдельной строке, а все остальное в cte имеет отступ.
  • Мои имена CTE длинные и описательные. CTE могут получить сложные, а описательные имена очень полезны.
  • По какой-то причине я предпочитаю глаголы для имен CTE. Делает это кажется более живым.
  • Подобный стиль с круглыми скобками, как у Javascript с фигурными скобками. Это также, как я делаю скобки в C #.

Это имитирует:

func getSomeData() {

    select        st.colA1, sot.colA2
    from          someTable st
    inner join    someOtherTable sot on st.key = sot.key

}

Несколько моментов, кроме формата CTE:

  • Две вкладки после «выбора» и других ключевых слов. Это оставляет достаточно места для «внутреннего соединения», «группировки по» и т. Д. Вы можете увидеть один пример выше, где это не так. Но "внутреннее соединение хешей" ДОЛЖНО выглядеть уродливо. Тем не менее, в этом пункте я, вероятно, буду экспериментировать с некоторыми из стилей, описанных выше, в будущем.
  • Ключевые слова в нижнем регистре. Их окраска с помощью IDE и их особый статус отступов выделяют их достаточно. Я резервирую заглавные буквы для других вещей, которые хочу подчеркнуть, основываясь на локальной (бизнес) логике.
  • Если столбцов мало, я помещаю их в одну строку (getSomeData). Если есть еще несколько, я вертикализирую их (getSomeOtherData). Если в одном блоке слишком много вертикализации, я помещаю несколько столбцов в одну и ту же строку, сгруппированную по локальной логике (последний сегмент вставки-выбора). Например, я бы поместил информацию школьного уровня в одну строку, ученический уровень в другую и т. Д.
  • Особенно при вертикализации я предпочитаю SQL Server "varname = colname + что-то синтаксис" вместо "colname + что-то как varname".
  • Удвойте последний пункт, если я имею дело с регистром дела.
  • Если определенная логика поддается «матричному» стилю, я буду иметь дело с последствиями ввода. Это похоже на то, что происходит с оператором case, где «когда» и «тогда» выровнены.

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

1 голос
/ 06 февраля 2009

Да, я вижу ценность выкладывания вашего sql строго определенным образом, но, безусловно, соглашение о присвоении имен и ваше намерение гораздо важнее. Вроде бы в 10 раз важнее.

Исходя из того, что мои домашние ненависти - это таблицы с префиксом tbl и хранимые процедуры с префиксом sp - мы знаем, что это таблицы и SP. Наименование объектов БД гораздо важнее, чем количество пробелов

Только мои $ 0,02

...