Monday, July 9, 2018

SQL coding Standards

http://dhs.pa.gov/cs/groups/webcontent/documents/document/p_032218.pdf

MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 1 of 37 COMMONWEALTH OF PENNSYLVANIA DEPARTMENT’S OF HUMAN SERVICES, INSURANCE, AND AGING INFORMATION TECHNOLOGY STANDARD Name Of Standard: MS SQL Server Number: 2012 / 2014 Naming and Coding Standard STD-DMS009 Domain: Category: Data Date Issued: Issued By Direction Of: Date Revised: 9/15/2016 Clifton Van Scyoc, Dir of Division of Technical Engineering Abstract: The purpose of this document is to detail and give examples of Microsoft Structured Query Language (MS SQL) development standards followed at the Departments of Human Services (DHS), Insurance (PID) and Aging (PDA). General: Coding standards are conventions and methods developers follow when developing, editing or maintaining program code. Better programming style, developer understanding, readability and reduced application development time are the results of following coding standards. Database Modeling Environment Computer Associates (CA) ERwin Data Modeler is the standard tool for designing and modeling SQL Server 2008/2012/2014 databases. All models are reviewed by the Database Management Section. All completed models are stored in the Microsoft Visual Studio Team Foundation Server. Database Data Definition Environment Microsoft SQL Server Management Studio is the standard tool to use for the execution and modification of Data Definition Language (DDL) for the development of SQL Server 2008/2012/2014 databases. The general process is: MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 2 of 37 1. Initially generate a DDL from ERwin using forward engineering, or if required, create DDL statements manually within SQL Server Management Studio. 2. Execute the DDL within SQL Server Management Studio and, if necessary, edit and/or tune the statements using the Management Studio environment. 3. Reverse engineer the database back into ERwin to keep the database and data model synchronized. Store revised data models and all DDL scripts in Microsoft Visual Studio Team Foundation Server. Store the DDL scripts in a consistent manner under the project folder in Team Foundation Server. Database Programming Environment Use SQL Server 2008/2012/2014 Management Studio to code and test stored procedures and triggers. Prototype every process using Transact-SQL (T-SQL) within SQL Server Management Studio prior to creating a new stored procedure, view, function or trigger. This results in ease of debugging. Use Execution Plans Estimated Execution plans need to be used while developing T-SQL. Actual Execution plans need to be included in the migration packet. Use Database Engine Tuning Advisor SQL Server DBA’s and analysts use this tool to determine if additional keys or indexes may be required. Creation of the additional objects are determined and executed by database administrators and analysts. General Import/Export File Rules All files imported to and exported from SQL Server 2008/2012/2014 preferred delimited. Although commas, hyphens, semicolons and other characters can be used to delimit files, only a vertical bar (| or ‘pipe’) is allowed, no exceptions. Using other characters introduces the possibility of that character being embedded as valid data within a text or large variable character column. A vertical bar is less likely to be valid data. Commenting Guidelines These rules apply in general to all source files. Object Header Usage Include object headers in every source code file. Object Maintenance Documentation MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 3 of 37 Include object maintenance documentation in every source code file. Keep this documentation current on all revisions after moving any given source file into production. Before initial migration into production, revision information is not required. Comment Quality Comments must contain a description of the process the SQL module (source file), procedure, or trigger accomplishes. Write the description in clear, concise, non-colloquial English, using business terms to describe the processes. Do not use comments such as: -- -- Declare the Customer Name Variable -- DECLARE @CustomerName AS VARCHAR(32) Describe the purpose of the process and how it works, in non-technical terms. This is important because most developers can read the SQL and see line-by-line what it does mechanically, but may not be able to easily grasp the purpose (business logic) behind the code. Write comments to aid the reader of the code. Assume that the reader is not well versed in Transact-SQL and try always to describe the “how” and “why” of the process clearly. Comment Quantity More comments are better than using fewer comments. Remember that the code is reviewed first, then, over time (perhaps after many years), require revisions and enhancements. Providing adequate comments allows the database administrator, developer, and the developer’s peers to quickly understand the logic and perform necessary revisions, and so forth. Standard Object Header Every object contains an object header. An object header contains the database name, object name, creation date, author, a brief description of the object, parameters passed, returns, calling mechanism, tables and aliases used in code, other procedures called, DPSR #, notes, and any special comments and warnings. Module headers remain open on the right-hand side. Documentation for Object Maintenance This section describes how to document changes in the Transact-SQL source code. The method involves using a maintenance documentation heading and comments within the source code. A common developer signature provides these together. Object Maintenance Documentation Immediately following the object header there is a skeletal maintenance block. Use this skeletal block as a template for maintenance done to the object code. Copy, paste, and fill in this block when you alter the object code. The block copy marks are on the lines with the equal signs. Include the lines with the block copy marks. MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 4 of 37 Make the insertion of the copied block directly after the skeleton block. Thus, the history is recorded from earliest to latest. Example of OBJECT HEADER AND MAINTENANCE DOCUMENTATION /****************************************************************************** * DATABASE: OMAPINTERNET * PROCEDURE NAME: usp_SelectAllResults * DATE: 04/03/2009 * AUTHOR: Homer Simpson * PROCEDURE DESC: This proc returns all the results for a specific NDC, * ShortName or market basket code or their combination * WorkOrder# 13798 ************************************************************************** * DATE: Developer Change ---------- ---------------- ------------------------------------------ 08/01/2013 Joe Developer Add Indicator **************************************************************************/ Minor Line-level Commenting Do not put comments on the same line as the code. Examples of this illegal style follow: DECLARE @IsNew AS Integer -– Is New Flag DECLARE @Firstname AS VARCHAR(32) -- First Name Field Insert all comments for a particular section of code before the code block, with one blank comment line before and after the comment. An example follows: -- -- Declare the local working variables -- DECLARE @IsNew AS Integer DECLARE @Firstname AS VARCHAR(32) -- -- Return identity value. -- SET @IDENTITY_CONTACT = CAST(SCOPE_IDENTITY() AS INT) SELECT @IDENTITY_CONTACT Formatting Guidelines Font Style, Size, and Capitalization MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 5 of 37 Font Style and Size Write all SQL code in 10 point Courier New font. Capitalization Please make sure that Transact-SQL keywords are opposite case from variables, field names, and object names when coding SQL statements,. Tab Stops Set tabs to either four spaces or eight spaces (default). Line Length Do not write a Transact-SQL line that exceeds 132 characters in length, unless there is no other way to properly format the source. Line Count—needs moved to store proc section. Do not write procedures that exceed four pages in length excluding comments, headers, and maintenance log, without written justification to the data base administrators. Exceptions to rule are procedures used in conversion or loads of data. Code exceeding this limit should be looked at closer and possibly split into smaller stored procedures or modularized. Star “*” Usage Do not use the star symbol “*” in a Transact-SQL statement, as this is very inefficient. This is prohibited .In all instances, include the appropriate fields in the statements where needed. An example of the wrong way to write a Transact-SQL statement follows: SELECT * FROM T_VENDOR If you must return a count, select one field in the table or use 1. Example below. Select count (1) from T_VENDOR Examples of the right way to write a Transact-SQL statement follows. Specify each field as in the examples: SELECT Field1, Field2, Field3, MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 6 of 37 Field4 FROM TABLE_A WHERE nbr_vt = @nbr_vt_recent SELECT PMT.IDN_APPLN_PMT, PMT.AMT_BNFT FROM T_APPLN_PMT PMT INNER JOIN T_VOU_TRNSMTL VT ON VT.IDN_TRNSMTL_VOU = PMT.IDN_TRNSMTL_VOU Compound Statements Compound statements are those that are encased within a BEGIN…END structure. Formatting rules for this structure are as follows: 1. The BEGIN statement aligns directly under the statement above. 2. The END statement is aligned in the same position as its corresponding BEGIN statement. 3. Within the BEGIN…END structure, statements are indented and should be in alignment. IF…ELSE Statement Blocking Treat all “IF” statements (and block “ifs”) as if they were compound statements using the BEGIN…END structure. No exceptions are permitted. An example follows: IF @@ROWCOUNT < 1 BEGIN RETURN -1 END ELSE BEGIN SELECT @RowReturned = @@ROWCOUNT RETURN 0 END Multi-line Parameter Style When you must expand a statement to more than one line (because it exceeds the 80- character line limit standard), use the style in the following example, for consistent readability. It is best to apply this style even when you do not exceed the 80-character limit (though this rule is not strictly enforced). EXECUTE usp_MyStoredProcedure MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 7 of 37 @MyParameter1, @MyParameter2, @MyParameter3 OUTPUT, @MyParameter4 OUTPUT Indenting and Formatting SQL Statements The styling presented in this standard provides for a more consistent look to all stored procedures and triggers. The guidelines presented here (by example) apply to all TransactSQL statements. Use of white space is highly recommended. Example of Select Statement SELECT DISTINCT t1.nbr_rcpt, t2.nam_rcpt FROM T_TABLE1 t1, T_TABLE2 t2 WHERE t1.nbr_value = t2.nbr_value AND t1.cde_value = @ParmKeyVal AND (t1.nbr_value < 1 OR t1.nbr_value > 99) ORDER BY t2.nam_rcpt DESC From the example, it can be seen that: 1. Individual elements are placed in separate lines 2. Elements are indented one tab stop 3. Keywords are to the left whenever possible 4. If the length of the keyword or keywords (ex: “SELECT DISTINCT” and “ORDER BY”) equals or exceeds the tab stop setting (8), the parameter is placed on the subsequent line at the proper indent position 5. Parentheses are used to distinguish logical blocks and are indented at the same level as any other parameter. Other examples follow: Example of Select Statement: SELECT DISTINCT t1.nbr_rcpt, t2.nam_rcpt FROM T_TABLE1 t1,T_TABLE2 t2 MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 8 of 37 WHERE t1.cde_value = t2.cde_value AND t1.nbr_rcpt = @ParmKeyVal AND (t1.cde_value < 1 OR t1.cde_value > 99) ORDER BY t2.nam_rcpt DESC Examples of Insert Statements INSERT INTO T_VENDOR ( nam_vendor, cde_active, dte_crtd, idn_user_crtd ) VALUES ( @Name, @Active, GETDATE(), @ModifiedUser ) Example of Update Statement UPDATE T_VENDOR SET nam_vendor = @Name, cde_active = @Active, dte_crtd = GETDATE(), idn_user_crtd = @ModifiedUser WHERE nbr_vendor = @VendorID Example of Delete Statement DELETE FROM T_VENDOR WHERE nbr_vendor = @VendorID Example of Case Statement MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 9 of 37 CASE @myfield WHEN 'A' THEN 'ABC ' WHEN 'B' THEN 'BCD ' WHEN 'C' THEN 'CDE ' ELSE 'JKL' END Naming Conventions For table and column names please reference the Data Administration Standards on the Data Domain page under Business and Technical Standards on the BIS web site. Table Naming All table names follow the current BIS naming conventions and are prefaced with a T_. Example: T_FIPS_CODE Column Naming All column names follow the current DHS naming conventions. View Naming All view names consist of the prefix VW_ followed by business function they perform or business rule they enforce. Example: VW_SEL_T_FIPS_CODE Variable Formats All variable names are defined in a consistent manner across all the programs. To ensure consistency parameters are descriptive and define correctly according to their usage. @p_IDN_RECON integer, @p_IDN_ALJ integer, @p_HONORABLE varchar(20)= NULL, Parameters can be set to NULL. Instead of using an IF block to check for NULL parameters, NULLS are checked like the example below. Second example is to check a range. (B.CDE_PARTY_RQNG = @p_CDE_PARTY_RQNG OR @p_CDE_PARTY_RQNG IS NULL) MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 10 of 37 ((DTE_FAA_BHA >= @p_DTE_FAA_BHA_FROM AND DTE_FAA_BHA <= @p_DTE_FAA_BHA_TO) OR (@p_DTE_FAA_BHA_FROM Is NUll AND @p_DTE_FAA_BHA_TO Is NUll)) If you have to use a dynamic order by (sort results) pass in the field to sort and the sort order. @p_field_order_sort varchar(50)=null, @p_order_sort varchar(4)=null IF @p_order_sort = 'ASC' BEGIN SELECT m.ProviderName as NAM_PROVR, m.NAM_BUSNS_MP, m.NAM_PROVR_ALT, FROM TBLMEDICHECK m WHERE m.Providername = @p_nam_provr ORDER BY CASE @p_field_order_sort WHEN 'NAM_PROVR' THEN m.ProviderName WHEN 'NAM_BUSNS_MP' THEN m.NAM_BUSNS_MP WHEN 'NAM_PROVR_ALT' THEN NAM_PROVR_ALT END ASC; END ELSE BEGIN SELECT m.ProviderName as NAM_PROVR, m.NAM_BUSNS_MP, m.NAM_PROVR_ALT, FROM TBLMEDICHECK m WHERE m.Providername = @p_nam_provr ORDER BY CASE @p_field_order_sort WHEN 'NAM_PROVR' THEN m.ProviderName WHEN 'NAM_BUSNS_MP' THEN m.NAM_BUSNS_MP WHEN 'NAM_PROVR_ALT' THEN NAM_PROVR_ALT END DESC; END Stored Procedures MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 11 of 37 When coding enterprise applications, the use of stored procedures to separate application logic from database code has been found beneficial. Stored procedures are used for any data access (SELECT) or manipulation (INSERT, DELETE, UPDATE). The advantages include:  Ease of Maintenance – When supporting database structure or application logic changes, the DML is easily accessible directly from the database, can be easily scanned using SQL, and eliminates the need to interrogate each COM or .NET object when searching for a particular database reference. As such, it is recommended that all web-based applications use stored procedures for the majority, if not all, database access.  Enhanced Performance – Stored procedures run directly on the database server, which is optimally tuned to perform such operations.  Reusability – Stored procedures can be called from multiple applications, thereby reducing the time required to design, code and test commonly used application functions. Stored procedures are named according to the business function they perform or business rule they enforce. The name should include a prefix of USP and a business description of the action performed. The name is appropriately abbreviated with items found in the standard abbreviation list. An example of a procedure name is USP_ADD_NEW_T_INDIV. As the name implies, this procedure adds a new row to the T_INDIV table. All stored procedures, begin with one of the following: USP_SELECT USP_UPDATE USP_INSERT USP_DELETE Stored Procedures performs only one function. This means one insert, one update or one delete statement per stored procedure. An “if” clause determining whether an insert or update should be performed, is acceptable. See the DBA team if there are any questions. Multiple update\delete\insert statements can cause locking\blocking, orphan records and unhandled transactions. Do not write store procedures that exceed four pages in length excluding comments, headers, and maintenance log, without written justification to the data base administrators. Exceptions to the rule are procedures used in conversion or loads of data. Analyze code exceeding this limit and split into smaller stored procedures or modularize. For a SELECT, items in yellow are standard. The comment block is simple and contains a brief audit listing of changes that go to production; not a running summary of changes during development. Error Trapping is highly recommended with the Enterprise libraries, because if MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 12 of 37 you have an error, the first thing we ask is what the error log says. Please also list the fields. No SELECT * is allowed. Also, white space for readability is also highly desirable. Example USE [RECON] GO /****** Object: StoredProcedure [RECONSchema].[USP_SELECT_BACK_END_RECON] Script Date: 09/10/2015 09:23:38 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /************************************************************************** -- Author: George Washington -- Create date: 07/04/2012 -- Description: get all fields for the Back End Screen from the RECON table ***************************************************************************** DATE: Developer Change ---------- ---------------- ------------------------------------------ 01/05/2012 George Washington New 03/25/2013 Tom Jefferson Added DTE_CLER_RTND **************************************************************************/ ALTER PROCEDURE [RECONSchema].[USP_SELECT_BACK_END_RECON] ( @IDN_RECONS Integer ) AS BEGIN SET NOCOUNT ON; BEGIN TRY SELECT [IDN_RECONS] ,[TXT_CASE_NUM] ,[TXT_APPEAL_NUM] ,[TXT_BHA_FILE_NUM] ,[DTE_RCVD_BHA] ,[DTE_MLNG_ORDER_FINAL_SCTRY] ,[DTE_CREATN] ,[NAM_BY_CRTD] ,[DTE_MODFD] ,[NAM_BY_MODFD] FROM [RECON].[dbo].[T_RECON] where IDN_RECONS = @IDN_RECONS END TRY BEGIN CATCH SELECT MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 13 of 37 ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage; END CATCH END For an UPDATE, items in yellow are standard. The comment block is simple and contains a brief audit listing of changes that go to production; not a running summary of changes during development. Error Trapping is highly recommended with the Enterprise libraries, because if you have an error, the first question is what the error log says. Please also list the fields. No SELECT * is allowed. Also, white space for readability is also highly desirable. Example USE [StateFacilityTrackingSystem] GO /****** Object: StoredProcedure [PTS].[USP_UPDATE_BSU] Script Date: 09/10/2015 09:52:53 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /************************************************************************** Database: StateFacilityTrackingSystem Procedure Name: USP_UPDATE_BSU Date: 10/21/2014 Author: Harry Potter Procedure Desc: This procedure creates new bsu for existing admission. Parameters: see below ************************************************************************** DATE: Developer Change ---------- ---------------- ------------------------------------------ 02/02/2014 PETER PAN New **************************************************************************/ ALTER PROCEDURE [PTS].[USP_UPDATE_BSU] @IDN_PTN_ADMSN AS INT=0, @IDN_BSU AS INT, @PNT_BSU_CODE AS VARCHAR(7), @PNT_BSU_NUMBER AS VARCHAR(7), @PNT_BSU_EFF_DTE AS DATETIME, @CWOPA_ID AS VARCHAR(12)=NULL AS SET NOCOUNT ON; BEGIN TRY MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 14 of 37 UPDATE PTS.T_PNT_BSU SET CDE_BSU=@PNT_BSU_CODE, DTE_EFFV_BSU=@PNT_BSU_EFF_DTE, NBR_CASE_BSU=@PNT_BSU_NUMBER, DTE_UPDTD_RECORD=GETDATE(), IDN_USER_UPDTD_RECORD=@CWOPA_ID WHERE IDN_BSU_PNT=@IDN_BSU END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage; END CATCH An INSERT/UPDATE is also acceptable as long as you are doing either an INSERT or an UPDATE – not both! This is acceptable: IF @P_IDN_USER = ‘cwopa\user’ BEGIN UPDATE PIOS.dbo.T_CW_ASGMT SET IDN_CW = @P_IDN_CW, DTE_ASGMT_CASE = @P_DTE_ASGMT_CASE, IDN_USER_CHANGE_LAST = @P_IDN_USER, DTE_RECORD_CHANGE_LAST = GetDate() WHERE IDN_ASGMT_CW = @P_IDN_ASGMT_CW END ELSE BEGIN INSERT INTO PIOS.dbo.T_CW_ASGMT (IDN_CW ,IDN_STATUS ,DTE_CHANGE_STATUS) VALUES (@P_IDN_CW ,@P_IDN_STATUS ,NULL) END MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 15 of 37 THIS IS NOT ACCEPTABLE: An Insert or UPDATE stored procedure performs one UPDATE or INSERT, and rarely more than that. Check parameters in your .NET code and then an INSERT or UPDATE is called. A Transaction can be set in the .NET code to either commit all INSERTS or none of them if the code has multiple INSERTS/UPDATES. In this case a collection in .NET can be used and the same INSERT could be called as many times as needed as you loop through the collection. USE [RECON] GO /****** Object: StoredProcedure [PTS].[USP_INSERT_DIAGNOSTICS] Script Date: 09/10/2015 10:18:52 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /********************************************************************************** ** Database : RECON Procedure Name : USP_INSERT_DIAGNOSTICS Date : 10/14/2014 Author : Tom Sawyer Procedure Desc : This procedure inserts records into Diagnostics table. Parameters: see below *********************************************************************************** * DATE: Developer Change ---------- ---------------- ------------------------------------------ 10/14/2014 Will Robinson New *********************************************************************************** */ ALTER PROCEDURE [PTS].[USP_INSERT_DIAGNOSTICS] @idn_pnt AS INT, @idn_admsn_pnt AS INT, @ambulationCode AS VARCHAR(1), @psych_Code_1 AS VARCHAR(7) , @psych_Code_Date_1 AS DATETIME, @psych_Code_NBR_Order_1 AS VARCHAR(1), @psych_Code_2 AS VARCHAR(7), @psych_Code_Date_2 AS DATETIME, @psych_Code_NBR_Order_2 AS VARCHAR(1), @psych_Code_3 AS VARCHAR(7), @psych_Code_Date_3 AS DATETIME, @psych_Code_NBR_Order_3 AS VARCHAR(1), @psych_Code_4 AS VARCHAR(7), @psych_Code_Date_4 AS DATETIME, @psych_Code_NBR_Order_4 AS VARCHAR(1), @psych_Code_5 AS VARCHAR(7), MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 16 of 37 @psych_Code_Date_5 AS DATETIME, @psych_Code_NBR_Order_5 AS VARCHAR(1), @psych_Code_6 AS VARCHAR(7), @psych_Code_Date_6 AS DATETIME, @psych_Code_NBR_Order_6 AS VARCHAR(1), @psych_Code_7 AS VARCHAR(7), @psych_Code_Date_7 AS DATETIME, @psych_Code_NBR_Order_7 AS VARCHAR(1), @substance_Code_1 AS VARCHAR(7), @substance_Code_Date_1 AS DATETIME, @substance_Code_NBR_Order_1 AS VARCHAR(1), @substance_Code_2 AS VARCHAR(7), @substance_Code_Date_2 AS DATETIME, @substance_Code_NBR_Order_2 AS VARCHAR(1), @substance_Code_3 AS VARCHAR(7), @substance_Code_Date_3 AS DATETIME, @CWOPA_ID AS VARCHAR(12) AS SET NOCOUNT ON; BEGIN TRY BEGIN TRANSACTION; INSERT INTO PTS.T_PNT_AMBTN ( CDE_AMBTN, IDN_ADMSN_PNT, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD ) VALUES ( @ambulationCode, @idn_admsn_pnt, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID ) if @psych_Code_1 IS NOT NULL and LTRIM(RTRIM(@psych_Code_1)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 17 of 37 IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @psych_Code_Date_1, 0, @psych_Code_NBR_Order_1, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @psych_Code_1, 1 ) end if @psych_Code_2 IS NOT NULL and LTRIM(RTRIM(@psych_Code_2)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @psych_Code_Date_2, 0, @psych_Code_NBR_Order_2, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @psych_Code_2, 1 ) end if @psych_Code_3 IS NOT NULL and LTRIM(RTRIM(@psych_Code_3)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 18 of 37 DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @psych_Code_Date_3, 0, @psych_Code_NBR_Order_3, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @psych_Code_3, 1 ) end if @psych_Code_4 IS NOT NULL and LTRIM(RTRIM(@psych_Code_4)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @psych_Code_Date_4, 0, @psych_Code_NBR_Order_4, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @psych_Code_4, 1 ) end if @psych_Code_5 IS NOT NULL and LTRIM(RTRIM(@psych_Code_5)) <> '' begin MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 19 of 37 INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @psych_Code_Date_5, 0, @psych_Code_NBR_Order_5, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @psych_Code_5, 1 ) end if @psych_Code_6 IS NOT NULL and LTRIM(RTRIM(@psych_Code_6)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @psych_Code_Date_6, 0, @psych_Code_NBR_Order_6, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @psych_Code_6, 1 ) MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 20 of 37 end if @psych_Code_7 IS NOT NULL and LTRIM(RTRIM(@psych_Code_7)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @psych_Code_Date_7, 0, @psych_Code_NBR_Order_7, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @psych_Code_7, 1 ) end if @substance_Code_1 IS NOT NULL and LTRIM(RTRIM(@substance_Code_1)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @substance_Code_Date_1, 0, @substance_Code_NBR_Order_1, GETDATE(), @CWOPA_ID, MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 21 of 37 GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @substance_Code_1, 2 ) end if @substance_Code_2 IS NOT NULL and LTRIM(RTRIM(@substance_Code_2)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @substance_Code_Date_2, 0, @substance_Code_NBR_Order_2, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @substance_Code_2, 2 ) end if @substance_Code_3 IS NOT NULL and LTRIM(RTRIM(@substance_Code_3)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 22 of 37 VALUES ( @substance_Code_Date_3, 0, @substance_Code_NBR_Order_3, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @substance_Code_3, 2 ) end if @substance_Code_4 IS NOT NULL and LTRIM(RTRIM(@substance_Code_4)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @substance_Code_Date_4, 0, @substance_Code_NBR_Order_4, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @substance_Code_4, 2 ) end if @medical_Code_1 IS NOT NULL and LTRIM(RTRIM(@medical_Code_1)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 23 of 37 DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @medical_Code_Date_1, 0, @medical_Code_NBR_Order_1, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @medical_Code_1, 3 ) end if @medical_Code_2 IS NOT NULL and LTRIM(RTRIM(@medical_Code_2)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @medical_Code_Date_2, 0, @medical_Code_NBR_Order_2, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @medical_Code_2, 3 ) end if @medical_Code_3 IS NOT NULL and LTRIM(RTRIM(@medical_Code_3)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 24 of 37 DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @medical_Code_Date_3, 0, @medical_Code_NBR_Order_3, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @medical_Code_3, 3 ) end if @medical_Code_4 IS NOT NULL and LTRIM(RTRIM(@medical_Code_4)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @medical_Code_Date_4, 0, @medical_Code_NBR_Order_4, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @medical_Code_4, 3 ) end MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 25 of 37 if @medical_Code_5 IS NOT NULL and LTRIM(RTRIM(@medical_Code_5)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @medical_Code_Date_5, 0, @medical_Code_NBR_Order_5, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @medical_Code_5, 3 ) end if @medical_Code_6 IS NOT NULL and LTRIM(RTRIM(@medical_Code_6)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @medical_Code_Date_6, 0, @medical_Code_NBR_Order_6, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 26 of 37 @medical_Code_6, 3 ) end if @medical_Code_7 IS NOT NULL and LTRIM(RTRIM(@medical_Code_7)) <> '' begin INSERT INTO PTS.T_PNT_DGNSTC ( DTE_EFFV_DGNSTC, IND_RECORD_ARCD, NBR_ORDER_DGNSTC, DTE_CREATN_RECORD, IDN_USER_CREATN_RECORD, DTE_UPDTD_RECORD, IDN_USER_UPDTD_RECORD, IDN_ADMSN_PNT, IDN_DX, IDN_TYPE_DGNSTC ) VALUES ( @medical_Code_Date_7, 0, @medical_Code_NBR_Order_7, GETDATE(), @CWOPA_ID, GETDATE(), @CWOPA_ID, @idn_admsn_pnt, @medical_Code_7, 3 ) end COMMIT; END TRY BEGIN CATCH ROLLBACK; SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage; END CATCH Triggers Triggers are to be avoided as they have the potential to cause execute multiple SQL statements without other developer knowledge. MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 27 of 37 Constraints Planning and creating tables requires identifying how to enforce integrity of the data stored within the columns of the tables. MS SQL Server has the following constraints to enforce integrity: Primary Key Constraints are columns or a column that uniquely identifies a row within a table. All tables should have a primary key and composite primary keys should be avoided. Primary keys should be named PK_tablename_columnname. For most of your OLTP tables, an identity column is the primary key. Example: PK_T_ADDRESS_IDN_ADDR. Foreign Key Constraints are columns or a column that is used to enforce a relation between information in two tables. A link is defined between the two tables when a primary key is referenced by a column or columns in another table. The reference becomes a foreign key in the second table. Foreign keys are named as FK_foreignkeytable_primarykeytable_columnname. Example: FK_T_NAME_T_ADDRESS_IDN_ADDR. Indexes An index is an on-disk structure associated with a table or a view that speeds retrieval of rows from the table or the view. An index contains keys built from one or more columns in the table or the view. These keys are stored in a structure (B-tree) that enables SQL Server to find the row or rows associated with the key values quickly and efficiently. A table or view can contain the following types of indexes: • Clustered o Clustered indexes sort and store the data rows in the table or view based on their key values. These are the columns included in the index definition. There can be only one clustered index per table, because the data rows themselves can be sorted in only one order. o The only time the data rows in a table are stored in sorted order is when the table contains a clustered index. When a table has a clustered index, the table is called a clustered table. If a table has no clustered index, its data rows are stored in an unordered structure called a heap. • Nonclustered o Nonclustered indexes have a structure separate from the data rows. A nonclustered index contains the nonclustered index key values and each key value entry has a pointer to the data row that contains the key value. MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 28 of 37 o The pointer from an index row in a nonclustered index to a data row is called a row locator. The structure of the row locator depends on whether the data pages are stored in a heap or a clustered table. For a heap, a row locator is a pointer to the row. For a clustered table, the row locator is the clustered index key. Indexes should be named IDX_ tablename_columnname(s). Example: IDX_T_ADDR_STATE_STATE Default Definitions Default Definitions are predefined values created on columns within a table. The default value is used when inserting a new row in a table and a particular column in the insert statement does not have a value. For example you may have a default of all 99999999 that you may want to set up as a default end date. The default has a prefix of D_ followed by a description of what the default does. Example: DF_OPEN_DATE User Defined Functions User defined functions can be created in SQL Server Management Studio to perform actions such as complicated calculations or character string manipulation. User defined functions are created and used for actions repeated within an application. An example is adding dashes to social security number. This user defined function could be created and used any time a correctly formatted social security number is required. User defined functions are named UDF_function. Example: UDF_FORMATSSN Transaction and Error Handling Try…Catch Try…Catch, is the preferred error handling method in SQL Server. This method is used in place of the old RAISEERROR. Errors in Transact-SQL code can be processed by using a TRY…CATCH construct similar to the exception-handling feature of the Microsoft .NET and Microsoft Visual C# languages. A TRY…CATCH construct consists of two parts: a TRY block and a CATCH block. When an error condition is detected in a Transact-SQL statement that is inside a TRY block, control is passed to a CATCH block where the error can be processed. MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 29 of 37 After the CATCH block handles the exception, control is then transferred to the first TransactSQL statement that follows the END CATCH statement. If the END CATCH statement is the last statement in a stored procedure or trigger, control is returned to the code that invoked the stored procedure or trigger. Transact-SQL statements in the TRY block following the statement that generates an error is not executed. If there are no errors inside the TRY block, control passes to the statement immediately after the associated END CATCH statement. If the END CATCH statement is the last statement in a stored procedure or trigger, control is passed to the statement that invoked the stored procedure or trigger. A TRY block starts with the BEGIN TRY statement and ends with the END TRY statement. One or more Transact-SQL statements can be specified between the BEGIN TRY and END TRY statements. A TRY block must be followed immediately by a CATCH block. A CATCH block starts with the BEGIN CATCH statement and ends with the END CATCH statement. In Transact-SQL, each TRY block is associated with only one CATCH block. Working with TRY…CATCH When using the TRY…CATCH construct, consider the following guidelines and suggestions: Each TRY…CATCH construct must be inside a single batch, stored procedure, or trigger. For example, you cannot place a TRY block in one batch and the associated CATCH block in another batch. The following script would generate an error: BEGIN TRY SELECT IDN_AGENCY, NAM_AGENCY FROM dbo.T_AGENCY ORDER BY NAM_AGENCY END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage; END CATCH Transact-SQL Restrictions Following is SQL Server functionality that is not used when developing procedures or triggers. MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 30 of 37 Cursors Cursors are not allowed. Looping within Stored Procedures. Looping within stored procedures is PROHIBITED. Looping is only performed in developer code and not in SQL stored procedures. An infinite loop can bring down SQL Server. THIS IS NOT ACCEPTABLE! WHILE len(@IDN_USER) > 0 BEGIN SET @ID_USER =LEFT(@IDN_USER, charindex(',', @IDN_USER+',')-1) INSERT INTO dbo.T_COURSE_INSTRR (IDN_OFFNG_COURSE, IDN_USER) VALUES (@IDN_COURSE_OFFRNG, @IDN_USER) END Use of “*=” and “=*” and SQL JOINS- stopping point Do not use of the “*=” and ”=*” join operators in the WHERE clause. Use instead the JOIN keyword in the FROM clause. Microsoft does not recommend the use of “*=” and ”=*” and may not provide support for these in future releases of MS SQL Server. Using this syntax for joins is discouraged (by Microsoft) because of the potential for ambiguous interpretation and because it is nonstandard. Be sure to use the join syntax. Instead of using where a = b and b = c, for example, use inner join on a = b, etc. Use left and right outer joins as well as UNION ALLS sparingly. Pick the join order carefully. The majority of outer joins can successfully be rewritten as inner joins with tremendous performance improvements. Use of SELECT INTO Do not use the SELECT INTO clause to create a table on the fly. Instead, create your table before the SELECT statement and use the INSERT statement followed by the appropriate SELECT. Usage of Column Prefixes It is generally recommended to use prefixes for columns appearing in the SELECT list. This is a coding best practice that leads to more maintainable applications. As an example, it is preferred to have: SELECT a.au_id, a.au_lname FROM dbo.authors a Over this: SELECT au_id, au_lname FROM dbo.authors Database SQL Options MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 31 of 37 Database SQL Options should be configured as recommended to remove deprecated behaviors, be ANSI compliant, and be able to leverage the full feature set (indexed views and indexes on computed columns). The following SQL options should be checked to see if they are configured properly as per Microsoft SQL Options control ANSI compliance options. The following database SQL Options should be ON: • ANSI_NULLS • ANSI_PADDING • ANSI_WARNINGS • ARITHABORT • CONCAT_NULL_YIELDS_NULL • QUOTED_IDENTIFIERS The following should be OFF: • NUMERIC_ROUNDABOUT Use of Defaults and Rules Database Administrators check stored procedures, functions, views and triggers for existence of defaults and rules. These objects have been deprecated in favor of CHECK constraints and are not supported in future releases of SQL Server. Null Comparisons Database Administrators check stored procedures, views, functions and triggers to flag the use of equality and inequality comparisons involving a NULL constant. These comparisons are undefined when ANSI_NULLS option is set to ON. It is recommended to set ANSI_NULLS to ON and use the IS keyword to compare against NULL constants. In a future version of SQL Server, ANSI_NULLS will always be ON and any applications that explicitly set the option to OFF will generate an error. Avoid using this feature in new development work, and plan to modify applications that currently use this feature. String = Expression Aliasing Database Administrators check stored procedures, functions, views and triggers for use of column aliases where the name of the expression uses a string value. It is recommended to use quoted identifiers instead. String aliases are not supported in future releases of SQL Server. As an example, the following syntax is not recommended: SELECT 'alias_for_col'=au_id+au_id FROM dbo.authors Recommended alternatives are: MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 32 of 37 SELECT au_id+au_id as "alias_for_col" FROM dbo.authors SELECT au_id+au_id as alias_for_col FROM dbo.authors SELECT au_id+au_id as [alias_for_col] FROM dbo.authors Primary Keys Database Administrators check all user databases to ensure that all tables have defined either a primary key or have a column with a Unique Constraint defined. Tables without a Primary Key defined or a column with a unique constraint defined will not be approved. Foreign Keys Database Administrators check all user databases to ensure that proper foreign key/primary key relationships are created when needed. Foreign keys are also defined as indexes. Order by Clause with Ordinals Database Administrators check stored procedures, functions, views and triggers for use of ORDER BY clause specifying ordinal column numbers as sort columns. As an example, the following syntax is not allowed: SELECT au_id FROM dbo.authors ORDER BY 2, 1 The use of ordinal column numbers is not be allowed. Schema Usage Use Schema Usage only as needed; otherwise, the default schema ‘dbo’, is used. Database Administrators check stored procedures, functions, views and triggers for use of schema qualified names when referencing tables and views. Unless specified otherwise, all Transact-SQL references to the name of a database object can be a four-part name in the form: [ server_name.[database_name].[schema_name]. | database_name.[schema_name]. | schema_name. ] ] When referencing a specific object, it is not necessary to specify the server, database, and owner (schema) for SQL Server to identify the object. However, it is recommended that at least the schema name be specified to identify a table or view inside a stored procedure, function, view or trigger. When SQL Server looks up a table/view without a schema qualification, it first looks in the default schema and then looks in the 'dbo' schema. The default schema corresponds to the current user for adhoc batches, and corresponds to the schema of a stored procedure MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 33 of 37 when inside one. In either case, SQL Server incurs an additional runtime cost to verify schema binding of unqualified objects. Applications are more maintainable and may experience a slight performance improvement if object references are schema qualified. Top without Order By Database Administrators check stored procedures, functions, views and triggers for usages of TOP in queries without an ORDER BY clause. It is recommended to specify sort criteria when using TOP clause. Otherwise, the results produced are plan dependent and may lead to undesired behavior. Usually TOP without ORDER BY is meaningless. Avoid Stored Procedure Recompiles See next section. Production Adhoc Querying Real time adhoc reporting against the production database is not permitted. Microsoft Access is not allowed to connect to SQL. To do reporting as this causes table locks, performance degradation and creates a security risk. Hard coded SQL Hard coded SQL in web pages or applications is not permitted. Put T-SQL in stored procedures for security reasons, efficiency and ease in debugging. Dynamic SQL is not allowed. Performance Recommendations General Considerations Connections to the SQL Server database are to be brief. A connection is made, a process completed and the connection dropped. No persistent connections to SQL Server are allowed. Stored procedures perform one process and not a series of processes. It is better to create a stored procedure that performs an insert rather than a stored procedure that performs an insert, update and a delete. Executing multiple stored procedures is preferred over executing one, unwieldy, multi-task stored procedure. Stored Procedure Recompiles No stored procedures are to interleave Data Definition Language (DDL) and Data Manipulation Language (DML) operations. In other words, do all CREATE/DROP statements separate from SELECT and UPDATE statements. If data operations are mixed, MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 34 of 37 the SQL server must recompile procedures each time to determine the best plan to use for each new or dropped object. Therefore, coding all creates and drops together reduces the amount of stored procedure compiles. Avoid creating a temporary table in a control-of-flow statement such as an IF…ELSE or WHILE statement. Avoid using a DROP statement for temporary tables in stored procedures, because tables are automatically dropped when the procedure is completed. Specifying the owner of objects such as dbo.Tablename and dbo.Stored procedure name cuts down on recompiles. Temporary Tables Often procedure throughput can be dramatically improved by the use of temporary tables. Restructuring a Transact-SQL statement that involves lengthy and/or complicated joins to perform the same functionally by multiple actions against a temp table will improve performance. Please note: use a temporary table to manipulate small amounts of data, and if data exceeds 500 records add an index. Also if you have > 6 data changes in a temporary table consider using the option (keep plan) to avoid unnecessary recompiles. Table Variable Type The table variable type functions exactly like the temporary table, with the exception that all data is loaded directly in random access memory. Temporary Tables vs. Table Variable Database Administrators check stored procedures and triggers for usages of temporary tables that may be replaced by use of table variables. When a procedure creates a temporary table and has no CREATE INDEX issued on it, and it is dropped all in the same procedure, consider using table variables instead to potentially observe fewer recompilations. Note that if large data volumes are inserted in the temporary table it may still be preferred to use temporary tables over table variables due to parallel execution restrictions and statistics maintenance. Indexes Examine the performance of the statements within the procedure and the entire application to determine if an additional index will justify its overhead. Consider overall index usage all along the development path. Indexes, or lack of indexes, are the direct cause of poor performance 90% of the time. As per Microsoft’s suggestion, all tables that have more than 500 records are to have a clustered index, even if a field is created just to hold the index. Please note when setting an index, pay close attention to the fill factor for the given index. The fill factor is the amount space consumed by the index and more importantly the amount of space that will be kept free for expansion. For an example a 90% fill factor is 90% full with 10% left for expansion. For tables that do a high volume of inserts, updates, deletes consider a lower fill factor, or perhaps not having a clustered index at all. A clustered index slows down inserts but speed up selects. The developer determines what the best tradeoff is. MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 35 of 37 Ultimately, it is the responsibility of the developer coding the stored procedures and the SQL code to determine what the best indexes are and how they are used. Execution Plan When debugging and tuning a stored procedure, examine the execution plan for clues as to the performance of the procedure and how it may be improved. The reason for execution plan is to determine whether an index is required. In the example below, execution identifies a missing index that could improve performance. From this, one asks if another index should be created to avoid the scan. If yes, create an index and rerun. SQL Profiler/Database Engine Tuning Advisor Two valuable and necessary tools when tracking and or monitoring performance are SQL Profiler and Database Engine Tuning Advisor. Only the DBA has permissions to run these two tools. The DBA can analyze the output from these tools and give suggestions on what tables or objects have problems and can benefit from index creation. Programmatic Recommendations This section provides recommendations to developers for improving the reliability of procedures and triggers. Use SET NOCOUNT When developing procedures that return a result set and use intermediate processing, be sure to set the SET NOCOUNT ON option to prevent the generation of unwanted result set count information. Use the SET NOCOUNT OFF statement to restore result counting before executing a SELECT statement to return results. Stylistic Recommendations MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 36 of 37 This section provides recommendations to developers for improving the readability of procedures and triggers. Nesting IF statements Avoid, wherever possible, nesting IF statements. Use compound Boolean expressions instead. No more than 4 nested IF statements are allowed. SQL Server 2014 Integration Services SQL Server Data Tools for Visual Studio 2013 is required when performing extract, transform and load (ETL) processing. Data Tools replaces SQL Server Business Intelligence Development Studio and brings enhancements and improvements to creating and executing packages. Naming Packages The name of the SQL Server Integration Services package indicates the database the package belongs to as well as the purpose of the SSIS package. In a development environment, the developer testing the package may own the package but in all other environments SA (System Administrator) owns the package. The package may very well have the same name as the job. The difference between a job and a package is that a job is a scheduled package. A package on its own must be started manually. The package names can be mixed case for ease of readability. Example: CUSTOMERVendorExport SQL Server 2014 Reporting Services SQL Server 2014 Reporting Services (SSRS) is required when creating any reports for use at the DHS. Naming Reports The name of the SQL Server 2014Reporting Services object should indicate the database the report belongs to as well as the purpose of the SSRS package. The report names can be mixed case for ease of readability. Example: CUSTOMERNameAndAddresses Job Naming Standards A job consists of a series of SQL Statements executed as a transaction (as one complete unit). The name of a SQL SERVER job indicates the database to which the job belongs as well as the purpose of the job. The job name is the same name as the SSIS package. MS SQL Server 2012 2014 Naming and Coding Standard.docx Page 37 of 37 SA owns the job in all environments. All jobs need DBA approval prior to being scheduled to run. The job names are mixed case for ease of readability. Example: ACCOUNTINGImportDailyFiles Exemptions from this Standard: There will be no exemptions to this standard. Refresh Schedule: All standards and referenced documentation identified in this standard will be subject to review and possible revision annually or upon request by the DHS Information Technology Standards Team. References: Microsoft SQL Server 2008/2012/2014 Books On Line Standard Revision Log: Change Date Version Change Description Author and Organization 1.0 New document Kiley Milakovic 12/11/2007 1.1 SQL Server 2005 revisions Matt Leitzel 01/13/2011 1.2 SQL Server 2008 revisions Matt Leitzel 09/15/2016 1.3 SQL Server 2012/2014 revisions Steve Isleib and Michael Kraus

http://dhs.pa.gov/cs/groups/webcontent/documents/document/p_032218.pdf

SQL Server - Guidelines and Coding Standards complete List Download

https://blog.sqlauthority.com/2008/09/23/sql-server-coding-standards-guidelines-part-1/
  • Use “Pascal” notation for SQL server Objects Like Tables, Views, Stored Procedures. Also tables and views should have ending “s”.
Example:
UserDetails
Emails
  • If you have big subset of table group than it makes sense to give prefix for this table group. Prefix should be separated by _.
Example:
Page_ UserDetails
Page_ Emails
  • Use following naming convention for Stored Procedure. sp<Application Name>_[<group name >_]<action type><table name or logical instance> Where action is: Get, Delete, Update, Write, Archive, Insert… i.e. verb
Example:
spApplicationName_GetUserDetails
spApplicationName_UpdateEmails
  • Use following Naming pattern for triggers: TR_<TableName>_<action><description>
Example:
TR_Emails_LogEmailChanges
TR_UserDetails_UpdateUserName
  • Indexes : IX_<tablename>_<columns separated by_>
Example:
IX_UserDetails_UserID
  • Primary Key : PK_<tablename>
Example:
PK_UserDetails
PK_ Emails
  • Foreign Key : FK_<tablename_1>_<tablename_2>
Example:
FK_UserDetails_Emails
  • Default: DF_<table name>_<column name>
Example:
DF_ UserDetails _UserName
  • Normalize Database structure based on 3rd Normalization Form. Normalization is the process of designing a data model to efficiently store data in a database. (Read More Here)
  • Avoid use of SELECT * in SQL queries. Instead practice writing required column names after SELECTstatement.
Example:
1
2
SELECT Username, Password
FROM UserDetails
  • Use SET NOCOUNT ON at the beginning of SQL Batches, Stored Procedures and Triggers. This improves the performance of Stored Procedure. (Read More Here)
  • Properly format SQL queries using indents.
Example: Wrong Format
1
SELECT Username, Password FROM UserDetails ud INNER JOIN Employee e ON e.EmpID = ud.UserID
Example: Correct Format
1
2
3
SELECT Username, Password
FROM UserDetails ud
INNER JOIN Employee e ON e.EmpID = ud.UserID
  • Practice writing Upper Case for all SQL keywords.
Example:
SELECT, UPDATE, INSERT, WHERE, INNER JOIN, AND, OR, LIKE.
  • It is common practice to use Primary Key as IDENTITY column but it is not necessary. PK of your table should be selected very carefully.
  • If “One Table” references “Another Table” than the column name used in reference should use the following rule :
Column of Another Table : <OneTableName> ID
Example:
If User table references Employee table than the column name used in reference should be UserID where User is table name and ID primary column of User table and UserID is reference column of Employee table.
  • Columns with Default value constraint should not allow NULLs.
  • Practice using PRIMARY key in WHERE condition of UPDATE or DELETE statements as this will avoid error possibilities.
  • Always create stored procedure in same database where its relevant table exists otherwise it will reduce network performance.
  • Avoid server-side Cursors as much as possible, instead use SELECT statement. If you need to use cursor then replace it next suggestion.
  • Instead of using LOOP to insert data from Table B to Table A, try to use SELECT statement with INSERTstatement. (Read More Here)
1
2
3
4
INSERT INTO TABLE A (column1, column2)
SELECT column1, column2
FROM TABLE B
WHERE ....
  • Avoid using spaces within the name of database objects; this may create issues with front-end data access tools and applications. If you need spaces in your database object name then will accessing it surround the database object name with square brackets.
Example:
[Order Details]
  • Do not use reserved words for naming database objects, as that can lead to some unpredictable situations. (Read More Here)
  • Practice writing comments in stored procedures, triggers and SQL batches, whenever something is not very obvious, as it won’t impact the performance.
  • Do not use wild card characters at the beginning of word while search using LIKE keyword as it results in Index scan.
  • Indent code for better readability. (Example)
  • While using JOINs in your SQL query always prefix column name with the table name. (Example). If additionally require then prefix Table name with ServerName, DatabaseName, DatabaseOwner. (Example)
  • Default constraint must be defined at the column level. All other constraints must be defined at the table level. (Read More Here)
  • Avoid using rules of database objects instead use constraints.
  • Do not use the RECOMPILE option for Stored Procedure unless there is specific requirements.
  • Practice to put the DECLARE statements at the starting of the code in the stored procedure for better readability (Example)
  • Put the SET statements in beginning (after DECLARE) before executing code in the stored procedure. (Example)


https://blog.sqlauthority.com/2008/09/24/sql-server-coding-standards-guidelines-part-2/

    • To express apostrophe within a string, nest single quotes (two single quotes).
    Example:
    SET @sExample 'SQL''s Authority'
      • When working with branch conditions or complicated expressions, use parenthesis to increase readability.
      IF ((SELECT 1FROM TableNameWHERE 1=2ISNULL)
      • To mark single line as comment use (–) before statement. To mark section of code as comment use (/*…*/).
      • If there is no need of resultset then use syntax that doesn’t return a resultset.
      IF EXISTS   (SELECT 1
      FROM UserDetails
      WHERE UserID 50)
          Rather than,
        IF EXISTS  (SELECT COUNT (UserID)
        FROM UserDetails
        WHERE UserID 50)
        • Use graphical execution plan in Query Analyzer or SHOWPLAN_TEXT or SHOWPLAN_ALL commands to analyze SQL queries. Your queries should do an “Index Seek” instead of an “Index Scan” or a “Table Scan”. (Read More Here)
        • Do not prefix stored procedure names with “SP_”, as “SP_” is reserved for system stored procedures.
          Example:
          SP<App Name>_ [<Group Name >_] <Action><table/logical instance>
        • Incorporate your frequently required, complicated joins and calculations into a view so that you don’t have to repeat those joins/calculations in all your queries. Instead, just select from the view. (Read More Here)
        • Do not query / manipulate the data directly in your front end application, instead create stored procedures, and let your applications to access stored procedure.
        • Do not store binary or image files (Binary Large Objects or BLOBs) inside the database. Instead, store the path to the binary or image file in the database and use that as a pointer to the actual file stored on a server.
        • Use the CHAR datatype for a non-nullable column, as it will be the fixed length column, NULL value will also block the defined bytes.
        • Avoid using dynamic SQL statements if you can write T-SQL code without using them.
        • Minimize the use of Nulls. Because they incur more complexity in queries and updates. ISNULL and COALESCE functions are helpful in dealing with NULL values
        • Use Unicode datatypes, like NCHAR, NVARCHAR or NTEXT if it needed, as they use twice as much space as non-Unicode datatypes.
        • Always use column list in INSERT statements of SQL queries. This will avoid problem when table structure changes.
        • Perform all referential integrity checks and data validations using constraints instead of triggers, as they are faster. Limit the use of triggers only for auditing, custom tasks, and validations that cannot be performed using constraints.
        • Always access tables in the same order in all stored procedure and triggers consistently. This will avoid deadlocks. (Read More Here)
        • Do not call functions repeatedly in stored procedures, triggers, functions and batches, instead call the function once and store the result in a variable, for later use.
        • With Begin and End Transaction always use global variable @@ERROR, immediately after data manipulation statements (INSERT/UPDATE/DELETE), so that if there is an Error the transaction can be rollback.
        • Excessive usage of GOTO can lead to hard-to-read and understand code.
          • Do not use column numbers in the ORDER BY clause; it will reduce the readability of SQL query.
            Example: Wrong Statement
            SELECT UserIDUserNamePasswordFROM UserDetailsORDER BY 2
          Example: Correct Statement
          SELECT UserIDUserNamePasswordFROM UserDetailsORDER BY UserName
          • The RETURN statement is meant for returning the execution status only, but not data. If you need to return data, use OUTPUT parameters.
          • If stored procedure always returns single row resultset, then consider returning the resultset using OUTPUTparameters instead of SELECT statement, as ADO handles OUTPUT parameters faster than resultsets returned by SELECT statements.
          • Effective indexes are one of the best ways to improve performance in a database application.
          • BULK INSERT command helps to import a data file into a database table or view in a user‐specified format.
          • Use Policy Management to make or define and enforce your own policies fro configuring and managing SQL Server across the enterprise, eg. Policy that Prefixes for stored procedures should be sp.
          • Use sparse columns to reduce the space requirements for null values. (Read More Here)
          • Use MERGE Statement to implement multiple DML operations instead of writing separate INSERT, UPDATE, DELETE statements.
          • When some particular records are retrieved frequently, apply Filtered Index to improve query performace, faster retrieval and reduce index maintenance costs.
          • EXCEPT or NOT EXIST clause can be used in place of LEFT JOIN or NOT IN for better peformance.
          Example:
          SELECT EmpNoEmpName
          FROM EmployeeRecord
          WHERE Salary 1000 AND Salary
          NOT IN (SELECT Salary
          FROM EmployeeRecord
          WHERE Salary 2000);
              (Recomended)
            SELECT EmpNoEmpNameFROM EmployeeRecordWHERE Salery 1000EXCEPT
            SELECT 
            EmpNoEmpNameFROM EmployeeRecordWHERE Salery 2000ORDER BY EmpName;

            https://blog.sqlauthority.com/2007/06/05/sql-server-database-coding-standards-and-guidelines-part-2/
            SQL Server Database Coding Standards and Guidelines – Part 2

            Coding Standards

            • Optimize queries using the tools provided by SQL Server5
            • Do not use SELECT *
            • Return multiple result sets from one stored procedure to avoid trips from the application server to SQL server
            • Avoid unnecessary use of temporary tables
              • Use ‘Derived tables’ or CTE (Common Table Expressions) wherever possible, as they perform better6
            • Avoid using <> as a comparison operator
              • Use ID IN(1,3,4,5) instead of ID <> 2
            • Use SET NOCOUNT ON at the beginning of stored procedures7
            • Do not use cursors or application loops to do inserts8
              • Instead, use INSERT INTO
            • Fully qualify tables and column names in JOINs
            • Fully qualify all stored procedure and table references in stored procedures.
            • Do not define default values for parameters.
              • If a default is needed, the front end will supply the value.
            • Do not use the RECOMPILE option for stored procedures.
            • Place all DECLARE statements before any other code in the procedure.
            • Do not use column numbers in the ORDER BY clause.
            • Do not use GOTO.
            • Check the global variable @@ERROR immediately after executing a data manipulation statement (like INSERT/UPDATE/DELETE), so that you can rollback the transaction if an error occurs
              • Or use TRY/CATCH
            • Do basic validations in the front-end itself during data entry
            • Off-load tasks, like string manipulations, concatenations, row numbering, case conversions, type conversions etc., to the front-end applications if these operations are going to consume more CPU cycles on the database server
            • Always use a column list in your INSERT statements.
              • This helps avoid problems when the table structure changes (like adding or dropping a column).
            • Minimize the use of NULLs, as they often confuse front-end applications, unless the applications are coded intelligently to eliminate NULLs or convert the NULLs into some other form.
              • Any expression that deals with NULL results in a NULL output.
              • The ISNULL and COALESCE functions are helpful in dealing with NULL values.
            • Do not use the identitycol or rowguidcol.
            • Avoid the use of cross joins, if possible.
            • When executing an UPDATE or DELETE statement, use the primary key in the WHERE condition, if possible. This reduces error possibilities.
            • Avoid using TEXT or NTEXT datatypes for storing large textual data.9
              • Use the maximum allowed characters of VARCHAR instead
            • Avoid dynamic SQL statements as much as possible.10
            • Access tables in the same order in your stored procedures and triggers consistently.11
            • Do not call functions repeatedly within your stored procedures, triggers, functions and batches.12
            • Default constraints must be defined at the column level.
            • Avoid wild-card characters at the beginning of a word while searching using the LIKE keyword, as these results in an index scan, which defeats the purpose of an index.
            • Define all constraints, other than defaults, at the table level.
            • When a result set is not needed, use syntax that does not return a result set.13
            • Avoid rules, database level defaults that must be bound or user-defined data types. While these are legitimate database constructs, opt for constraints and column defaults to hold the database consistent for development and conversion coding.
            • Constraints that apply to more than one column must be defined at the table level.
            • Use the CHAR data type for a column only when the column is non-nullable.14
            • Do not use white space in identifiers.
            • The RETURN statement is meant for returning the execution status only, but not data.
            Reference:
            SQL SERVER - Database Coding Standards and Guidelines - Part 2 codingstandard
            5) Use the graphical execution plan in Query Analyzer or SHOWPLAN_TEXT or SHOWPLAN_ALL commands to analyze your queries. Make sure your queries do an “Index seek” instead of an “Index scan” or a “Table scan.” A table scan or an index scan is a highly undesirable and should be avoided where possible.
            6) Consider the following query to find the second highest offer price from the Items table:
            1
            2
            3
            4
            5
            6
            7
            8
            SELECT MAX(Price)
            FROM Products
            WHERE ID IN
            (
            SELECT TOP 2 ID
            FROM Products
            ORDER BY Price DESC
            )
            The same query can be re-written using a derived table, as shown below, and it performs generally twice as fast as the above query:
            1
            2
            3
            4
            5
            6
            7
            SELECT MAX(Price)
            FROM
            (
            SELECT TOP 2 Price
            FROM Products
            ORDER BY Price DESC
            )
            7) This suppresses messages like ‘(1 row(s) affected)’ after executing INSERT, UPDATE, DELETE and SELECT statements. Performance is improved due to the reduction of network traffic.
            8) Try to avoid server side cursors as much as possible. Always stick to a ‘set-based approach’ instead of a ‘procedural approach’ for accessing and manipulating data. Cursors can often be avoided by using SELECT statements instead. If a cursor is unavoidable, use a WHILE loop instead. For a WHILE loop to replace a cursor, however, you need a column (primary key or unique key) to identify each row uniquely.
            9) You cannot directly write or update text data using the INSERT or UPDATE statements. Instead, you have to use special statements like READTEXT, WRITETEXT and UPDATETEXT. So, if you don’t have to store more than 8KB of text, use the CHAR(8000) or VARCHAR(8000) datatype instead.
            10) Dynamic SQL tends to be slower than static SQL, as SQL Server must generate an execution plan at runtime. IF and CASE statements come in handy to avoid dynamic SQL.
            11) This helps to avoid deadlocks. Other things to keep in mind to avoid deadlocks are:
            • Keep transactions as short as possible.
            • Touch the minimum amount of data possible during a transaction.
            • Never wait for user input in the middle of a transaction.
            • Do not use higher level locking hints or restrictive isolation levels unless they are absolutely needed.
            12) You might need the length of a string variable in many places of your procedure, but don’t call the LEN function whenever it’s needed. Instead, call the LEN function once and store the result in a variable for later use.
            13)
            1
            2
            3
            4
            IF EXISTS (
             SELECT 1
             FROM Products
             WHERE ID = 50)
            Instead Of:
            1
            2
            3
            4
            IF EXISTS (
             SELECT COUNT(ID)
             FROM Products
             WHERE ID = 50)
            14) CHAR(100), when NULL, will consume 100 bytes, resulting in space wastage. Preferably, use VARCHAR(100) in this situation. Variable-length columns have very little processing overhead compared with fixed-length columns.