Generally speaking, the SQL queries that I write return unformatted data, and I leave it at the presentation level, web page or Windows application to format the data as needed. Other people I work with, including my boss, will insist that it is more efficient to have a database. I’m not sure that I am buying this and I think that even if the measuring performance were achieved due to the fact that the database did this, you have more good reasons to avoid this altogether.
For example, I will post my queries at the data access level with the goal of potentially reusing queries when possible. With this in mind, I make sure that queries can be reused more often if the data remains in their native type rather than converting the data to a string and applying formatting functions to them, for example, formatting a date column in DD Format -MMM-YYYY for display. Of course, if SQL returned dates as formatted strings, you could cancel the process to return the value back to the date data type, but this seems inconvenient due to the lack of a better word. Furtehrmore, when it comes to formatting other data, for example, the serial number of a machine consisting of a prefix, base and suffix with a dash and leading zeros removed in each subfield, you risk that you cannot correctly return to the original serial number when go in the other direction. This may be a bad example, but I hope you see the direction I'm going ...
To take it a step further, I see that people write VERY complex SQL queries because they essentially write what I would call presentation logic in SQL instead of returning simple data and then applying that presentation logic at the presentation level . In my opinion, this leads to a very complex, complicated to maintain and more fragile SQL that is less adaptable to changes.
Take the following real-life example of what I found on our system and tell me what you think. Reasonable for this approach was that it simplified the web application for page rendering, since the following 1-line fragment of the classic ADO logic in the classic ASP web application was used to process returned strings.
oRS.GetString ( , , "</td>" & vbCrLf & "<td style=""font-size:x-small"" nowrap>" ,"</td>" & vbCrLf & "</tr>" & vbCrLf & "<tr>" & vbCrLf & _ "<td style=""font-size:x-small"" nowrap>" ," " ) & "</td>" & vbCrLf & "</tr>" & vbCrLf & _
Here is SQL itself. Although I appreciate the author’s ability to write complex SQL, I feel that this is a nightmare to maintain. Am I nuts? SQL returns a list of programs that currently work against our database and the status of each of them:
Since SQL did not display with CR / LF when I pasted here, I decided to put SQL on an empty personal Google site. Please feel free to comment. Thanks.
By the way, this SQL was actually built using VB Script embedded in the classic ASPIN page but not calling the stored procedure, so you have the added complexity of inline concatenations and cited markup if you know what I mean, not to mention lack of formatting. The first thing I did when I was asked to help debug SQL was to add debug.print to the SQL output and pass it through the SQL formatter I just found. Some formatting was lost when pasting at the following link:
Edit (Andomar): copied inline: (removed external link, thanks-Chad)
SELECT Substring(Datename("dw",start_datetime),1,3) + ', ' + Cast(start_datetime AS VARCHAR) "Start Time (UTC/GMT)" ,program_name "Program Name" ,run_sequence "Run Sequence" ,CASE WHEN batchno = 0 THEN Char(160) WHEN batchno = NULL THEN Char(160) ELSE Cast(batchno AS VARCHAR) END "Batch #" /* ,Replace(Replace(detail_log ,'K:\' ,'file://servernamehere/DiskVolK/') ,'\' ,'/') "log"*/ /* */ ,Cast('<a href="GOIS_ViewLog.asp?Program_Name=' AS VARCHAR(99)) + Cast(program_name AS VARCHAR) + Cast('&Run_Sequence=' AS VARCHAR) + Cast(run_sequence AS VARCHAR) + Cast('&Page=1' AS VARCHAR) + '' + Cast('">' + CASE WHEN end_datetime >= start_datetime THEN CASE WHEN end_datetime <> 'Jan 1 1900 2:00 PM' THEN CASE WHEN (success_code = 10 OR success_code = 0) AND exit_code = 10 THEN CASE WHEN errorcount = 0 THEN 'Completed Successfully' ELSE 'Completed with Errors' END WHEN success_code = 100 AND exit_code = 10 THEN 'Completed with Errors' ELSE CASE WHEN program_name <> 'FileDepCheck' THEN 'Failed' ELSE 'File not found' END END ELSE CASE WHEN success_code = 10 AND exit_code = 0 THEN 'Failed; Entries for Input File Missing' ELSE 'Aborted' END END ELSE CASE WHEN ((Cast(Datediff(mi,start_datetime,Getdate()) AS INT) <= 240) OR ((SELECT Count(* ) FROM MASTER.dbo.sysprocesses a(nolock) INNER JOIN gcsdwdb.dbo.update_log b(nolock) ON a.program_name = b.program_name WHERE a.program_name = update_log.program_name AND (Abs(Datediff(n,b.start_datetime,a.login_time))) < 1) > 0)) THEN 'Processing...' ELSE 'Aborted without end date' END END + '</a>' AS VARCHAR) "Status / Log" ,Cast('<a href="' AS VARCHAR) + Replace(Replace(detail_log,'K:\','file://servernamehere/DiskVolK/'), '\','/') + Cast('" title="Click to view Detail log text file"' AS VARCHAR(99)) + Cast('style="font-family:comic sans ms; font-size:12; color:blue"><img src="images\DetailLog.bmp" border="0"></a>' AS VARCHAR(999)) + Char(160) + Cast('<a href="' AS VARCHAR) + Replace(Replace(summary_log,'K:\','file://servernamehere/DiskVolK/'), '\','/') + Cast('" title="Click to view Summary log text file"' AS VARCHAR(99)) + Cast('style="font-family:comic sans ms; font-size:12; color:blue"><img src="images\SummaryLog.bmp" border="0"></a>' AS VARCHAR(999)) "Text Logs" ,errorcount "Error Count" ,warningcount "Warning Count" ,(totmsgcount - errorcount - warningcount) "Information Message Count" ,CASE WHEN end_datetime > start_datetime THEN CASE WHEN Cast(Datepart("hh",(end_datetime - start_datetime)) AS INT) > 0 THEN Cast(Datepart("hh",(end_datetime - start_datetime)) AS VARCHAR) + ' hr ' ELSE ' ' END + CASE WHEN Cast(Datepart("mi",(end_datetime - start_datetime)) AS INT) > 0 THEN Cast(Datepart("mi",(end_datetime - start_datetime)) AS VARCHAR) + ' min ' ELSE ' ' END + CASE WHEN Cast(Datepart("ss",(end_datetime - start_datetime)) AS INT) > 0 THEN Cast(Datepart("ss",(end_datetime - start_datetime)) AS VARCHAR) + ' sec ' ELSE ' ' END ELSE CASE WHEN end_datetime = start_datetime THEN '< 1 sec' ELSE CASE WHEN ((Cast(Datediff(mi,start_datetime,Getdate()) AS INT) <= 240) OR ((SELECT Count(* ) FROM MASTER.dbo.sysprocesses a(nolock) INNER JOIN gcsdwdb.dbo.update_log b(nolock) ON a.program_name = b.program_name WHERE a.program_name = update_log.program_name AND (Abs(Datediff(n,b.start_datetime,a.login_time))) < 1) > 0)) THEN 'Running ' + Cast(Datediff(mi,start_datetime,Getdate()) AS VARCHAR) + ' min' ELSE ' ' END END END "Elapsed Time" /* ,end_datetime "End Time (UTC/GMT)" ,datepart("hh" , (end_datetime - start_datetime)) "Hr" ,datepart("mi" ,(end_datetime - start_datetime)) "Mins" ,datepart("ss" ,(end_datetime - start_datetime)) "Sec" ,datepart("ms" ,(end_datetime - start_datetime)) "mSecs" ,datepart("dw" ,start_datetime) "dp" ,case when datepart("dw" ,start_datetime) = 6 then ' Fri' when datepart("dw" ,start_datetime) = 5 then ' Thu' else '1' end */ ,totalrows "Total Rows" ,inserted "Rows Inserted" ,updated "Rows Updated" /* ,success_code "succ" ,exit_code "exit" */ FROM update_log WHERE start_datetime >= '5/29/2009 16:15' ORDER BY start_datetime DESC