Подтвердить что ты не робот

Стандарты форматирования SQL

В моей последней работе мы работали над приложением, очень загруженным базой данных, и я разработал некоторые стандарты форматирования, чтобы мы все писали 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 или по 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, однако они различаются.

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

4b9b3361

Ответ 1

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

Единственный другой аспект, который важен для меня, заключается в том, что какой бы макет/стиль кодирования вы ни выбрали для своего магазина, убедитесь, что он последовательно используется всеми программистами.

Просто для справки, вот как я бы представил приведенный вами пример, только мои настройки макета. Особо следует отметить, что предложение ON находится в той же строке, что и join, в соединении указывается только первичное условие соединения (т.е. Совпадение ключей), а другие условия перемещаются в предложение where.

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
where
        ST.SourceTableID = X
    and JT.ColumnName3 = Y
    and JT.Column3 = SJT.Column4

Один совет, получите себе копию SQL Prompt от Red Gate. Вы можете настроить инструмент так, чтобы он использовал желаемые настройки макета, и тогда все кодировщики в вашем магазине смогут использовать его, чтобы гарантировать, что все пользователи применяют одинаковые стандарты кодирования.

Ответ 2

Поздний ответ, но, надеюсь, полезно.

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

Как разработчики мы иногда создаем что-то, что работает, а затем говорим: "Я отформатирую это позже", но позже это никогда не наступит.

Первоначально мы использовали SQL Prompt (это было здорово), но затем переключились на ApexSQL Refactor, потому что это бесплатный инструмент.

Ответ 3

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

SELECT  st.column_name_1, jt.column_name_2,
        sjt.column_name_3
FROM    source_table AS st
        INNER JOIN join_table AS jt USING (source_table_id)
        INNER JOIN second_join_table AS sjt ON st.source_table_id = sjt.source_table_id
                AND jt.column_3 = sjt.column_4
WHERE   st.source_table_id = X
AND     jt.column_name_3 = Y

Короче: 8-пространственный отступ, ключевые слова в шапках (хотя SO красит их лучше в нижнем регистре), без камелий (бессмысленно на Oracle) и обертывания строк при необходимости.

UPDATE:

UPDATE  target_table
SET     column_name_1 = @value,
        column_name_2 = @value2
WHERE   condition_1 = @test

И INSERT:

INSERT  INTO target_table (column_name_1, column_name_2,
                column_name_3)
VALUES  (@value1, @value2, @value3)

Теперь позвольте мне первыми признать, что этот стиль имеет проблемы. 8-пространственный отступ означает, что ORDER BY и GROUP BY либо смещают отступ, либо отделяют слово BY от себя. Также было бы более естественным отступать весь предикат предложения WHERE, но я обычно выравниваю следующие операторы AND и OR в левом поле. Отступы после завернутых линий INNER JOIN также несколько произвольны.

Но по какой-то причине мне все же легче читать, чем альтернативы.

Я закончил с одним из моих более сложных творений в последнее время, используя этот стиль форматирования. Почти все, что вы встретили в инструкции SELECT, появляется в этом. (Он также был изменен, чтобы скрыть свое происхождение, и я, возможно, ввел ошибки при этом.)

SELECT  term, student_id,
        CASE
            WHEN ((ft_credits > 0 AND credits >= ft_credits) OR (ft_hours_per_week > 3 AND hours_per_week >= ft_hours_per_week)) THEN 'F'
            ELSE 'P'
        END AS status
FROM    (
        SELECT  term, student_id,
                pm.credits AS ft_credits, pm.hours AS ft_hours_per_week,
                SUM(credits) AS credits, SUM(hours_per_week) AS hours_per_week
        FROM    (
                SELECT  e.term, e.student_id, NVL(o.credits, 0) credits,
                        CASE
                            WHEN NVL(o.weeks, 0) > 5 THEN (NVL(o.lect_hours, 0) + NVL(o.lab_hours, 0) + NVL(o.ext_hours, 0)) / NVL(o.weeks, 0)
                            ELSE 0
                        END AS hours_per_week
                FROM    enrollment AS e
                        INNER JOIN offering AS o USING (term, offering_id)
                        INNER JOIN program_enrollment AS pe ON e.student_id = pe.student_id AND e.term = pe.term AND e.offering_id = pe.offering_id
                WHERE   e.registration_code NOT IN ('A7', 'D0', 'WL')
                )
                INNER JOIN student_history AS sh USING (student_id)
                INNER JOIN program_major AS pm ON sh.major_code_1 = pm._major_code AND sh.division_code_1 = pm.division_code
        WHERE   sh.eff_term = (
                        SELECT  MAX(eff_term)
                        FROM    student_history AS shi
                        WHERE   sh.student_id = shi.student_id
                        AND     shi.eff_term <= term)
        GROUP   BY term, student_id, pm.credits, pm.hours
        )
ORDER   BY term, student_id

Эта мерзость вычисляет, является ли студент занятым полный или неполный рабочий день в определенный срок. Независимо от стиля, этот трудный для чтения.

Ответ 4

Ницца. Как программист Python, вот мои предпочтения:

Newlines после select, from и where только тогда, когда это необходимо для удобства чтения.

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

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

В конечном счете, это будет оценочный вызов, который будет сделан во время проверки кода.

Для insert я бы поставил круглые скобки по-другому:

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

Причина такого форматирования заключается в том, что если SQL использует отступ для блочной структуры (например, Python), скобки не понадобятся. Таким образом, если в любом случае используется отступ, то круглые скобки должны оказывать минимальное влияние на макет. Это достигается путем размещения их в конце строк.

Ответ 5

Я бы предложил следующий стиль, основанный на предположении Джона:

/*
<Query title>
<Describe the overall intent of the query>
<Development notes, or things to consider when using/interpreting the query>
*/
select
    ST.ColumnName1,
    JT.ColumnName2,
    SJT.ColumnName3
from 

    -- <Comment why this table is used, and why it first in the list of joins>
    SourceTable ST

    -- <Comment why this join is made, and why it an inner join>
    inner join JoinTable JT
        on ST.SourceTableID = JT.SourceTableID

    -- <Comment why this join is made, and why it an left join>
    left join SecondJoinTable SJT
        on  ST.SourceTableID = SJT.SourceTableID
        and JT.Column3 = SJT.Column4

where

    -- comment why this filter is applied
    ST.SourceTableID = X

    -- comment why this filter is applied
    and JT.ColumnName3 = (
            select 
                somecolumn
            from 
                sometable
        )
;

Преимущества:
- Комментарии являются неотъемлемой частью написания кода и обнаружения ошибок.
- Добавление -all- "on" -фильтров в соединение позволяет избежать ошибок при переходе от внутреннего к левому соединению.
- Размещение точки с запятой на новой строке позволяет легко добавлять/комментировать предложения.

Ответ 6

Я склонен использовать макет, похожий на ваш, хотя я даже иду на несколько шагов дальше, например:

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

where
        ST.SourceTableID    =   X
    and JT.ColumnName3      =   Y
    and JT.Column3          =   SJT.Column4

Возможно, на первый взгляд это выглядит немного чрезмерно, но ИМХО использование табуляции таким образом дает наиболее чистую, наиболее систематизированную компоновку с учетом декларативной природы SQL.

Вы, вероятно, получите здесь ответы на все вопросы. В конце концов, это сводится к личным или согласованным с командой предпочтениям.

Ответ 7

SELECT
    a.col1                  AS [Column1]
    ,b.col2                 AS [Column2]
    ,c.col1                 AS [Column3]
FROM
    Table1 a
    INNER JOIN Table2 b     ON b.Id = a.bId
    INNER JOIN Table3 c     ON c.Id = a.cId
WHERE
    a.col     = X
    AND b.col = Y

Здесь используется гораздо больше строк, чем во многих примерах, но я чувствую, что это намного проще для понимания, позволяет быстро удалять столбцы/пункты/таблицы. Это помогает использовать преимущества вертикально ориентированного монитора.

Ответ 8

Я использую формат, аналогичный вашему, за исключением того, что я помещаю ключевое слово 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

Ответ 9

Я понимаю, что очень опоздал на эту дискуссию, но я хотел бы высказать свои мысли. Я определенно поддерживаю запятые в начале строки. Как вы говорите, Адам Ральф, легче закомментировать поле, и я также нахожу, что сложнее случайно пропустить запятую, когда они в начале, хотя это не кажется серьезной проблемой. В прошлом я часами пытался отследить случайные синтаксические ошибки в длинных процедурах T-SQL, где я случайно пропустил запятую в конце строки (я уверен, что некоторые из вас, вероятно, также сделали это), Я также за алиасинг как можно больше.

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

Ответ 10

Я работаю над написанием средства форматирования SQL с открытым исходным кодом (только на этом этапе на SQL-сервере) на С#, поэтому я поставил вышеупомянутые запросы через него.

Он использует стратегию, аналогичную OP, а именно, что каждый "раздел" имеет дочерние элементы с отступом под ним. Там, где это необходимо, я добавляю пробел между разделами для ясности - они не будут добавлены, когда нет соединений или минимальных условий.

Результат:

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 ST.SourceTable2ID = SJT.SourceTable2ID

WHERE ST.SourceTableID = X
  AND JT.ColumnName3 = Y
  AND JT.Column3 = SJT.Column4

ORDER BY
    ST.ColumnName1

Ответ 11

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

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

Против:

Select column1,
   column2,
   column3, ect...

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

Ответ 12

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

SELECT ST.ColumnName1,
       JT.ColumnName2,
       SJT.ColumnName3,
       CASE WHEN condition1 = True 
             AND condition2 = True Then DoSomething
            Else DoSomethingElse
        END ColumnName4
  FROM SourceTable AS ST
 INNER
  JOIN JoinTable AS JT
    ON JT.SourceTableID = ST.SourceTableID
 INNER
  JOIN SecondJoinTable AS SJT
    ON ST.SourceTableID = SJT.SourceTableID
   AND JT.Column3 = SJT.Column4
  LEFT
  JOIN (SELECT Column5
          FROM Table4
       QUALIFY row_number() OVER
                 ( PARTITION BY pField1,
                                pField2
                       ORDER BY oField1
                 ) = 1
       ) AS subQry
    ON SJT.Column5 = subQry.Column5
 WHERE ST.SourceTableID = X
   AND JT.ColumnName3 = Y

Ответ 13

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

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

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

Ответ 14

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

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

Только мои $0.02 стоит

Ответ 15

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

Ответ 16

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

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

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

Ответ 17

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

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

Очень нравится тот факт, что вы идете в нижнем регистре по ключевым словам - Кто хочет, чтобы эти ВЫШЕИЗЛОЖЕНЫ на вас. Я также предпочитаю псевдонимы в нижнем регистре таблицы - делает их более удобочитаемыми.

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

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

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

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
;

Спасибо, что обсудили это.

Ответ 18

Число разных мнений страшно. Это то, что использует моя организация:

 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

Поддержание 8-символьного отступа является ключом к удобочитаемости IMHO.

Ответ 19

Никто еще не делал общих табличных выражений (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 делает с его скобками. Это также, как я делаю скобки в С#.

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

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 более устойчив, чем в других областях. Не экспериментировал со стилями, более похожими на те, что изложены в вопросе. Наверное сделаю когда нибудь и посмотрю как мне это понравится. Я, вероятно, проклят, чтобы быть в среде, где это выбор, хотя это забавное проклятие иметь.

Ответ 20

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

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

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

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


Вот краткий обзор с некоторыми из моих заметок о предпочтениях с учетом оператора SELECT. Я бы добавил скриншоты всех 13 разделов; Но это очень много скриншотов, и я просто рекомендую вам бесплатно edition-- сделать несколько скриншотов и проверить элементы управления форматом. Я скоро опробую 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] = ЛОЖЬ

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

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

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

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

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

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

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

9. Пробелы (ПРО)

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

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

(изменить?) Строка & Block--> [Разрыв строки до/после комментариев блока] = ИСТИНА; [Изменить комментарии строки в блок]; [Блок в линию]

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

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

(Может быть полезно) Извлечь SQL из программы Code--> [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

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

Ответ 21

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

Пример 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())

Ответ 22

Лучше поздно, чем никогда. Я использую другой стиль и перенял его у очень хорошего разработчика SQL, с которым я работал. Я выравниваю ключевые слова по правому краю и не использую буквы UPPERCASE для простоты ввода. Ключевые слова будут выделены редактором, и я не вижу необходимости, чтобы они были в верхнем регистре, если вы не выполняете много редактирования в текстовых редакторах, которые не поддерживают функции выделения ключевых слов. Я не пытаюсь сделать его компактным, а как можно более читаемым и выровненным по вертикали. Вот пример выбора, взятого из ответа @BenLaan, написанного в моем формате:

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 st.SourceTable2ID = sjt.SourceTable2ID
 where st.SourceTableID = X
       and jt.ColumnName3 = Y
       and jt.Column3 = sjt.Column4
 order by st.ColumnName1

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

ОБНОВЛЕНИЕ: переписывание одного из сложных запросов, упомянутых в предыдущих постах:

select
       term
       , student_id
       , case
           when((ft_credits > 0 and credits >= ft_credits) or (ft_hours_per_week > 3 and hours_per_week >= ft_hours_per_week))
             then 'F'
           else 'P'
         end as status
  from (select term
               , student_id
               , pm.credits AS ft_credits
               , pm.hours AS ft_hours_per_week
               , SUM(credits) AS credits
               , SUM(hours_per_week) AS hours_per_week
          from (select e.term
                       , e.student_id
                       , nvl(o.credits, 0) credits
                       , case
                           when nvl(o.weeks, 0) > 5 
                             then (nvl(o.lect_hours, 0) + nvl(o.lab_hours, 0) + nvl(o.ext_hours, 0)) / nvl(o.weeks, 0)
                           else 0
                        end as hours_per_week
                  from enrollment as e
                         inner join 
                       offering as o using (term, offering_id)
                         inner join
                       program_enrollment as pe 
                         on e.student_id = pe.student_id 
                         and e.term = pe.term 
                         and e.offering_id = pe.offering_id
                 where e.registration_code not in ('A7', 'D0', 'WL')
                )
                  inner join 
                student_history as sh using (student_id)
                  inner join 
                program_major as pm 
                  on sh.major_code_1 = pm._major_code and sh.division_code_1 = pm.division_code
         where sh.eff_term = (select max(eff_term)
                                from student_history as shi
                               where sh.student_id = shi.student_id
                                     and shi.eff_term <= term)
         group by term, student_id, pm.credits, pm.hours
        )
 order by term, student_id

Ответ 23

Мне нравится, чтобы мой SQL был отформатирован так, хотя, хотя намерение легко читается, большинство форматов будут работать. Я просто ненавижу видеть утверждения, созданные в дизайнере запросов, а затем оставил этот путь. Если я редактирую кому-то еще процедуру /view/function/trigger и т.д., Я попытаюсь сохранить уже используемое форматирование (если это действительно плохо, тогда я переформатирую все это).

Выбрать выражение

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);

Операция обновления

UPDATE TargetTable SET
       ColumnName1 = @value,
       ColumnName2 = @value2
 WHERE (Condition1 = @test);

Вставить выражение

INSERT INTO TargetTable 
           (
             ColumnName1,
             ColumnName2,
             ColumnName3
           ) 
           values 
           (
             @value1,
             @value2,
             @value3
           );

Ответ 24

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

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

Некоторые правила, которые я всегда использую:

  • Всегда используйте. Обозначение
  • Всегда используйте псевдоним перед столбцом, поэтому. Обозначение
  • Я положил and и or в конец строки
  • Не используйте unneseccary brackets
  • Не используйте UPPERCASE
  • Обычно предпочитают cte для вложенных подзапросов

В качестве примера, вот как я форматировал запрос, используемый в качестве примера в этом вопросе:

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

И запрос "students":

select
    term,
    student_id,
    case
        when (ft_credits > 0 and credits >= ft_credits) or (ft_hours_per_week > 3 and hours_per_week >= ft_hours_per_week) then 'F'
        else 'P'
    end as [status]
from (
    select
        a.term,
        a.student_id,
        pm.credits as ft_credits,
        pm.[hours] as ft_hours_per_week,
        sum(a.credits) as credits,
        sum(a.hours_per_week) as hours_per_week
    from (
        select
            e.term, e.student_id, NVL(o.credits, 0) credits,
            case
                when NVL(o.weeks, 0) > 5 then
                    (NVL(o.lect_hours, 0) + NVL(o.lab_hours, 0) + NVL(o.ext_hours, 0)) / NVL(o.weeks, 0)
                else
                    0
            end as hours_per_week
        from enrollment as e
            inner join offering as o using (term, offering_id)
            inner join program_enrollment as pe on pe.student_id = e.student_id and pe.term = e.term and pe.offering_id = e.offering_id
        where
            e.registration_code Not in ('A7', 'D0', 'WL')
    ) as a
        inner join student_history as sh using (student_id)
        inner join program_major as pm on pm._major_code = sh.major_code_1 and pm.division_code = sh.division_code_1
    where
        sh.eff_term = 
            (
                select max(eff_term)
                from student_history as shi
                where
                    shi.student_id = sh.student_id and
                    shi.eff_term <= term
             )
    group by
        a.term,
        a.student_id,
        pm.credits,
        pm.[hours]
) as a
order by
    term,
    student_id

Ответ 25

Мой предпочтительный стиль:

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
WHERE
  ST.SourceTableID = X
AND
  JT.ColumnName3 = Y
AND
  JT.Column3 = SJT.Column4

Ответ 26

SELECT st.ColumnName1
      ,jt.ColumnName2
      ,sjt.ColumnName3
FROM   SourceTable st
JOIN   JoinTable jt ON jt.SourceTableID = st.SourceTableID
JOIN   SecondJoinTable sjt ON SstT.SourceTableID = sjt.SourceTableID
                              AND jt.Column3 = sjt.Column4
WHERE  st.SourceTableID = X
       AND jt.ColumnName3 = Y

Я использую все шапки для слов действий, объединений или предложений, они выделяются лучше. JOIN - это то же самое, что и INNER JOIN, поэтому INNER не нужно выписывать, он предположил, напишите OUTER JOIN или LEFT JOIN, когда вам это нужно. Я также использую lowere case для моих псевдонимов. Обычная внешняя причина, если вы закомментируете последний столбец, вы застряли с запятой выше, и запрос завершился неудачно.

Ответ 27

Уже сто ответов здесь, но после долгих разборок и вскрытий на протяжении многих лет, это то, что я решил:

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

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

Ответ 28

Это формат, который я использую. Пожалуйста, прокомментируйте, если это может быть лучше.

CREATE PROCEDURE [dbo].[USP_GetAllPostBookmarksByUserId]
    @id INT,
    @startIndex INT,
    @endIndex INT
AS
BEGIN

    SET NOCOUNT ON

    SELECT      *
    FROM
            (   SELECT      ROW_NUMBER() OVER ( ORDER BY P.created_date ) AS row_num, P.post_id, P.title, P.points, p.estimated_read_time, P.view_count, COUNT(1) AS "total_attempts" -- todo
                FROM        [dbo].[BOOKMARKED] B
                INNER JOIN  [dbo].[POST] P
                ON          B.entity_id = P.post_id
                INNER JOIN  [dbo].[ATTEMPTED] A
                ON          A.entity_id = P.post_id
                WHERE       B.user_id = 1 AND P.is_active = 1
                GROUP BY    P.post_id, P.title, P.points, p.estimated_read_time, P.view_count
            )   AS PaginatedResult
    WHERE       row_num >= @startIndex
    AND         row_num < @endIndex
    ORDER BY    row_num

END

Ответ 29

Похоже, что большинство из вас по-прежнему работают на мониторах, поддерживающих только 800x600. Мои мониторы будут делать 1920x1080, поэтому я хочу использовать все это пространство справа.

как насчет этого:

select col1, col2, col3
, case when x = 1 then 'answer1'
       else 'answer2'
  end
, col4, col5, col6, col7
from table1 t1
inner join table2 t2 on t1.col1 = t2.col1 and t1.col2 and t2.col2
where t1.col5 = 19 and t1.col7 = 'Bill Gates'