N S

Novick Software Management • Design • Programming • Training • Consulting

   

 

 

Separator First Formatting

Volume 3 #8    February 22, 2005  Full TOC

by Andrew Novick

Sign up for this newsletter at: http://www.novicksoftware.com/coding-in-sql/coding-in-sql-signup.htm

The second theme of 2005 for the Coding-in-SQL newsletter is T-SQL Coding Style.  That is, how T-SQL statements and comments are presented.

You may have already noticed that the formatting of the SQL statements in this newsletter is slightly unusual.  Over the last few years, I've come to use a system that I call “Separator First Formatting” or SFF.  I've seen a few other programmers use it, so I'm not the only one.

The principal practice in SFF is to put separators, such as commas and “and” and “or” operators at the start of a new line.  We'll go into the details in a second.

There are several reasons for using the SFF system:

·         Documentation. SFF doesn't add documentation; it's intended to promote it by making it easier to include documentation on each line to explain the code.

·         Typability. Ease of adding and removing lines in a series.

·         Visibility. Some of the separators such as join operators and “and” logical operators are extremely important and get visual prominence by starting the line.

·         Flexibility. By putting separators at the beginning of the line it becomes easy to comment it out by adding a double-dash at the beginning of the line. (Query Analyzer has a hot-key, CTRL-SHIFT-C, that inserts the double-dash)

When formatting with separators first, almost all separators start their own line.  That leads to a lot of lines but most importantly, when combined with T-SQL's double-dash comment, it makes it easier to put an explanatory comment on each, and sometimes every, line.  Here's an example:

-- SELECT with Seperator First Firmatting
SELECT a.au_id
    , [dbo].[udf_Name_FullWithComma](au_fname, null
                            , au_lname, null) as Name -- so it's sortable
    , au_fname, au_lname -- sent so client grid can sort
    , t.title
    , ta.royaltyper
    FROM pubs..authors a with (nolock)
        RIGHT OUTER JOIN pubs..titleauthor ta WITH (NOLOCK)
            on a.au_id = ta.au_id
        INNER JOIN pubs..titles t WITH (NOLOCK)
            on ta.title_id = t.title_id
    WHERE t.type = 'trad_cook'
      and ta.royaltyper > 50 -- 50 cents. authors aren't paid well.
    ORDER BY Name
            , t.title -- multiple titles per author.
GO

For starters, each subclause (FROM, WHERE, ORDER BY) of the SELECT starts a new line indented one tab stop from the start of the SELECT.  The first entry in the list goes on the line with the subclause.  That's a compromise to keep the code slightly more compact.

In most circumstances, every entry in a list after the first goes on its own line.  There will be exceptions.  For one, the arguments to a function call rarely belong on their own line.  Therefore the lines:

    , dbo.udf_NameFullWithComma(au_fname, null
                            , au_lname, null) as Name –-- so it's sortable.

are broken only when it was necessary to do so for publication.  Sometimes space considerations are more important and several lines are combined. For example this line has two fields on it because they're covered by the same comment:

    , au_fname, au_lname -- sent so client grid can sort on these columns.

My overriding decision criteria for layout is to make the code more readable. It's just too bad that I don't get paid by the line of code.

I try and put each table in the FROM clause on its own line with any WITH clause.  WITH clauses are hints instructing SQL Server how to perform the query.  This line pulls in information from the pubs.titleauthor table:
 

       RIGHT OUTER JOIN pubs..titleauthor ta WITH (NOLOCK)

Notice that I almost always use a table alias.  I also use column aliases for every expression but avoid them when the column is not an expression.

When I write SQL for publication I try to put SQL keywords in upper case.  I do that so that they are visually distinct.  When writing SQL for any purpose except publication, I type in all lowercase except variable names that have upper case letters embedded.  The coloring that Query Analyzer uses is sufficient to differentiate the parts of SQL.  Besides, typing all those upper case characters is harder on the fingers.  After 30+ years of programming my digits are pretty tired and they appreciate any break that they get.

You may discover almost as many formatting conventions as there are programmers.  SFF works for me because it makes the SQL more readable and easier to change.  For example, to add another column to the end of the SELECT list all that is necessary is to put in the new line.  There's no need to change the line before the new one to add a comma after the expression.  The same works in reverse.  By putting the separators at the start of a line, it's only necessary to put a double dash at the start of a line to eliminate it.  There's no need to go to the previous line and adjust the commas.  For example, to eliminate the second conditional expression from the WHERE clause, just add a double dash as in:

    WHERE t.type = 'trad_cook'

      -- and ta.royaltyper > 50 -- 50 cents. authors aren't paid well.

The 2nd set of double dashes that delimited the original comment is ignored.

In a function creation script, SFF comes into play in the parameter list, as you can see from this function declaration:

CREATE FUNCTION dbo.udf_Name_FullWithComma (

    @sFirstName nvarchar(20) = N'' -- First Name
  , @sMiddleName nvarchar(20) = N'' -- Middle or Initial
  , @sLastName nvarchar(40) = N'' -- Last Name
  , @sSuffixName nvarchar(20) = N'' -- Suffix name, like Jr or MD
)   RETURNS nvarchar(128)
    WITH SCHEMABINDING -- Or comment why not
/*
* The function comment block goes here
***************************************************************/
AS BEGIN

To make the CREATE FUNCTION script easy to maintain:

·         Put the opening parenthesis on the line with the function name.

·         Skip a line

·         Put each parameter on its own line.

·         Use default values when possible.

·         Comment each parameter.

·         Put the right parenthesis that closes the parameter list on a line with the RETURNS clause.

·         The WITH SCHEMABINDING line. It has the WITH SCHEMABINDING line, or a comment that says why the function is not schema bound. If you add WITH ENCRYPTION it also goes here.

·         Finally, the AS BEGIN goes on its own line.

Not only do these practices make formatting a little easier, they document the parameters. One of the reasons to get every parameter on its own line is to leave room for the comment describing how the parameter is used.  Unless the name, “says it all”, each parameter deserves a comment describing how to use it.

This article is the start of the theme of "T‑SQL Coding Style".  That is, how to write T-SQL code so that it's readable and easily modified. As always, if you have comments about the newsletter and in particular, the new direction that it's taking, please let me know at coding-in-sql@novicksoftware.com.

Transact-SQL User-Defined Functions has been published!  Take a look at it now!


Do you have an interesting stored procedure, user-defined-function, or other sample code?  If you'd like to share them please send them in an email to: coding-in-sql@NovickSoftware.com  and they might be published in this newsletter.  I try and respond to every request that I get. 

Thanks, 
Andy
Andrew Novick


RSS as HTML

Personal Blog

 
New Tips:

Loading SQL Profiler trace (.trc) files with fn_trace_gettrace

Upcoming
Presentations:

Big Data:
Working with Terabytes
in SQL Server

July 9 '08

Nov 19-21
SQL Pass 2008


Full Schedule