Академический Документы
Профессиональный Документы
Культура Документы
STANDARD
Version
1.3
Effective date
11 Jan 2008
V 1.3
RECORD OF CHANGE
*A - Added M - Modified D - Deleted
Effective
Date
Changed Items
22-Sep06
Firstly created
V1.0
11-Jan08
Adjusted to
reflect SQL 2005
V1.1
Update
v.1.2
Adjusted to
reflect Oracle
v.1.3
20 May
08
2 Jul
2008
A*
M, D
Change Description
New Version
2/20
V 1.3
TABLE OF CONTENTS
Record of change................................................................................................. 2
I.
II.
INTRODUCTION..................................................................................5
1.
Purpose....................................................................................................... 5
2.
Application scope........................................................................................5
3.
Related documents......................................................................................5
4.
Abbreviations.............................................................................................. 5
5.
References................................................................................................... 6
2.
3.
4.
5.
UDO naming must confer to the following regular expression ([a-zA-Z][azA-Z0-9]).............................................................................................................. 8
6.
7.
8.
Tables that map one-to many, many-to-many relationships should be
named by concatenating the names of the tables in question, starting with the
most central tables name...................................................................................8
9.
10.
Avoid naming fields in a way that indicates its use as a foreign key............9
11.
12.
13.
16. When parenthesis around multi-line expressions, always put them on their
own lines............................................................................................................ 11
17. When using IF statements, always BEGIN new scope, even it contains only
one line of code.................................................................................................11
18. Always create scope when defining Procedures and multi statement
Functions........................................................................................................... 11
19. When joining always identify all columns with aliases and always alias
using AS keyword...............................................................................................12
20. Avoid joining in the where clause, instead use ANSI syntax for joining.
Include the reference key last............................................................................12
3/20
V 1.3
21.
22.
23. When defining procedures and functions, its nice to include a commented
Test Harness. Declared used variables for usage in testing................................13
24.
25. Use comments only to illuminate things that are not obvious from reading
the code............................................................................................................. 13
III.
4.
In declaring parameters and variables data type, avoid using the exact
data type if it is referencing to an existing column data type............................14
5.
6.
The schema name should be define properly in DML, inside a procedure,
package or function, to avoid errors such as table or view does not exists. . . .15
IV.
BEST PRACTICES..............................................................................16
1.
2.
Coding....................................................................................................... 17
3.
Transactions.............................................................................................. 19
4.
5.
4/20
I.
V 1.3
INTRODUCTION
a.
Purpose
This document requires or recommends certain practices for writing SQL code
while developing application with RDBMS is SQL server. The objective of this
coding standard is to have a positive effect on:
This document is originally developed base on the standard & guide line of SQL
2000, and also be revised to reflect the changes offer in most recent Microsoft
SQL Server 2005.
This document is organized in to two major sections, the first one giving the
most basic standard for naming and rule, meanwhile the second section provide
the best practice as a walkthrough to help developers produce the most
efficiency code.
b.
Application scope
All projects developed which utilizes SQL server as the RDBMS will be under
scope of this standard.
c.
Related documents
No.
Code
Name of documents
1
2
d.
Abbreviations
No.
Abbr.
Description
T-SQL
UDO
User-Defined Object
DLL
5/20
DML
e.
No.
1
V 1.3
References
Abbr.
T-SQL Coding Standard for programming the Microsoft
SQL Server 2005
Author
Casper.Nielsen@gmail.com
6/20
II.
V 1.3
Naming conventions make the produced code more understandable by making them
easier to read. This section lists the convention to be used throughout while write the
SQL code, either within the stored procedures, triggers or in a simple query.
a.
Correct:
SELECT MAX([Salary]) FROM dbo.[EmployeeSalary]
Incorrect:
SELECT max([Salary]) from dbo.[EmployeeSalary]
b.
Correct:
DECLARE @MaxValue int
Incorrect:
DECLARE @MaxValue INT
c.
Correct:
CREATE TABLE dbo.EmployeeSalary
(
EmployeeSalaryID
INT
)
Incorrect:
CREATE TABLE dbo.Employeesalary
(
EmployeesalaryID
int
)
d.
Correct:
DECLARE @RecordCount int
Incorrect:
DECLARE @Rc int
7/20
V 1.3
e.
UDO naming must confer to the following regular expression ([azA-Z][a-zA-Z0-9]).
Do not use any special or language dependent characters to name objects.
Constraints can use the underscore character.
Correct:
CREATE TABLE dbo.[EmployeeSalary]
Incorrect:
CREATE TABLE dbo.[Employee Salary]
f.
view_: Views
IX_: Indexes
Correct:
CREATE PROCEDURE dbo.usp_EmployeeSelectAll
Incorrect:
CREATE PROCEDURE dbo.EmployeeSelectRetired -without preffixed
g.
Correct:
CREATE TABLE dbo.[Employee]
Incorrect:
CREATE TABLE dbo.[Employees]
8/20
V 1.3
h.
Tables that map one-to many, many-to-many relationships should
be named by concatenating the names of the tables in question, starting
with the most central tables name.
Correct:
CREATE TABLE dbo.[EmployeeSalary]
i.
Correct:
CREATE TABLE dbo.[Employee]
(
EmployeeId int NOT NULL,
EmployeeAddessId int NOT NULL Foreign key to EmployeeAddress
table
)
Incorrect:
CREATE TABLE dbo.[Employee]
(
EmployeeID int NOT NULL,
Addresspk int NOT NULL Foreign key to Address table
)
j.
Avoid naming fields in a way that indicates its use as a foreign key
Correct:
CREATE TABLE dbo.[EmployeeAddress]
(
EmployeeAddressId int NOT NULL,
EmployeeId int NOT NULL,
AddressId int NOT NULL
)
Incorrect:
CREATE TABLE dbo.[EmployeeAddress]
(
EmployeeId int NOT NULL,
AddressId int NOT NULL
)
9/20
V 1.3
By presenting object name in front of stored procedure name, this help to grouping
all stored procedures written to access to the designate object.
When creating procedures to wrap single INSERT/UPDATE/DELETE statements,
operation should be Insert, Update and Delete respectively.
Correct:
CREATE PROCEDURE dbo.usp_EmployeeSelect
Incorrect:
CREATE PROCEDURE dbo.usp_RetiredEmployee
l.
Correct:
CREATE PROCEDURE dbo.usp_EmployeeSelect
Incorrect:
CREATE PROCEDURE usp_RetiredEmployee
m.
Correct:
SELECT [EmployeeName], [EmployeeAddress] FROM dbo.[Employee]
Incorrect:
SELECT [EmployeeName], [EmployeeAddress] FROM Employee
n.
Properly arrange statements: Either use one-liners without
identification or multi-liners with indentation. Do not mix the two
Correct:
SELECT [EmployeeName], [EmployeeAddress] FROM dbo.[Employee]
Or
SELECT [EmployeeName], [EmployeeAddress]
FROM dbo.[Employee]
WHERE [EmployeeName] = JOHN
Incorrect:
SELECT [EmployeeName], [EmployeeAddress] FROM dbo.[Employee]
WHERE [EmployeeName] = JOHN
10/20
V 1.3
Correct:
BEGIN
(code goes here)
END
Incorrect:
BEGIN
(code goes here)
END
p.
When parenthesis around multi-line expressions, always put them
on their own lines
Correct:
RETURN
(
(code goes here)
)
Incorrect:
RETURN (
(code goes here))
q.
When using IF statements, always BEGIN new scope, even it
contains only one line of code
Correct:
IF (@MaxValue > 100)
BEGIN
(code goes here)
END
ELSE
BEGIN
(code goes here)
END
Incorrect:
IF (@MaxValue > 100)
BEGIN
(code goes here)
END
ELSE
(code goes here)
11/20
V 1.3
r.
Always create scope when defining Procedures and multi
statement Functions
Correct:
CREATE PROCEDURE dbo.[usp_EmloyeeSelect]
AS
BEGIN
(code goes here)
END
Incorrect:
CREATE PROCEDURE dbo.[usp_EmloyeeSelect]
AS
(code goes here)
s.
When joining always identify all columns with aliases and always
alias using AS keyword
Correct:
SELECT E. EmployeeName, A.Street
FROM dbo.[Employee] AS E
JOIN dbo.[Address] AS A ON E.AddressId = A.AddressId
Incorrect:
SELECT E.EmployeeName, Street
FROM dbo.[Employee] E
JOIN dbo.[Address] ON E.AddressId = dbo.[Address].AddressId
t.
Avoid joining in the where clause, instead use ANSI syntax for
joining. Include the reference key last
Correct:
SELECT E. EmployeeName, A.Street
FROM dbo.[Employee] AS E
JOIN dbo.[Address] AS A ON E.AddressId = A.AddressId
Incorrect:
SELECT E.EmployeeName, Street
FROM dbo.[Employee] E, dbo.[Address] AS A
WHERE E.AddressId = A.AddressId Joins in the WHERE clause
u.
Correct:
12/20
V 1.3
Incorrect:
v.
Correct:
SELECT E. EmployeeName, A.Street
FROM dbo.[Employee] AS E
JOIN dbo.[Address] AS A ON E.AddressId = A.AddressId
Incorrect:
SELECT E. EmployeeName, A.Street
FROM dbo.[Employee] AS E
INNER JOIN dbo.[Address] AS A ON E.AddressId = A.AddressId
w.
When defining procedures and functions, its nice to include a
commented Test Harness. Declared used variables for usage in testing.
In procedures include a transaction which is properly rolled back after checking
values. This test can be skipped if the procedure is a simple INSERT/UPDATE/DELETE
with no logic besides that
Test harness is an open source SQL Testing tool, can be referred from
http://spunit.sourceforge.net/
x.
If you use a designer tool to generate DML reformat it using the design styles
defined above. In effect it is disallowed to check in DML from designer in to the
project repository, this would help to keep your code consistency.
Using designer tool to generate DDL however is allowed and encouraged.
y.
Use comments only to illuminate things that are not obvious from
reading the code.
13/20
V 1.3
Correct:
CREATE OR REPLACE PROCEDURE X_SDS.usp_Location_GetAll
Incorrect:
CREATE OR REPLACE PROCEDURE [X_SDS].[usp_Location_GetAll]
d.
In declaring parameters and variables data type, avoid using the
exact data type if it is referencing to an existing column data type
Correct:
p_paramName IN <SCHEMA>.<TABLE>.<COLUMN>%TYPE
p_location IN SCDAT.A_PORTFOLIOS.POR_FREECODE_39%TYPE
Incorrect:
p_location IN NVARCHAR2
e.
14/20
V 1.3
f.
The schema name should be define properly in DML, inside a
procedure, package or function, to avoid errors such as table or view
does not exists
Correct:
SELECT * FROM SCDAT.A_PORTFOLIOS
Incorrect:
SELECT * FROM A_PORTFOLIOS
15/20
V 1.3
Introduce a artificial Primary key on Tables, unless the table fall into one of
the following categories:
o
o
o
Many-to-many relationship
Staging table
Imported External tables with reoccurring importing
Always have unique indexes or primary keys on all tables without exception
never leave the integrity up to the application
If you have enumerations in another layer that are persisted onto the
database, map these in a table and ensure consistency by constraints.
If you allow NULL in a field, make sure it has a meaning apart from empty and
zero
Never use the TEXT or NTEXT types instead use the MAX types. This help to
improve querying performance when accessing this type of data from
database.
Be cautious when using the blob type for storing files. Weigh the structure
benefit with the added database load before deciding which approach to use.
Examine where the file logically belongs: If it have significance to the
database, store it there, otherwise store it on the file system.
If you choose the file system as the data store for files, remember to backup
the file store simultaneously with the database to counter synchronization
issues.
Implement the database so it will keep itself consistent with the model it was
designed for. This involves using referential integrity checks extensively.
Implement these checks using constraints. As a minimum IDs with foreign
keys and fields that have a constant limit should be constrained.
16/20
V 1.3
Avoid cascading updates and deletes. Instead use Procedures as access points
to these operations.
Unless a management decision have been taken to allow the usage of Table
Adapters in the other .Net layers, the Table Adapters should exist only in the
data access-layer. Typed Datasets can be used in all layers, if they themselves
do not include Table Adapters. Keep in mind that even when using Table
Adapters T-SQL code should be kept on the database, i.e. the adapter only
wraps stored procedures, functions and views.
Be careful when using collations - they handles differently. Find the most
general collation and use this is the database default, for most European
language scenarios this will be the SQL_Latin1_General_CP1_CI_AS (Case
insensitive/Accent sensitive). When the needs arise to use a specialized
collation, do so on the specific field.
b.
Coding
Use Procedures for functionality with side-effects - Functions for everything
else requiring parameters.
Sole exception is if the Function requires a specific database state to run
correctly - in this case write it as a Procedure
Avoid the use of GOTO. They are basically not needed after the introduction of
TRY/CATCH and often indicate sloppy coding.
Avoid using the @@ERROR function to handle exceptional states. Instead use
the TRY/CATCH construct.
Avoid T-SQL code anywhere but in Views, Procedures, Functions and Batches.
This includes SQL Agent Jobs, DTS, SSIS and .Net code. Only use the
following T-SQL in other layers:
o
SELECT dbo.ufn_MyFunction(someParameter)
EXEC dbo.usp_MyProcedure(someParameter)
17/20
V 1.3
Avoid using batches (scripts) for recurring tasks, except creating and
initializing the database. Use SSIS for transferring batches of data.
If you feel like using a CURSOR to solve a particular problem, first consider
finding a set-based solution. Most of the times the problem can be solved
using CASE.
If this approach is not viable try solving it with a WHILE loop on the primary
key.
Always individually name fields in INSERT and UPDATE statements. Never use
the * operator in such statements.
Correct
INSERT INTO dbo.[User] (FirstName, LastName)
VALUES (@FirstName, @LastName)
Incorrect
INSERT INTO dbo.[User]
VALUES (@FirstName, @LastName)
Set the NOCOUNT state as the first statement in all Procedures where you
dont specifically need the count returned.
Correct
CREATE PROCEDURE dbo.usp_MyProcedure (...)
AS
BEGIN
SET NOCOUNT ON
(code goes here)
END
18/20
V 1.3
Try avoiding prefixing any UDO beyond what is described here. If you need to
further group objects, consider using a schema different from dbo to create
the objects
c.
Transactions
Always set XACT_ABORT.
If you have more than one database modifying action in a Procedure, decide if
it needs to run atomically (most probably it does) if so set XACT_ABORT ON
and encapsulate all statements in a transaction. If it is not required to run
atomically, explicitly set XACT_ABORT OFF.
Correct
CREATE PROCEDURE dbo.usp_MyProcedure (...)
AS
BEGIN
SET XACT_ABORT ON
BEGIN TRAN
(...)
COMMIT TRAN
END
d.
It is important to make sure that when running a query, the order of tables
accessed is vital for speed. Important is also that if a composite index is
referred to in a query, the keys must be referred to in the proper order and in
the proper sort order. If content is looked up in reverse, use DESC on a
column when creating indexes. The driving table in a query (in the FROM
clause) should be the table to return the fewest rows seen in percentage.
Use database tuning advisor to inspect and optimize your SQL query,
investigating the execution plan of long running statement would help.
Use SQL Server profiler for debugging and watching on-going process.
19/20
V 1.3
It is important to make sure that when running a query, the order of tables
accessed is vital for speed. Important is also that if a composite index is
referred to in a query, the keys must be referred to in the proper order and in
the proper sort order. If content is looked up in reverse, use DESC on a
column when creating indexes. The driving table in a query (in the FROM
clause) should be the table to return the fewest rows seen in percentage.
Use database tuning advisor to inspect and optimize your SQL query,
investigating the execution plan of long running statement would help.
Use SQL Server profiler for debugging and watching on-going process.
20/20