Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

T-SQL Best Practices - PART I - Coding Style

T-SQL Hints and Tips

T-SQL Best Practices - PART I - Coding Style

by  donutman  Posted    (Edited  )
This FAQ is a summary of a long thread, thread183-856683, concerning coding styles that are commonly followed in order to insure that the T-SQL that you write can be easily understood by other programmers. The suggestions in that thread actually went beyond just questions of style and so I've grouped them into three categories: coding styles, naming conventions and general do's and don'ts. To see how nicely everything is formatted, it may be necessary to increase the size of your browser window or copy and paste the code into a fictitious stored procedure in EM in order to see it in full color!

Coding Style
[ul]
[li]Adopt a convention and enforce it company wide.[/li]
[li]Use indenting to help break up the sequence of statements, so that conditional statement flow is readily apparent.[/li]
[li]Some people like to use a fixed 3- or 4-spaces per indent level, while others like it to vary depending on the statement preceding the indent. [/li]
[li]Capatilize the entire keyword that EM would display in blue (e.g. within a stored procedure).[/li]
[li]Camel case the names of system functions like CharIndex() that EM would display in fuscia.[/li]
[li]Keep lines short so that horizontal scrolling isn't necessary.[/li]
[li]Use Begin and End blocks. Place the Begin at the end of the conditional clause and place the End on its own line but at the same indent level as the If or While that initiated its use.[/li]
[li]Use SET for assignment statements. An exception is SELECT @Err=@@Error, @RC=@@RowCount when both assignments must be made at the same time.[/li]
[li]Use SELECT for assignment statements that require a query. [/li]
[li]Dispense with the superfluous AS in data type statements and when aliasing.[/li]
[/ul]
Code:
[center][red] -- This BEGIN/END block assumes a fixed 3-space indent level --[/red][/center]
BEGIN
   DECLARE @ChrPos int, @Err int, @RC int, @Yr int
   DECLARE @SqlCase varchar(8000), 
      @AggFunction varchar(8000), @Delimiter varchar(5)
   SELECT CustomerOrderNo, FirstName, LastName, 
          FullName=LastName+', '+FirstName, OrderDate,
          ProductID, ProductName, Quantity, Price
      FROM Customer C 
         INNER JOIN CustomerOrder CO
            ON C.CustomerID=CO.CustomerID 
         INNER JOIN OrderItem OI 
            ON CO.CustomerOrderID=OI.CustomerOrderID
         INNER JOIN Product P
            ON OI.ProductID=P.ProductID
         INNER JOIN luProductPrice PP
            ON P.ProductID=PP.ProductID and PP.CustomerID=C.CustomerID 
      WHERE Year(OrderDate)=@Yr
      ORDER BY FullName
   SELECT @Err=@@Error, @RC=@@RowCount   
   IF @ChrPos>0 BEGIN
      SET @ChrPos = CharIndex('(CASE ',@SqlCase,@ChrPos)
      SET @SqlCase = Stuff (@SqlCase,@ChrPos+6,0,'WHEN ')
   END
   ELSE BEGIN
      SET @ChrPos = CharIndex(' WHEN ',@SqlCase,@ChrPos+10)
      SET @SqlCase = Stuff (@SqlCase, @ChrPos+1,9,'IS NULL')
   END
   WHILE Len(@AggFunction)<>@ChrPos BEGIN
      SET @ChrPos=Len(@AggFunction)
      SET @AggFunction=Replace(@AggFunction,' (','(')
      SET @AggFunction=Replace(@AggFunction,'( ','(')
   END
END
[green]
/* NOTE:
[ul][li]Each level of indentation is 3-spaces.[/li]
[li]Because the Select portion of the statement requires more than one line to list the columns it is given a double indent and leaves the single indent for the next main clause of a Select statement, namely the From clause. This makes it very clear to the reader that the Select statement is continued and that the next independent line of code is an If statement because the IF is at the same indent level as the SELECT.[/li]
[li]Each Declare statement is devoted to one data type.[/li][/ul]
*/ [/green]
[center][red]-- Another common approach to indentation is --
 the flexible indent.[/red][/center]
BEGIN
   DECLARE @ChrPos      AS int
   DECLARE @Err         AS int
   DECLARE @RC          AS int
   DECLARE @SqlCase     AS varchar(8000)
   DECLARE @AggFunction AS varchar(8000)
   DECLARE @Delimiter   AS varchar(5)
   SELECT CustomerOrderNo, 
          FirstName, 
          LastName, 
          FullName=LastName+', '+FirstName, 
          OrderDate,
          ProductID, 
          ProductName, 
          Quantity, 
          Price
   FROM Customer C 
        INNER JOIN CustomerOrder CO
              ON C.CustomerID=CO.CustomerID 
        INNER JOIN OrderItem OI 
              ON CO.CustomerOrderID=OI.CustomerOrderID
        INNER JOIN Product P
              ON OI.ProductID=P.ProductID
        INNER JOIN luProductPrice PP
              ON P.ProductID=PP.ProductID and 
                 PP.CustomerID=C.CustomerID 
   WHERE Year(OrderDate)=@Yr
   ORDER BY FullName
   SET @Err=@@Error
   IF @ChrPos>0 BEGIN
      SET @ChrPos  = CharIndex('(CASE ',@SqlCase,@ChrPos)
      SET @SqlCase = Stuff (@SqlCase,@ChrPos+6,0,'WHEN ')
   END
   ELSE BEGIN
        SET @ChrPos  = CharIndex(' WHEN ',@SqlCase,@ChrPos+10)
        SET @SqlCase = Stuff (@SqlCase, @ChrPos+1,9,'IS NULL')
   END
END
[green]/* NOTE:[ul][li]Only one variable to a Declare statement.[/li]
[li]Each column within a Select is given it's own line. [/li]
[li]The superfluous [i]AS[/i] has returned.[/li]
[li]The main clauses of the Select statements are at the same level of indentation.[/li]
[li]The columns, the table names and the conditional If statements have their indentation level determined by the preceding line.[/li]
[li]Some writers will employ a rule regarding left justification of repetitive statements as in the Declare statements, the Inner Join clause and the conditional statements within the If statement.[/li][/ul]
*/[/green]
I believe that both approaches and pretty much any combination of the two will produce clean, readable code. The first approach conserves vertical space, but the second one makes it easier to see a list of items like the column names and variable names.

Many thanks to those who contributed to the original thread that helped make this FAQ and the next two: Part II - Naming Conventions and Part III - Do's and Don'ts:[blue]
ESquared MDXer SQLSister
JayKusch nigelrivett TJRTech
john76 SQLBill vongrunt[/blue]

-Karl (donutman)
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top