Хорошая практика использования отступов в операторах SQL [закрыто]
-
07-07-2019 - |
Вопрос
Какова общепринятая практика создания отступов в SQL-операторах?Например, рассмотрим следующий оператор SQL:
SELECT column1, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
Как это должно быть оформлено с отступом?Большое спасибо.
Решение
SELECT column1
, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
Мне нравится иметь все ", "впереди, таким образом, я никогда не ищу их при появлении ошибки в строке X из редактора SQL.
Это пример для тех, кто не использует этот тип записи SQL-инструкции.Оба содержат ошибку в виде пропущенной запятой.
SELECT sdcolumn123
, dscolumn234
, sdcolumn343
, ffcolumn434
, sdcolumn543
, bvcolumn645
vccolumn754
, cccolumn834
, vvcolumn954
, cvcolumn104
FROM table1
WHERE column3 IN
(
...
)
SELECT sdcolumn123, dscolumn234, asdcolumn345, dscolumn456, ascolumn554, gfcolumn645 sdcolumn754, fdcolumn845, sdcolumn954, fdcolumn1054
FROM table1
WHERE column3 IN
(
...
)
В первом примере мне показалось проще и быстрее.Надеюсь, этот пример лучше покажет вам мою точку зрения.
Другие советы
SELECT column1, column2
FROM table
WHERE column3 IN (
SELECT TOP(1) column4
FROM table2
INNER JOIN table3 ON table2.column1 = table3.column1
)
Это довольно короткий и легкий для чтения. Я бы внес коррективы, если бы было выбрано больше столбцов или больше условий соединения.
Не уверен, что есть принятая практика, но вот как я это сделаю:
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN
(
SELECT TOP(1)
column4
FROM
table2
INNER JOIN
table3
ON table2.column1 = table3.column1
)
Мне нравится иметь "реки" пустого пространства в коде. Это немного облегчает сканирование.
SELECT column1,
column2
FROM table1
WHERE column3 IN (SELECT column4
FROM table2
JOIN table3
ON table2.column1 = table3.column1);
Мне нравится, как Джалберт выстраивает ключевые слова справа от себя. Я также хотел бы добавить, что мне нравятся AND и OR слева (некоторые люди ставят их справа). Кроме того, мне нравится выстраивать мои знаки равенства, когда это возможно.
SELECT column1,
column2
FROM table1, table2
WHERE table1.column1 = table2.column4
AND table1.col5 = "hi"
OR table2.myfield = 678
Это мой личный метод. В зависимости от длины условия соединения я иногда делаю отступ в строке ниже.
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (
SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3 ON table2.column1 = table3.column1
)
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (
SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3
ON table2.column1 = table3.column1 -- for long ones
)
Я написал кодовый стандарт для нашего магазина, который предельно смещен в сторону читабельности / «открываемости». (последний в первую очередь полезен в операторах вставки-выбора):
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN
(
SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3 ON table2.column1 = table3.column1
)
На более сложных запросах становится все более очевидным, насколько это полезно:
SELECT
Column1,
Column2,
Function1
(
Column1,
Column2
) as Function1,
CASE
WHEN Column1 = 1 THEN
a
ELSE
B
END as Case1
FROM
Table1 t1
INNER JOIN Table2 t2 ON t1.column12 = t2.column21
WHERE
(
FilterClause1
AND FilterClause2
)
OR
(
FilterClause3
AND FilterClause4
)
Как только вы перешли на системы с более чем одним объединением в большинстве ваших запросов, я понял, что свободное использование вертикального пространства - ваш лучший друг со сложным SQL.
Если у вас есть длинная инструкция SQL, которую вы хотите переформатировать без всякого набора текста и табуляции, вы можете добавить ее в этого веб-сайта и получите красиво отформатированный результат. Вы можете поэкспериментировать с различными форматами, чтобы увидеть, что делает ваш текст наиболее читабельным.
Изменить. Я считаю, что это является местоположением средства форматирования SQL в 2014 году.
Форматирование SQL - это область, в которой существует много расхождений и разногласий...Но, черт возьми, мне нравится сосредотачиваться на удобочитаемости и думать, что, что бы вы ни делали, последовательное соблюдение любых правил, снижающих удобочитаемость, является, как гласит старое клише, "глупой последовательностью" ( "Глупая последовательность - это хобби для простых умов").
Итак, вместо того чтобы называть их правилами, вот несколько рекомендаций.Для каждого основного предложения в инструкции SQL (Select, Insert, Delete, From, Where, Having, Group BY, Order By, ...Возможно, я упускаю несколько) должны быть ЛЕГКО идентифицируемы.Поэтому я обычно размещаю их с отступами на самом высоком уровне, все вровень друг с другом.Затем внутри каждого предложения я равномерно делаю отступ для следующей логической подструктуры...и так далее..Но я не стесняюсь (и часто делаю) изменять шаблон, если в каком-либо отдельном случае это было бы более читабельно...Хорошим примером являются сложные операторы Case.Поскольку все, что требует горизонтальной прокрутки, значительно снижает читаемость, я часто пишу сложные (вложенные) регистровые выражения в нескольких строках.Когда я это делаю, я стараюсь оставить в начале такого оператора висячий отступ, основанный на его логическом месте в инструкции SQL, и делаю отступ в остальных строках инструкции на несколько символов дальше...
Код базы данных SQL существует уже давно, еще до того, как компьютеры начали использовать нижний регистр, поэтому исторически предпочтение отдавалось ключевым словам в верхнем регистре, но я предпочитаю удобство чтения традициям...(и каждый инструмент, который я использую, теперь все равно кодирует ключевые слова цветом)
Я бы также использовал псевдонимы таблиц, чтобы уменьшить объем текста, который приходится сканировать глазу, чтобы понять структуру запроса, при условии, что псевдонимы не создают путаницы.В запросе, содержащем менее 3 или 4 таблиц, подойдут односимвольные псевдонимы, я часто использую первую букву таблицы, если все таблицы начинаются с другой буквы...опять же, все, что больше всего способствует удобочитаемости.Наконец, если ваша база данных поддерживает это, многие ключевые слова являются необязательными (например, "Внутренний", "Внешний", "Как" для псевдонимов и т.д.) "Into" (из Insert Into) является необязательным на Sql Server, но не на Oracle) Поэтому будьте осторожны при использовании этого, если ваш код должен быть независимым от платформы...
Ваш пример я бы написал следующим образом:
Select column1, column2
From table1 T1
Where column3 In (Select Top(1) column4
From table2 T2
Join table3 T3
On T2.column1 = T3.column1)
Или
Select column1, column2
From table1 T1
Where column3 In
(Select Top(1) column4
From table2 T2
Join table3 T3
On T2.column1 = T3.column1)
Если бы в предложении select было еще много столбцов, я бы сделал отступ во второй и последующих строках...Обычно я НЕ придерживаюсь какого-либо строгого правила (по одному столбцу в строке), поскольку прокрутка в прямом направлении почти так же вредна для удобства чтения, как и горизонтальная прокрутка, особенно если только в первых десяти столбцах экрана есть какой-либо текст)
Select column1, column2, Col3, Col4, column5,
column6, Column7, isNull(Column8, 'FedEx') Shipper,
Case Upper(Column9)
When 'EAST' Then 'JFK'
When 'SOUTH' Then 'ATL'
When 'WEST' Then 'LAX'
When 'NORTH' Then 'CHI' End HubPoint
From table1 T1
Where column3 In
(Select Top(1) column4
From table2 T2
Join table3 T3
On T2.column1 = T3.column1)
Отформатируйте код любым способом, который сделает его наиболее читаемым...
Мне нравится, когда разные части моего запроса располагаются вертикально. Я имею тенденцию использовать размер табуляции 8 пробелов для SQL, который, кажется, работает хорошо.
SELECT column1,
column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
Пример отступа для очень очень очень сложного SQL:
SELECT
produtos_cesta.cod_produtos_cesta,
produtos.nome_pequeno,
tab_contagem.cont,
produtos_cesta.sku,
produtos_kits.sku_r AS sku_kit,
sku_final = CASE
WHEN produtos_kits.sku_r IS NOT NULL THEN produtos_kits.sku_r
ELSE produtos_cesta.sku
END,
estoque = CASE
WHEN produtos2.estoque IS NOT NULL THEN produtos2.estoque
ELSE produtos.estoque
END,
produtos_cesta.unidades as unidades1,
unidades_x_quantidade = CASE
WHEN produtos.cod_produtos_kits_tipo = 1 THEN CAST(produtos_cesta.quantidade * (produtos_cesta.unidades / tab_contagem.cont) * produtos_kits.quantidade AS int)
ELSE CAST(produtos_cesta.quantidade * produtos_cesta.unidades AS int)
END,
unidades = CASE
WHEN produtos.cod_produtos_kits_tipo = 1 THEN produtos_cesta.unidades / tab_contagem.cont * produtos_kits.quantidade
ELSE produtos_cesta.unidades
END,
unidades_parent = produtos_cesta.unidades,
produtos_cesta.quantidade,
produtos.controla_estoque,
produtos.status
FROM
produtos_cesta
INNER JOIN produtos
ON (produtos_cesta.sku = produtos.sku)
INNER JOIN produtos_pacotes
ON (produtos_cesta.sku = produtos_pacotes.sku)
INNER JOIN (
SELECT
produtos_cesta.cod_produtos_cesta,
cont = SUM(
CASE
WHEN produtos_kits.quantidade IS NOT NULL THEN produtos_kits.quantidade
ELSE 1
END
)
FROM
produtos_cesta
LEFT JOIN produtos_kits
ON (produtos_cesta.sku = produtos_kits.sku)
LEFT JOIN produtos
ON (produtos_cesta.sku = produtos.sku)
WHERE
shopper_id = '" + mscsShopperId + @"'
GROUP BY
produtos_cesta.cod_produtos_cesta,
produtos_cesta.sku,
produtos_cesta.unidades
)
AS tab_contagem
ON (produtos_cesta.cod_produtos_cesta = tab_contagem.cod_produtos_cesta)
LEFT JOIN produtos_kits
ON (produtos.sku = produtos_kits.sku)
LEFT JOIN produtos as produtos2
ON (produtos_kits.sku_r = produtos2.sku)
WHERE
shopper_id = '" + mscsShopperId + @"'
GROUP BY
produtos_cesta.cod_produtos_cesta,
tab_contagem.cont,
produtos_cesta.sku,
produtos_kits.sku_r,
produtos.cod_produtos_kits_tipo,
produtos2.estoque,
produtos.controla_estoque,
produtos.estoque,
produtos.status,
produtos.nome_pequeno,
produtos_cesta.unidades,
produtos_cesta.quantidade,
produtos_kits.quantidade
ORDER BY
produtos_cesta.sku,
produtos_cesta.unidades DESC
Поскольку большинство из приведенных выше выровняло имена возвращаемых столбцов, я считаю, что выстраивание имен и условий таблиц значительно улучшает читабельность.
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN
(
SELECT TOP(1)
column4
FROM
table2 INNER JOIN
table3 ON table2.column1 = table3.column1
)
И когда условия соединения становятся длинными.
SELECT
Column1,
Column2
FROM
Table1 JOIN
Table2 ON
Table1.Column3 = Table2.Column4 JOIN
Table3 ON
Table2.Column1 = Table3.Column1 and
Table2.ColumnX = @x and
Table3.ColumnY = @y
WHERE
Condition1=xxx and
Condition2=yyy and
(
Condition3=aaa or
Condition4=bbb
)
Вот мой взгляд на это:
select column1, column2
from table1
where (column3 in (
select top(1) column4
from table2
inner join table3
on (table2.column1 = table3.column1)
))
;
- Все в нижнем регистре, потому что строчные символы легче читать (и у нас есть подсветка кода, чтобы подчеркнуть ключевые слова), а также их легче вводить
- Каждое ограничение или параметр для ключевого слова (например, from при выборе или on при соединении) имеет отступ, чтобы показать их зависимость от ключевого слова outward
- Закрывающая скобка находится на том же уровне отступа, что и открывающая , где
- Используйте квадратные скобки для предложений where и on, чтобы повысить удобочитаемость
- Поставьте точку с запятой, закрывающую оператор select, с одинаковым отступом, чтобы можно было лучше различать несколько операторов (если вам нужна точка с запятой в вашем языке, как это делает SAS PROC SQL)
- Он по-прежнему довольно компактный и не растягивается по всей странице
Конечно, это сводится к личным предпочтениям. И если в условиях команды, это то, что должно быть согласовано между членами ради последовательности. Но это было бы моим предпочтением:
SELECT column1, column2
FROM table1
WHERE column3 IN(SELECT TOP(1) column4
FROM table2
INNER JOIN table3 ON
table2.column1 = table3.column1
)
Я бы отформатировал это так:
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (SELECT TOP(1)
column4
FROM
table2
INNER JOIN table3 ON table2.column1 = table3.column1)
или как это:
SELECT
column1,
column2
FROM
table1
WHERE
column3 IN (SELECT TOP(1) column4
FROM table2
INNER JOIN table3 ON table2.column1 = table3.column1)
Это мое обычное предпочтение.
....SELECT column1
........,column2
....FROM table1
....WHERE column3 IN (
........SELECT TOP(1) column4
........FROM table2
........INNER JOIN table3
............ON table2.column1 = table3.column1
....)
Несмотря на то, что stackoverflow портит форматирование с дополнительным начальным пробелом, я поставил несколько периодов, чтобы вы могли увидеть фактическое форматирование ...
Я только что пропустил его через мой prettifier SQL, и получилось вот так ....
SELECT column1, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
http://extras.sqlservercentral.com/prettifier/prettifier.aspx р>
..... Но я не нашел способа получить цвета в StackOverflow.
Да, это довольно субъективно...Но вот мои 2 цента:
SELECT
Column1,
Column2
FROM Table1
WHERE
Column3 IN (
SELECT Column4
FROM Table2
JOIN Table3 ON
Table2.Column1 = Table3.Column1
)
Но, на самом деле, я бы, наверное, переписал его без:
SELECT
Column1,
Column2
FROM Table1
JOIN Table2 ON
Table1.Column3 = Table2.Column4
JOIN Table3 ON
Table2.Column1 = Table3.Column1
По сути, мои правила таковы:
- Ключевые слова с заглавной буквы
- Столбцы располагаются в отдельных строках, но ВЫБРАННЫЕ модификаторы (ВЫБЕРИТЕ TOP 100, ВЫБЕРИТЕ DISTINCT и т.д.) Или отдельные столбцы (ВЫБЕРИТЕ 1, ВЫБЕРИТЕ Id, ВЫБЕРИТЕ * и т.д.) Располагаются в одной строке
- Условия объединения с отступом под предложением JOIN
- Используйте JOIN для ВНУТРЕННЕГО СОЕДИНЕНИЯ (поскольку оно является общим) и полностью укажите другие (ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ, ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ и т.д.)
- Откройте parens в той же строке, закройте paren в отдельной строке.Если у вас есть псевдоним, то псевдоним идет с close paren .
Эта ссылка - лучшая, которую я нашел. http://www.sqlinform.com/free_online_sw.html
Ну, конечно, это зависит от запроса. Р>
Для простых запросов очень формальная схема отступов - это просто больше проблем, чем стоит, и она может сделать код менее читаемым, а не больше. Но по мере роста сложности вам нужно начать более осторожно разбираться в том, как вы структурируете оператор, чтобы быть уверенным, что он будет читаться позже.
Я не знаю, есть ли стандарт, но мне нравится делать это таким образом;
SELECT column1, column2
FROM table1
WHERE column3 IN
(
SELECT TOP(1) column4
FROM table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
потому что я могу лучше читать и анализировать SQL.
SELECT
Column1,
Column2
FROM
Table1
WHERE
Column3 IN
(
SELECT TOP (1)
Column4
FROM
Table2
INNER JOIN
Table3
ON
Table2.Column1 = Table3.Column1
)
Что я обычно делаю, так это
print("SELECT column1, column2
FROM table1
WHERE column3 IN (SELECT TOP(1) column4
FROM table2 INNER JOIN
table3 ON table2.column1 = table3.column1)");
Это дело вкуса.
Это мои предпочтения.
SELECT
column1
,column2
FROM
table1
WHERE column3 IN (
SELECT TOP(1) column4
FROM
table2
INNER JOIN table3
ON table2.column1 = table3.column1
)
Вот как мы это сделаем здесь:
select COLUMN1, COLUMN2, case when COLUMN5 = 'X' and COLUMN6 = 'Y' then 'one' when COLUMN5 in ( 'AAA', 'BBB' ) then 'two' else 'three' end as COLUMN7 from TABLE1 where COLUMN2 in ( select top(1) COLUMN4 from TABLE2 inner join TABLE3 on TABLE2.COLUMN1 = TABLE3.COLUMN1 and TABLE2.COLUMN2 between TABLE3.COLUMN2 and TABLE3.COLUMN3 )
Наша идея состоит в том, чтобы сохранить ключевые слова sql в нижнем регистре и поместить все изменяющиеся (и, следовательно, «более интересные») вещи, такие как имена таблиц или столбцов, в верхний регистр. Код может выглядеть немного «взорванным» здесь, но это повышает удобочитаемость, если у вас есть сложные запросы с более длинными именами (включая схему и т. д.) намного дольше, чем в этом примере. И: сделать отступ для всех объектов в соответствии с их «уровнем».