Title: SQL Server Best Practices
 1SQL ServerBest Practices
By Vern Rabe 
 2What are Best Practices?
- General rules or guidelines for software 
 development.
- Intended to improve quality, performance, and 
 maintenance
- Not always possible to follow, but always try
3Best Practices  GeneralComment code
- (duh) Since stored procedures and triggers are 
 compiled, not interpreted, there is no
 performance loss by adding many lengthy comments.
4Best Practices  GeneralDont Hardcode
- Consider replacing ANY reference to a number, 
 character string, or datetime with data driven
5Best Practices  GeneralFormat Code
- Formatting eases reading, debugging 
- No right method, but 
- Select U.VIN, 
-  U.Instance, 
-  U.AcquisitionDate 
-  from dbo.UsedTruck U 
-  join dbo.TradeID T 
-  on U.TradeID  T.TradeID 
-  left outer join dbo.UsedTruckSale S 
-  on U.VIN  S.VIN 
-  and U.Instance  S.Instance 
-  where dbo.fxIsInInventory(U.StatusCode)  1 
-  and (T.TradeType  Repo 
-  or T.TradeType  NT Repo) 
-  and COALESCE(S.SaleType, X)  X
6Best Practices  GeneralUse Windows 
Authentication
- Easier administration 
- Centralized administration 
- More secure 
- More flexible 
- Better auditing
7Best Practices  DB DesignNormalize
- Normalize to at least 3rd normal form, then 
 denormalize only when performance requires it. In
 most cases, a normalized database will perform
 faster.
- Denormalized  sometimes OK 
- Un-normalized  never OK 
8Best Practices  DB DesignData Integrity
- Data integrity should be maintained in the 
 database, using CONSTRAINTS when possible,
 otherwise triggers.
- Never rely on code outside of the table to assure 
 the tables integrity
9Best Practices  DB DesignPrimary Key
- Every table should have a declared PK, and if the 
 PK is a surrogate key, there should be a declared
 Alternate Key on the candidate key(s).
10Best Practices  DB DesignReferential 
Integrity
- Declared Referential Integrity (DRI) is the first 
 choice. FAST  Absolute
- DRI Implemented with FOREIGN KEY CONSTRAINTs 
- If DRI cant work (e.g., dbo.Expense.VIN), use 
 trigger code. Still absolute, but not as fast
 (see TRUNCATE)
11Best Practices  DB DesignDomain Integrity
- Limit what can be stored in a column, e.g., 
 ActiveFlag can only be 0, 1, 2, 3 or 9
- Similar to Referential Integrity, but where 
 theres no table holding possible values
- Implemented with CHECK CONSTRAINTs
12Best Practices  DB DesignClustered Index
- Every table should have a clustered index 
- The Primary Key is usually NOT the best choice 
 for the clustered index, even though by default
 it will be
- The best choice is determined by how the table 
 will be used (queried)
13Best Practices  DB DesignData Types to Avoid
- TEXT and NTEXT - Many string functions cannot be 
 used on these datatypes, and indexing is nearly
 useless.
- FLOAT or REAL - These are approximate numeric 
 datatypes, and are usually only appropriate in
 scientific applications.
14Best Practices  DB DesignData Types to Avoid
- Use CHAR instead of VARCHAR only when character 
 length is very consistent. Good example for CHAR
 is State Code or Fleet Code.
15Best Practices  T-SQLThink SET
- SQL is a set based language, and the optimizer is 
 designed to take advantage of that. Avoid cursors
 or looping (row level processing) whenever you
 can.
16Best Practices  T-SQLUDF
- User Defined Functions can make queries easier to 
 read and write, but if not deterministic, they
 can severely impact performance.
17Best Practices  T-SQLSelect 
- Do not use select  or insert into dbo.Table 
 select (without explicit column list).
- Explicit column lists reduce disk I/O (no need to 
 read system tables to identify columns), and are
 more maintainable when columns are added or
 re-positioned.
18Best Practices  T-SQLAvoid ltgt andlike ...
- An index cannot be used on a where clause using 
 wild cards at the beginning of a search string
 using LIKE, and using ltgt (or NOT).
- To increase the chances of the optimizer 
 identifying an efficient query plan, include any
 and all qualifiers that apply.
19Best Practices  T-SQLAlways Use BeginEnd
- Even if a block only contains one statement, 
 delimit with beginend
- Good 
- If _at_somevar gt 25 
- begin 
- Select _at_somevar  25 
- End 
- Bad 
- If _at_somevar gt 25 
-  select _at_somevar  25 
-  
20Best Practices  T-SQLUse Schema Name
- When querying a table, prefix it with the owner 
 (schema), typically dbo. There is a slight
 performance improvement, schema binding requires
 it, and its more readable.
- SELECT a.au_id, 
-  a.au_lname 
-  FROM dbo.authors a
21Best Practices  T-SQLUse Table Alias
- Use table aliasing, even if you are not joining. 
 Aliasing positively eliminates ambiguity, eases
 subsequent modification, and further reduces the
 chance of a typo not being recognized, as in a
 subquery.
- SELECT a.au_id, 
-  a.au_lname 
-  FROM dbo.authors a 
22Best Practices  T-SQLAvoid Table Hints
- It is rare that the SQL Server optimizer doesnt 
 choose the best plan.
- If you think you need to add a Table Hint, triple 
 check your query before doing so.
23Best Practices  T-SQLUse WITH with Table 
Hints
- Good 
-  from dbo.Num N WITH (UPDLOCK, PAGLOCK) 
- Bad 
-  from dbo.Num N (UPDLOCK, PAGLOCK) 
- Yukon will not support without WITH 
24Best Practices  T-SQLSET NOCOUNT ON
- All stored procedures and triggers should begin 
 with SET NOCOUNT ON.
- See _ProcedureTemplate.sql and _FunctionTemplate.s
 ql in SourceSafe
25Best Practices  T-SQLUse ANSI Join Syntax
- Support for T-SQL join syntax will be eliminated 
 in upcoming SQL Server release
- T-SQL syntax can return incorrect results with 
 outer joins
- Difficult to miss a join criterion w/ ANSI syntax 
- Easier to read
26Best Practices  T-SQLAvoid Dynamic SQL
- Performs slower because the optimizer must create 
 an execution plan with every execution
- Increased security risks because it does not take 
 part in ownership chaining.
27Best Practices  T-SQLUse of _at__at_IDENTITY
- The _at__at_IDENTITY function can return incorrect 
 results if there is a trigger on the destination
 table. Use SCOPE_IDENTITY(), or in rare cases
 IDENT_CURRENT() instead.
28Best Practices  T-SQLStored Procedure Debug
- Add a _at_DebugFlag bit parameter to stored 
 procedures, defaulting to 0. When passed in as 1,
 conditional code throughout the procedure can
 return variable values, interim result sets, and
 execution times.
- See _ProcedureTemplate.sql in SourceSafe
29Best Practices  T-SQLStored Procedure Return
- Make sure stored procedures return a value 
 indicating success/failure. Use the RETURN
 statement for this, and do not use the RETURN
 statement for anything else.
- See _ProcedureTemplate.sql in SourceSafe 
30Best Practices  T-SQLCall Procedures with 
Parameter Names
- Exec pnl_GetSomething _at_what  name 
- Easier to read 
- Allows error free changes to procedure 
31Best Practices  T-SQLError Trap in ALL 
Procedures w/DML
- In Stored Procedures and Triggers, always check 
 _at__at_error after every data manipulation statement
- Valid transaction control requires it 
- Examplepe_valuegroups Instead of aborting, it 
 continued, returning NULLs
- See _ProcedureTemplate.sql in SourceSafe 
32Best Practices  T-SQLTemp Tables vs.Table 
Variables
- As a general rule, temp tables perform better 
 than table variables on large tables, and table
 variables perform better on small tables. There
 are so many factors, however, that testing each
 case is the only sure way to know.
- Also consider using derived tables
33Best Practices  T-SQLAvoid stringexpression
- Bad 
- Select SerNo  SerialNo,  
- Good 
- Select SerialNo AS SerNo, 
- Deprecated, support will be dropped
34Best Practices  T-SQLDont use  NULLor ltgt 
NULL
- ANSI says any comparison to NULL returns NULL, 
 e.g.,
- If _at_i  NULL will never return true 
- Use IS (NOT) NULL Instead 
35Best Practices  T-SQLFollow ANSI Standards
- Use ANSI terms instead of T-SQL 
- COALESCE instead of ISNULL 
- CURRENT_TIMESTAMP instead of GET_DATE() 
- ROWVERSION instead of TIMESTAMP 
- Format dates YYYYMMDD
36Best Practices  T-SQLFollow ANSI Standards
- These should be ON 
- ANSI_NULLS 
- ANSI_PADDING 
- ANSI_WARNINGS 
- ARITHABORT 
- CONCAT_NULL_YIELDS_NULL 
- QUOTED_IDENTIFIERS 
- These should be OFF 
- NUMERIC_ROUNDABORT 
37Best Practices  T-SQLAvoid Truncate
- Does not fire triggers  if theres a delete 
 trigger, you probably want it to fire
- Cannot use SCHEMA BINDING 
- Cannot create FK constraints 
- Cannot create indexed views 
- Cannot index computed columns
38Best PracticesThis Presentation
- Can be found at 
- www.rabe.net 
- Click on SQL tab
39SQL Review
- Structured 
- Query 
- Language