SQL Server Standards-Naming Convention PDF
SQL Server Standards-Naming Convention PDF
Version 1.5
I. Namin
Namingg Convention s
The main goal of adopting a naming convention for database objects is
so that you and others can easily identify the type and purpose of all
objects contained in the database. The information presented here
serves as a guide for you to follow when naming your database
objects. When reading these rules and guidelines, remember
that consistent naming can be the most important rule to follow.
Please also keep in mind that following the guidelines as outlined in
this document can still produce long and cryptic names, but will limit
their numbers and impact. However, ultimately your unique situation
situation
will dictate the reasonability of your naming convention. The goal of
this particular naming convention is to produce practical, legible,
concise, unambiguous and consistent names for your database
objects.
1. Tables
2. Columns (incl. Primary, Foreign and Composite Keys)
3. Indexes
4. Constraints
5. Views
6. Stored Procedures
7. Triggers
1. TABLES
When naming your database tables, give consideration to other steps
in the development process. Keep in mind you will most likely have
to utilize the names you give your tables several times as part of other
objects, for example, procedures, triggers or views may all contain
references to the table name. You want to keep the name as simple
and short as possible. Some systems enforce
e nforce character limits on object
names also.
1a (Singular
Rule 1a ( Singular Names)
Names) - Table names should be singular, for
example, "Customer" instead of "Customers". This rule is
applicable because tables are patterns for storing an entity as a record
– they are analogous to Classes serving up class instances. And if for
no other reason than readability, you avoid errors due to the
pluralization of English nouns in the process of database development.
For instance, activity becomes activities, ox becomes oxen, person
becomes people or persons, alumnus becomes alumni, whilewhi le data
remains data.
1b (Prefixes
Rule 1b ( Prefixes) – Don’t use prefixes unless they are deemed
necessary to help you organize your tables into related groups or
distinguish them from other unrelated tables. Generally speaking,
prefixes will cause you to have to type a lot of unnecessary characters.
Do not give your table names prefixes like "tb" or "TBL_" as these are
redundant and wordy. It will be obvious which names are the table
names in SQL statements because they will always be preceded by the
FROM clause of the SELECT statement. In addition, many RDBMS
administrative and/or query tools (such as SQL Server Management
Studio) visually separate common database objects in the
development environment. Also note that Rule 5a provides a means
to distinguish views from tables.
Rule 2a (Identity Primary Key Fields) - For fields that are the primary
key for a table and uniquely identify each record in the table, the
name should simply be [tableName] + “Id“(e.g.in a Customer table,
the primary key field would be “CustomerId”. A prefix is added
mainly because “Id” is a keyword in SQL Server and we would have to
wrap it in brackets when referencing it in queries otherwise. Though
CustomerId conveys no more information about the field than
Customer.Id and is a far wordier implementation, it is still preferable
to having to type brackets around “Id”.
Rule 2b (Foreign Key Fields) - Foreign key fields should have the
exact same name as they do in the parent table where the field is the
primary. For example, in the Customers table the primary key field
might be "CustomerId". In an Orders table where the customer id is
This rule combined with rule 2a makes for much more readable SQL:
... File inner join Directory on File.FileID = Directory.FileID ...
3. INDEXES
Indexes will remain named as the SQL Server default, unless the index
created is for a special purpose. All primary key fields and foreign key
fields will be indexed and named in the SQL Server default. Any other
index will be given a name indicating it’s purpose.
{U/N}IX_{TableName}{SpecialPurpose}
where "U/N" is for unique or non-unique and "IX_" matches the default
prefix that SQL Server assigns indexes.
Rule 3b (Prefixes and Suffixes) - Avoid putting any prefix other than
that specified in Rule 3a before your special-purpose indexes..
4. CONSTRAINTS
Constraints are at the field/column level so the name of the field the
constraint is on should be used in the name. The type of constraint
(Check, Referential Integrity a.k.a Foreign Key, Primary Key, or
Unique) should be noted also. Constraints are also unique to a
particular table and field combination, so you should include the table
name also to ensure unique constraint names across your set of
database tables.
Examples:
1. PkProducts_Id - primary key constraint on the Id field of the
Products table
2. FkOrders_ProductId - foreign key constraint on the ProductId field
in the Orders table
3. CkCustomers_AccountRepId - check constraint on the AccountRepId
The reason underscores are used here with Pascal Case notation is so
that the table name and field name are clearly separated. Without the
underscore, it would become easy to get confused about where the
table name stops and the field name starts.
5. VIEWS
Views follow many of the same rules that apply to naming tables.
There are only two differences (Rules 5a and 5b). If your view
combines entities with a join condition or where clause, be sure to
combine the names of the entities that are joined in the name of your
view. This is discussed in more depth in Rule 5b.
6. STORED PROCEDURES
Unlike a lot of the other database objects discussed here, stored
procedures are not logically tied to any table or column. Typically
though, stored procedures perform one or more common database
activities (Read, Insert, Update, and/or Delete) on a table, or another
action of some kind. Since stored procedures always perform some
type of operation, it makes sense to use a name that describes the
operation they perform. Use a verb to describe the type of operation,
followed by the table(s) the operations occur on.
The use of the “sp” prefix is acceptable and encouraged. This will help
developers identify stored procedures and differentiate them from
other non prefixed objects such as tables when viewing a listing of
database objects.
7. FUNCTIONS
Functions follow many of the same rules that apply to naming stored
procedures. There are only two differences (Rules 5a and 5b) that
exist so the user of the function knows they are dealing with a function
and not a stored procedure and all of the details that involves (value
returned, can be used in a select statement, etc.).
8. TRIGGERS
Triggers have many things in common with stored procedures.
However, triggers are different than stored procedures in two
important ways. First, triggers don't exist on their own. They are
dependent upon a table. So it is wise to include the name of this table
in the trigger name. Second, triggers can only execute when an Insert,
Update, or Delete happens on one or more of the records in the table.
So it also makes sense to include the type of action that will cause the
trigger to execute.
10. Variables
In addition to the general naming standards regarding no special
characters, no spaces, and limited use of abbreviations and acronyms,
common sense should prevail in naming variables; variable names
should be meaningful and natural.
Rule 10b (Prefix ) – All variables must begin with the “@” symbol. Do
NOT user “@@” to prefix a variable as this signifies a SQL Server
system global variable and will affect performance.
Example 1:
We have a modular system that deals with students and teacher data
separately. We have defined these modules as such:
spSTU_Attendance_InserUpdate
spTEA_Credentials_Delete
spSTU_ValidateStudentID
spTEA_Address_InsertUpdate
spSTU_Address_InsertUpdate
vwSTU_AllStudents
Example 2:
Should you find the need for even more granularity when
implementing your naming conventions, consider using sub-modules
as well.
spDTA_STU_Attendance_InserUpdate
spDTA_TEA_Credentials_Delete
vwRPT_STU_StudentAchievementReport
spRPT_TEA_TeacherQualificationsReport
spDTA_STU_Address_InsertUpdate
vwDTA_STU_ValidateStudent
The first of the following two queries shows the old style join, while the
second one shows the new ANSI join syntax:
SELECT
a. Aut hor I d,
t . Ti t l e
FROM Ti t l es t , Aut hor s a, Ti t l eAut hor t a
WHERE
a. Aut horI d = t a. Aut horI d AND
t a. Ti t l eI d = t . Ti t l eI d AND
t . Ti t l e LI KE ' %Comput er %'
SELECT
a. Aut hor I d,
t . Ti t l e
FROM dbo. Aut hor s a
I NNER J OI N dbo. Ti t l eAut hor t a ON
a. Aut hor I d = t a. Aut hor I d
I NNER J OI N dbo. Ti t l es t ON
t a. Ti t l eI d = t . Ti t l eI d
WHERE
t . Ti t l e LI KE ' %Comput er %'
Prefix all table name with the table owner (in most cases “dbo.”). This
results in a performance gain as the optimizer does not have to
perform a lookup on execution as well as minimizing ambiguities in
your T-SQL.
Use aliases for your table names in most T-SQL statements; a useful
convention is to make the alias out of the first or first two letters of
each capitalized table name, e.g. “Site” becomes “s” and “SiteType”
becomes “st”.
Now if you run the above INSERT statement. You get the following
error from SQL Server:
Confusing SQL:
SELECT dbo. Deal Uni t I nvoi ce. Deal Uni t I nvoi ceI D,
dbo. Deal Uni t I nvoi ce. Uni t I nvent or yI D, dbo. Uni t I nvent or y. Uni t I D,
dbo. Uni t I nvent or y. St ockNumber AS [ St ock Number ] , dbo. Uni t Type. Uni t Type
AS [ Uni t Type] , I SNULL( dbo. Make. Descri pt i on, ' ' ) AS Make,
I SNULL( dbo. Model . Descr i pt i on, ' ' ) AS Model , DATEPART( YEAR,
dbo. Uni t . Pr oduct i onYear ) AS [ Year ] , dbo. Uni t Type. Uni t TypeI D,
dbo. Met er Type. Descr i pt i on AS Met er Type, dbo. Uni t I nvent or y. Met er Readi ng,
dbo. Uni t I nvent or y. ECMReadi ng, ' $' + LTRI M( CONVERT( nvar char ( 18) ,
CAST( dbo. Deal Uni t I nvoi ce. Pr i c e AS deci mal ( 18, 2) ) ) ) AS Pr i ce, ' $' +
LTRI M( CONVERT( nvar char ( 18) , CAST( dbo. Deal Uni t I nvoi ce. Cost AS
deci mal ( 18, 2) ) ) )
AS Cost , dbo. Deal Uni t I nvoi ce. I sTr adeI n, I SNULL( dbo. Uni t . Vi n, ' ' ) AS
Vi n, I SNULL( dbo. Uni t . Ser i al Number , ' ' ) AS Ser i al Number ,
dbo. Uni t I nvent or y. Avai l abi l i t ySt at us I D,
dbo. Uni t I nvent or y. Sel l i ngSt at us I D, dbo. Uni t I nvent or y. I sNew,
dbo. Uni t I nvent or y. Uni t Pur chaseOr der I D,
dbo. Uni t I nvent or y. BaseCost , dbo. Deal Uni t I nvoi ce. Deal Packet I nvoi ceI D
FROM dbo. Deal Uni t I nvoi ce I NNER J OI N
dbo. Uni t I nvent or y ON dbo. Deal Uni t I nvoi ce. Uni t I nvent or yI D =
dbo. Uni t I nvent or y. Uni t I nvent or yI D I NNER J OI N
dbo. Uni t ON dbo. Uni t I nvent or y. Uni t I D = dbo. Uni t . Uni t I D LEFT OUTER J OI N
dbo. Met er Type ON dbo. Uni t . Met er TypeI D = dbo. Met er Type. Met er TypeI D LEFT
OUTER J OI N
dbo. Uni t Type ON dbo. Uni t I nvent or y. Uni t TypeI D = dbo. Uni t Type. Uni t TypeI D
AND dbo. Uni t Type. I nActi ve = 0 LEFT OUTER J OI N
dbo. Make ON dbo. Uni t . MakeI D = dbo. Make. MakeI D AND dbo. Make. I nacti ve = 0
LEFT OUTER J OI N dbo. Model ON dbo. Uni t . Model I D = dbo. Model . Model I D AND
dbo. Model . I nActi ve = 0
Now look at the same SQL Statement but organized in an easy to read
and more maintainable format:
SELECT
dui . Deal Uni t I nvoi ceI D,
dui . Uni t I nvent or yI D,
ui . Uni t I D,
ui . St ockNumber [ St ock Number ] ,
ut . Uni t Type AS [ Uni t Type] ,
COALESCE( mk. Descr i pt i on, ' ' ) Make,
COALESCE( ml . Descri pt i on, ' ' ) Model ,
DATEPART( YEAR, u. Pr oduct i onYear ) [ Year ] ,
ut . Uni t TypeI D,
mt . Descri pt i on AS Met er Type,
ui . Met er Readi ng,
ui . ECMReadi ng,
' $' + LTRI M( CONVERT( nvar char ( 18) , CONVERT( deci mal ( 18, 2) , dui . Pr i ce) ) )
Pr i ce,
' $' + LTRI M( CONVERT( nvar char ( 18) , CONVERT( deci mal ( 18, 2) , dui . Cost ) ) )
Cost ,
dui . I sTr adeI n,
COALESCE( u. Vi n, ' ' ) Vi n,
COALESCE( u. Ser i al Number , ' ' ) Ser i al Number ,
ui . Avai l abi l i t ySt at us I D,
ui . Sel l i ngSt at us I D,
ui . I sNew,
ui . Uni t Pur chaseOr derI D,
ui . BaseCost ,
dui . Deal Packet I nvoi ceI D
FROM
dbo. Deal Uni t I nvoi ce dui
I NNER J OI N dbo. Uni t I nvent or y ui
ON dui . Uni t I nvent or yI D = ui . Uni t I nvent or yI D
I NNER J OI N dbo. Uni t u ON
ON ui . Uni t I D = u. Uni t I D
LEFT J OI N dbo. Met er Type mt
ON u. Met er TypeI D = mt . Met er TypeI D
LEFT J OI N dbo. Uni t Type ut
ON ui . Uni t TypeI D = ut . Uni t TypeI D
AND ut . I nActi ve = 0
LEFT J OI N dbo. Make mk
ON u. MakeI D = mk. MakeI D
AND mk. I nacti ve = 0
LEFT J OI N dbo. Model ml
ON u. Model I D = ml . Model I D
AND ml . I nActi ve = 0
Note how the tables are aliased and joins are clearly laid out in an
organized manner.
5. Code Commenting
Important code blocks within stored procedures and user defined
functions should be commented. Brief functionality descriptions should
be included where important or complicated processing is taking place.
Comment syntax:
/*
bl ock comment s use ( / * ) t o begi n
and ( */ ) t o cl ose
*/
---------------------------------
Par amet er Def i ni t i on:
---------------------------------
@Tabl eName = Tabl e t o be val i dat ed.
Never, ever 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. Make your front-end applications deadlock-
intelligent, that is, these applications should be able to resubmit the
transaction in case the previous transaction fails with error 1205. In
your applications, process all the results returned by SQL Server
immediately so that the locks on the processed rows are released,
hence no blocking.
Sample transaction:
- - dec l ar e/ i ni t i al i z e er r or count er
DECLARE @er r i nt
SELECT @er r = 0
BEGI N TRAN
I F @er r = 0
BEGI N
COMMI T TRAN
RETURN 0
END
ELSE
BEGI N
ROLLBACK TRAN
RETURN @er r
END
- - decl ar e er r or count er
DECLARE @er r i nt
BEGI N TRAN
GOTO END_PROC
- - Handl e Er r or s
ERROR_HDLR:
ROLLBACK TRANSACTI ON
RETURN @er r
SQL Server 10.0(2008) and greater – SQL version 10.0 has added
Try/Catch functionality and new functions to report error status to
enhance error handling. You may implement this methodology when
developing in SQL 10.0 or higher. Example(s) below.
COMMI T TRANSACTI ON
END TRY
GO
BEGI N CATCH
SELECT
ERROR_NUMBER( ) as Er r or Number ,
ERROR_MESSAGE( ) as Er r or Message
- - Test XACT_STATE f or 1 or - 1.
- - XACT_STATE = 0 means t her e i s no t r ansact i on and
- - a commi t or r ol l back oper at i on woul d gener at e an er r or.
Perform all your referential integrity checks and data validations using
constraints (foreign key and check constraints) instead of triggers, as
they are faster. Limit the use triggers only for auditing, custom tasks
and validations that cannot be performed using constraints.
Constraints save you time as well, as you don't have to write code for
these validations, allowing the RDBMS to do all the work for you.
Should the need arise where cursors are the only option, avoid using
dynamic and update cursors. Make sure you define your cursors as
local, forward only to increase performance and decrease overhead.
Sample Cursor:
DECLARE @var 1 i nt
SELECT Col 2
FROM MyTabl e1
WHERE Col 1 = 5
There is, however, a work around. See the example below. By using
this method you will in effect bypass parameter sniffing. I would
suggest only using this where you find problems with parameter
sniffing.
SELECT *
FROM MyTabl e
WHERE col 1 = @var 1a
and col 2 = @var 2a