webdevqa.jp.net

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

selectfrom、およびwhereの後の改行については、意見の相違がありました。選択行の目的は、レイアウトを変更せずに「トップ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にアクセスすると突然ランダムになってしまうことに常に驚かされます。

53
Timbo

私は、ソースコードを簡単に読むことができる限り、フォーマットは二次的なものであると考えています。この目的が達成される限り、採用できる多くの優れたレイアウトスタイルがあります。

私にとって重要な他の唯一の側面は、ショップで採用するコーディングレイアウト/スタイルが何であれ、すべてのコーダーが一貫して使用することを確認することです。

参考までに、あなたが提供した例を紹介します。レイアウトの設定だけです。特に、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

1つのヒントとして、 SQLプロンプト のコピーを Red Gate から入手してください。希望のレイアウト設定を使用するようにツールをカスタマイズすると、ショップのコーダー全員がそれを使用して、全員が同じコーディング標準を採用できるようになります。

16
John Sansom

遅い答えですが、うまくいけば便利です。

大規模な開発チームの一員として働いている私の経験では、好きな標準を定義することができますが、実際にはこれらを強制するか、開発者が非常に簡単に実装できるようにすることが問題です。

開発者として、機能するものを作成して「後でフォーマットします」と言うこともありますが、それは後からありません。

最初は、このためにSQLプロンプトを使用しました(それは素晴らしかったです)が、無料ツールであるため ApexSQL Refactor に切り替えました。

22
John Emeres

私はパーティーに遅れていますが、私は好みの書式設定スタイルを追加するだけです。これは本やマニュアルから学んだに違いありません。それはコンパクトです。サンプルの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インデントの位置をずらすか、Word BYを単独で分割します。 WHERE句の述語全体をインデントする方が自然ですが、通常、次のANDおよびOR演算子を左マージンに揃えます。ラップ後のインデントINNER JOIN行も多少arbitrary意的です。

しかし、何らかの理由で、私はまだ他の方法よりも読みやすいと思います。

最後に、このフォーマットスタイルを使用した、より複雑な作品の1つで終わります。 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

この憎悪は、学生が与えられた学期でフルタイムかパートタイムかを計算します。スタイルに関係なく、これは読みにくいです。

17
yukondude

いいねPythonプログラマーとして、ここに私の好みがあります:

selectfrom、およびwhereの後の改行は、読みやすくするために必要な場合のみ。

コードがよりコンパクトで読みやすい場合、私は通常、よりコンパクトな形式を好みます。より多くのコードを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

最終的に、これはコードレビュー中に行われる判断の呼び出しになります。

insertの場合、括弧を別の方法で配置します。

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

このフォーマットの理由は、SQLがブロック構造(Pythonなど)にインデントを使用した場合、括弧は必要ないためです。そのため、とにかくインデントが使用される場合、括弧はレイアウトに最小限の影響しか与えません。これは、行の最後に配置することにより実現されます。

5
ddaa

私は、C#でオープンソースのSQL Formatter(この段階ではSQLサーバーのみ)の作成に取り組んでいるので、上記のクエリを使用します。

OPと同様の戦略を採用しています。つまり、各「セクション」の下にインデントされた子要素があります。必要に応じて、セクションを明確にするためにセクション間に空白を追加します。結合がない場合、または最小の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 ST.SourceTable2ID = SJT.SourceTable2ID

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

ORDER BY
    ST.ColumnName1
4
Ben Laan
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

ここにある多くの例よりもはるかに多くの行を使用していますが、理解しやすく、列/句/表をすばやく削除できると感じています。これは、垂直指向のモニターを活用するのに役立ちます。

4
RossBille

ジョンの提案に基づいて、次のスタイルを提案します。

/*
<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's first in the list of joins>
    SourceTable ST

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

    -- <Comment why this join is made, and why it's 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" -filterを追加すると、内部結合から左結合に変更する際の間違いを回避できます。
-改行にセミコロンを配置すると、where句を簡単に追加/コメントできます。

4
Wouter

私はあなたのレイアウトに似たレイアウトを使用する傾向がありますが、さらにいくつかのステップに進みます:

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の宣言的な性質を考えると、最もクリーンで体系的なレイアウトが得られます。

おそらく、ここであらゆる種類の答えが見つかるでしょう。最終的には、個人的な好みまたはチームが同意した好みに依存します。

3
Adam Ralph

遅いですが、帽子をリングに投げます。書くのに少し時間がかかりますが、慣れるとパターンが非常に読みやすくなるため、垂直方向の配置でパターンが出現します。

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
3
Error_2646

これは私の個人的なSQLスタイルガイドです 。他のいくつかに基づいていますが、いくつかの主なスタイル上の特徴があります-小文字のキーワード、無関係なキーワード(outerinnerasc)、川"。

サンプル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
mattmc3

私はこの議論に非常に遅れていることに気づきましたが、考えを述べたいと思います。私は間違いなく、行頭のコンマを支持しています。 Adam Ralph と言うように、フィールドをコメントアウトするのは簡単です。また、最初にコンマを誤って見逃すことは難しいですが、これはメジャーのようには聞こえませんが問題。長い時間をかけて長いT-SQLプロシージャの偶発的な構文エラーを追跡しようとして過去何時間も費やしてきましたが、行末で誤ってコンマを忘れてしまいました(おそらくこれを行った人もいるでしょう) 。また、可能な限りエイリアシングを支持しています。

全体的に、しかし、私はそれがすべて個人的な好みに依存していることを理解しています。コードを簡単に読むことができ、各開発者がスタイル全体である程度の一貫性を示している限り、それが最も重要だと思います。

2
Daniel

このスレッドには多くの良い点があります。私が人々に使用を説得しようと試みている1つの標準は、各列の前の同じ行にコンマを配置することです。そのようです:

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

とは対照的に:

Select column1,
   column2,
   column3, ect...

私がこのプラクティスを好む理由は、必要に応じて行をコメントアウトでき、対応するコンマがコメントアウトされているために行を実行してもコンマの問題が発生しないためです。これを行ったスレッドで別のユーザーを見たことがありますが、実際には指摘していません。会話にもたらす大きな啓示ではなく、私の2セントです。ありがとう

2
AeternusMenti

まだ誰もやっていません 共通テーブル式 (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では、「with」は別の行にあり、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形式以外のいくつかのポイント:

  • 「選択」およびその他のキーワードの後の2つのタブ。これにより、「内部結合」、「グループ化」などのための十分な余地が残されます。それ以外の場合、上記の例を見ることができます。しかし、「内部ハッシュ結合」は見苦しいはずです。それにもかかわらず、この時点で、おそらく上記のスタイルのいくつかを将来的に実験するつもりです。
  • キーワードは小文字です。 IDEによる色分けと特別なインデントステータスは、それらを十分に強調します。ローカル(ビジネス)ロジックに基づいて強調したい他のもののために大文字を予約します。
  • 列が少ない場合、それらを1行に配置します(getSomeData)。さらにいくつかある場合は、それらを垂直化します(getSomeOtherData)。 1つのユニットで垂直化が多すぎる場合、ローカルに定義されたロジック(最終的な挿入選択セグメント)でグループ化された同じ行にいくつかの列を水平化します。たとえば、学校レベルの情報を1行に、学生レベルの情報を別の行に配置します。
  • 特に、垂直化するときは、SQLサーバーの「varname = colname + something構文」を「colname + something as varname」よりも優先します。
  • Caseステートメントを扱っている場合は、最後のポイントを2倍にします。
  • 特定のロジックが「マトリックス」スタイルに適している場合は、タイピングの結果に対処します。それはcase文で起こっていることの一種で、「when」と「then」が整列しています。

私は自分のCTEスタイルに他の分野よりも落ち着いていることがわかりました。質問で提示されたスタイルに似たスタイルを試していない。おそらくいつかやってみて、私はそれが好きかどうかを確認します。私はおそらく、それが選択できる環境にいるのは呪われていますが、それは楽しい呪いです。

2
pwilcox

ONキーワードを結合と同じ行に配置し、ANDおよびOR演算子を行の最後に配置することを除いて、ユーザーの形式と同様の形式を使用して、すべての結合/選択基準がうまく揃うようにします。

私のスタイルはJohn Sansomのスタイルに似ていますが、結合条件を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ごとに新しい行とインデントを付け、ENDCASEに戻します。

_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
Tom H

異なる意見の数は恐ろしいです。これは私の組織が使用するものです:

 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文字のインデントを維持することが重要です。

1
dthree

プロジェクト内および一般的なSQLのフォーマットを標準化するためのあなたの努力に心から同意します。

また、フォーマットの選択にも非常に同意します。私は「join」ステートメントをインデントし、さらに「on」ステートメントをもう1インデントしない限り、ほぼ同じものを思い付きました。

キーワードに小文字を使用するという事実に非常によく似ています。小文字のテーブルエイリアスも好む-読みやすくする

小さなインデントを使用するという事実に非常によく似ています(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
;

これについて議論してくれてありがとう。

1
dlink

私の答えは、John Sansom answered Feb 6 '09 at 11:05。ただし、Red GateのSQLプロンプトでの答えとは対照的に、 NOTEPAD ++のSQLInFormプラグイン を使用して、いくつかのフォーマットオプションを示します。

SQLInFormプラグインには、セットアップ可能な5つの異なるプロファイルがあります。プロファイル内には、無料版と有料版の両方で利用可能な多くの設定があります。完全なリストは以下にあり、それらの plugin-help-general-options ページをオンラインで見ることができます。

私の好みをとりとめなくする代わりに、利用可能なSQLInFormオプションを提示することが有益だと考えました。私の好みのいくつかも以下に記載されています。投稿の最後に、元の投稿で使用されたフォーマット済みSQLコードがあります(original VS format1 VS format2)。

ここで他の答えを読んでください-私はいくつかのことで少数派のようです。好き leading commasShort Video Here )-IMO、新しいフィールドが選択されている場合、読みやすくなります。また、Column1 with linebreakおよびSELECTの隣ではありません。


SELECTステートメントを考慮した、いくつかの私の設定ノートの概要を以下に示します。 13のセクションすべてのスクリーンショットを追加します。しかし、それは多くのスクリーンショットであり、無料版をお勧めします。スクリーンショットをいくつか撮り、フォーマットコントロールをテストしてください。私はPro版をすぐにテストします。しかし、オプションに基づいて、それは本当に便利で、わずか20ドルであるように見えます。

SQLInForm Notepadd ++:オプションと設定

1。一般(無料)

DB:SQL、DB2/UDB、Oracle、MSAccess、SQL Server、Sybase、MYSQL、PostgreSQL、Informix、Teradata、Netezza SQL

[スマートインデント] = FALSE

2。色(無料)

3。キーワード(PRO)

[Upper/LowerCase]>キーワード

4。改行>リスト(無料)

[コンマの前] = TRUE 5

[カンマを2列左に移動] = FALSE

5。改行>選択(PRO)

[結合>結合後] = FALSE

[JOIN> ON前] = FALSE

(変更なし)-> [JOIN> Indent JOIN]; [JOIN> ON後]

6。改行> Ins/Upd/Del(PRO)

7。改行>条件(PRO)

CASEステートメント-> [WHEN]、[THEN]、[ELSE]…確かにこれらの設定で遊んで、良い設定を選びたい

8。アライメント(PRO)

(変更なし)-> [JOIN> Indent JOIN]; [JOIN> ON後]

9。空白(PRO)

(変更?)空白行Blank [すべて削除] = TRUE; [すべて保ちます]; [キープワン]

10。コメント(PRO)

(変更?)行とブロック-> [ブロックコメントの前後の改行] = TRUE; [行コメントをブロックに変更]; [ラインにブロック]

11。ストアドプロシージャ(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

お役に立てれば。

好き:

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
user1400745

SSMS内でRed Gate SQL ReFactorを使用していますが、再構成(およびSSMSの代替)を行う別のツールは ApexのSQL Edit です。オンラインでコードを投稿する場合は、 The Simple-Talk SQL Prettifier があります。

1
K. Brian Kelley

既に作成されたT-SQLに変更を加える場合、既に使用されている規則(ある場合)に従います。

私が最初から書いているか、慣例がない場合、キーワードに大文字を使用することを好むことを除いて、質問で与えられた慣習に従う傾向があります(読みやすさの個人的な好み)。

他のコード形式の規則と同様に、SQLの形式では、重要な点は、その規則が何であるかではなく、規則を持つことです(もちろん常識の範囲内!)

1
Russ Cam

ええ、私はあなたのSQLを厳密に定義された方法でレイアウトすることの価値を見ることができますが、命名規則とあなたの意図は間違いなくもっと重要です。 10倍重要です。

それに基づいて、私のペット嫌いはtblが前に付いたテーブルであり、spが前に付いたストアドプロシージャです-それらはテーブルとSPであることがわかります。 DBオブジェクトの命名は、スペースの数よりもはるかに重要です

ちょうど私の$ 0.02相当

1
MrTelly

絶対に遅れるよりはましです。私は別のスタイルを使用し、以前使用していた非常に優れたSQL開発者から採用しました。キーワードを右揃えにし、入力しやすいように大文字を使用しません。キーワードはエディターによって強調表示され、キーワードの強調表示機能をサポートしていないテキストエディターで多くの編集を行わない限り、キーワードを大文字にする必要はありません。私はそれをコンパクトにしようとはしませんが、むしろ読みやすく、できるだけ垂直に揃えます。以下は、私の形式で書かれた@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

すべてのチームが同じフォーマットパターンに従うようにすることは、最も難しいことです。誰もが同じ方法に従えば、私はどんなフォーマットでも従うでしょうが、それは同じ話ではありませんでした。

更新:以前の投稿で言及した複雑なクエリの1つを書き換えます。

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
0
rageit

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

更新ステートメント

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

文を挿入

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

バグを簡単に見つけて修正できるため、適切なフォーマットルールを設定することが非常に重要だと思います。 「コードを一度書くと、このコードは10000000回読み取られる」と言われているように、フォーマットに時間をかけることは常に良いことです。主な目標は次のとおりです。

  • コードを読みやすく理解しやすくする
  • コードを維持または拡張するために必要な労力を最小限に抑える
  • システムのユーザーと開発者がコードコメントやソフトウェアマニュアルなどの二次的なドキュメントソースを参照する必要性を減らします。

私がいつも使っているいくつかのルール:

  • 常に使用します。記法
  • 列の前に常にエイリアスを使用します。記法
  • andorを行末に配置します
  • 不nes好なブラケットを使用しないでください
  • 大文字を使用しないでください
  • 通常、ネストされたサブクエリよりも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

「学生」クエリ:

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
0
Roman Pekar
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を書きます。また、エイリアス名には小文字を使用しています。最後の列をコメントアウトして、上のコンマでスタックし、クエリが失敗した場合の一般的な原因。

0
DanTheMan

私の好みのスタイル:

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
0
Brady Holt

これは私が使用する形式です。改善できる場合はコメントしてください。

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
0
CodeZila

ここではすでに100件の回答がありますが、長年に渡って多くの苦労を重ねた結果、これが私が解決したものです。

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つ追加するとコードの多くの行がインデントされる可能性があるため、これにより面倒なdiffが作成される可能性がありますが、読みやすくするために気に入っています。

0
Codemonkey