Download Best Practices for Data Definitions - Cont`d

Document related concepts

Database wikipedia , lookup

Tandem Computers wikipedia , lookup

Microsoft Jet Database Engine wikipedia , lookup

Entity–attribute–value model wikipedia , lookup

Clusterpoint wikipedia , lookup

Open Database Connectivity wikipedia , lookup

Extensible Storage Engine wikipedia , lookup

Null (SQL) wikipedia , lookup

Database model wikipedia , lookup

Relational model wikipedia , lookup

Microsoft SQL Server wikipedia , lookup

SQL wikipedia , lookup

PL/SQL wikipedia , lookup

Transcript
Lifecycle of database code:
Best development and deployment
practices in SQL server 2000
and 2005
Omri Bahat, PhD
SQL Farms, Inc.
703-946-0885
Agenda
 Key factors in every IT environment
– People, Process, Technology
 Focus of this presentation
– Process and technology in database server systems



Development - Best practices, key concepts and guidelines
QA - Automated tests for database releases
Production - Best deployment practices
– New solutions for MS-SQL 2000 and 2005


Development, packaging, distributed deployment and querying
Tools that answer the dev, QA, and production requirements
above, and follow the Dev to QA to Production release process
– Solutions for small and large SQL farms alike
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Lifecycle of product changes and DB code
 Change requests are provided by the business unit
– Requirements are passed to development
 Dev team scopes and composes the release code
– Produces rollout and rollback code packages
– The complete code base is passed to quality assurance (QA)
 QA tests the release code for functionality and standards
– If the release does not meet expectations (business requirements,
technical standards), the entire code base is returned to dev
– Once the release meets the business requirements and all technical
standards, it is then passed to production
 Production DB administrators (DBAs) rollout the release code
– Unexpected rollout errors prompt release rollback
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Business continuity
 Business continuity is achieved through
– Independent dev/QA/prod environments and resources





Databases
Database servers
Network infrastructure, security accounts, user access
Separate networks
Geographically distributed production environments and failover
DEV
QA
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
PROD
Lifecycle of DB code releases - Development
 A staging area that imitates the production environment
– Contains production business-schema (e.g., tables, views procedures,
functions, user groups, roles)
– Typically does not contain production-specific objects used by database
administrators (e.g., DB maintenance objects)
– Volume of data is significantly smaller than production

Meta-data is the same; non-meta-data is different
 Accessible by developers and dev team members
– Dev security policies are more loose than production
– Domains, users, and active directory accounts are different
 Used to develop and test new features and functionality
– Contains DB objects that are not yet available in production
– As a consequence, dev environments are NOT CLEAN (!) and contain
objects that should NOT make it to production
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Code releases
- Project planning
- Best coding practices
DB Code Development - Step by step
 Determine which databases and servers are affected by the release
– Typically determined by the project architecture
 Identify the data access rules to ensure proper connectivity
– How do non-DB applications communicate with the database?
 ADO
2.x, ADO.Net, ODBC, JDBC, other drivers
– If needed, how do databases communicate?

Linked servers, RPC calls, OPENROWSET
– Logins and users required for proper communications

Domain users and groups, SQL server logins, DB users and roles
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
DB Code Development: Step by step - cont’d
 Identify changes to the data definitions (DDL)
– Tables, views, keys, constraints, indexes
– Which objects need to be created or altered
– Delete objects that are no longer in use, to keep production clean!
 Identify data manipulation (DML) requirements
– Stored procedures, functions
– Tune the table and view schema based on DML operations
Revisit indexes on tables and views
 Apply triggers where needed

– Identify how, when, and who calls each DML object

e.g., SQL jobs, non-DB tier applications, and such
– Tune user and group permissions based on needed DML operations

Grant minimal permissions that will support the needed functionality
 With SQL 2K5 - T-SQL vs. CLR
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - Tables
CREATE TABLE PhoneBook(
FirstName VARCHAR(128),
LastName VARCHAR(128),
PhoneNumber VARCHAR(32))
 Naming conventions
– Make sure that table names follow a pre-determined naming convention





e.g., every table name starts with ‘utb’
Keep table names short, precise, self-explanatory, and clean
Avoid spaces and wildcards (e.g., ‘_’) in object names if possible
To avoid ambiguities
To easily search for the object in the database by name
 Explicitly indicate the table owner / schema
– SQL 2K: Use dbo object owner wherever possible



To avoid ambiguities and potential coding errors
To avoid scripting bugs in MS tools (DMO, Query Analyzer)
Security reasons
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
 Explicitly indicate the target filegroup
– Important when production databases use more than one filegroup
– Specify the filegroup for


Table data (location of data pages), e.g., ON [PRIMARY]
TEXT / NTEXT / IMAGE / XML columns, e.g., TEXTIMAGE_ON [DEFAULT]
– Talk to your production DB administrator!
 Make sure that total column length does not exceed 8060 bytes
– SQL 2K gives a warning upon such table creation; error upon 8060+ insert
– SQL 2005 handles 8060+ tables with variable length columns

At a price of performance impact
CREATE TABLE dbo.utbPhoneBook(
FirstName VARCHAR(128),
LastName VARCHAR(128),
PhoneNumber VARCHAR(32))
ON [PRIMARY]
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - Columns
 Naming convention
– Column names should be standardized, self-explanatory
 Every table must have a unique identifier
– A column with distinct entries
– A set of columns that their combined value is unique

Number of columns should be kept minimal
 Add a fixed set of columns to every table
–
–
–
–
e.g., InsertTime, UpdateTime, SQLLogin, BitArray
Helps to control, synchronize, and audit data
Populate these columns with an UPDATE trigger
Do not use timestamp/rowversion column types

Column types do not contain enough information
– These columns may be omitted in performance sensitive tables

Minimize overhead and performance impact
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - Cont’d
 Internationalization and localization
– Unicode columns for non-English strings
– NVARCHAR, NCHAR, NTEXT
 Collation - server, database, table
– Special caution with temp table - consider database_default
CREATE TABLE #MyTable (
MyCol1 NVARCHAR(16) COLLATE DATABASE_DEFAULT,
MyCol2 NVARCHAR(32) SQL_Latin1_General_CP1_CI_AS)
SELECT * FROM ::fn_helpcollations()
EXEC sp_help <name of temp table as it appears in tempdb>
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
CREATE TABLE dbo.utbPhoneBook(
PersonID INT IDENTITY(1,1),
FirstName VARCHAR(128),
LastName VARCHAR(128),
PhoneNumber VARCHAR(32),
BitArray INT,
InsertTime DATETIME,
UpdateTime DATETIME,
SQLLogin NVARCHAR(128))
ON [PRIMARY]
GO
CREATE TRIGGER dbo.TRG_utbPhoneBook_Update
ON dbo.utbPhoneBook
AFTER UPDATE
AS
UPDATE
SET
FROM
a
UpdateTime = getdate(),
SQLLogin = SUSER_SNAME()
dbo.utbPhoneBook a
INNER JOIN inserted i
ON a.PersonID = i.PersonID
GO
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
 Make sure that table columns capture data at high granularity
– Recovering details from low granularity data can be difficult
– e.g., PhoneNumber: CountryCode, AreaCode, NumberBody, Extension
 Do not allow columns to be NULL
– Avoid coding ambiguities (no need to check whether col value IS NULL)
– Performance gain when inserting data to sensitive (e.g., large) tables
– Standardize values that will replace NULL entries, and use defaults



Empty string (i.e., '') for string column types
(-1) for numeric columns
getdate() or ‘1/1/1900’ for date columns
 Avoid using the following column types
– TIMESTAMP/ROWVERSION - customize your own time tracking instead
– FLOAT - has overflow and rounding errors. Use DECIMAL instead.
– BIT - use an (TINY)INT column as array of bits instead.
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
 Column defaults
– Assign column default value instead of allowing NULL columns
– Naming conventions


Default name should be assigned by the developer
Make sure that default name is not automatically assigned by SQL
 General tips
– Avoid user-defined data types if possible
– Use BIGINT, or 4 TINYINT column types to store IP addresses
– Use check constraints to validate the domain of column values
 Tips for high volume data tables
– Avoid using TEXT / NTEXT / IMAGE / XML columns

Minimize overhead - Data of those columns is not stored on the data pages
– Use fixed (and not variable) length columns wherever possible

Reduce column size control overhead
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
CREATE TABLE dbo.utbPhoneBook(
PersonID INT IDENTITY(1,1),
FirstName VARCHAR(128) NOT NULL DEFAULT '',
LastName VARCHAR(128) NOT NULL DEFAULT '',
CountryCode INT NOT NULL DEFAULT 1,
AreaCode INT NOT NULL DEFAULT -1,
NumberBody INT NOT NULL DEFAULT -1,
Extension INT NOT NULL DEFAULT -1,
BitArray INT NOT NULL DEFAULT 0,
InsertTime DATETIME NOT NULL DEFAULT getdate(),
UpdateTime DATETIME NOT NULL DEFAULT getdate(),
SQLLogin NVARCHAR(128) NOT NULL)
ON [PRIMARY]
GO
EXEC sp_helpconstraint @objname = '[dbo].[utbPhoneBook]', @nomsg = 'nomsg'
GO
IMPOSSIBLE TO CONTROL (e.g., drop)
DEFAULTS BASED ON THEIR NAMES!
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
CREATE TABLE dbo.utbPhoneBook(
PersonID INT IDENTITY(1,1),
FirstName VARCHAR(128) NOT NULL
CONSTRAINT DF_utbPhoneBook_FirstName DEFAULT '',
LastName VARCHAR(128) NOT NULL
CONSTRAINT DF_utbPhoneBook_LastName DEFAULT '',
CountryCode INT NOT NULL
CONSTRAINT DF_utbPhoneBook_CountryCode DEFAULT 1,
AreaCode INT NOT NULL
CONSTRAINT DF_utbPhoneBook_AreaCode DEFAULT -1,
NumberBody INT NOT NULL
CONSTRAINT DF_utbPhoneBook_NumberBody DEFAULT -1,
Extension INT NOT NULL
CONSTRAINT DF_utbPhoneBook_Extension DEFAULT -1,
BitArray INT NOT NULL
CONSTRAINT DF_utbPhoneBook_BitArray DEFAULT 0,
InsertTime DATETIME NOT NULL
CONSTRAINT DF_utbPhoneBook_InsertTime DEFAULT getdate(),
UpdateTime DATETIME NOT NULL
CONSTRAINT DF_utbPhoneBook_UpdateTime DEFAULT getdate(),
SQLLogin NVARCHAR(128) NOT NULL)
ON [PRIMARY]
GO
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
EXEC sp_helpconstraint @objname = '[dbo].[utbPhoneBook]', @nomsg = 'nomsg'
GO
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - Indexes
 Clustered indexes
CREATE TABLE dbo.utbMyTable (
Col1 INT NOT NULL
PRIMARY KEY CLUSTERED,
Col2 VARCHAR(10) NOT NULL,
Col3 DECIMAL(18, 10))
Col1 (CI)
1
2
3
4
5
6
7
8
9
10
Col2
Col3
abc
7
bcd
2.13
cde
-1.9
MyString1 -123.115
MyString1
-2
abc
1.1
bcd
2.2
cde
2.1
d
8.9
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - Cont’d
 Non-clustered indexes
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Col1 (CI)
1
2
3
4
5
6
7
8
9
10
Col2
Col3
abc
7
bcd
2.13
cde
-1.9
MyString1 -123.115
MyString1
-2
abc
1.1
bcd
2.2
cde
2.1
d
8.9
Best Practices for Data Definitions - Cont’d
 TEXT, NTEXT, IMAGE, XML columns
CREATE TABLE dbo.utbMyTable (
Col1 INT NOT NULL
PRIMARY KEY CLUSTERED,
Col2 VARCHAR(10) NOT NULL,
Col3 DECIMAL(18, 10),
ColText TEXT)
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
 Every table should have a clustered index (CI)
– The CI determines the physical and logical storage of table data
– The CI need not be applied on the same column(s) as the primary key (PK)
– The CI should be applied on most frequently queried columns

Column order matters - make sure that the CI is applied correctly
 Which columns to index?
– High cardinality column(s) that are queried often
– Remember: Indexes come at a price


Num of indexes increases = Slower INSERT, DB file disk size increases
Maintenance is required for each index in production
 Indexes should only be applied on columns with high cardinality
–
–
–
–
On a single column
On several columns - cardinality of the combined columns value counts
Otherwise, index will not be used by the optimizer
Best performance when indexes are applied on unique column(s)
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
 Avoid indexes on long (wide) column, or columns combination
– Better performance achieved with shorter index rows
– If possible, avoid indexes on string columns
 Always specify the index properties
– FILLFACTOR, PAD_INDEX, FILEGROUP
– In performance sensitive application, calculate the needed FILLFACTOR

Instead of accepting the server default
 Naming convention - Simple, self-explanatory, and informative names
– Ensure that index name is assigned by the user, not by the SQL server
– e.g.,


Clustered:
Non-clustered:
CI_<TableName>_<Column(s)Name(s)>_<Unique>
IX_<TableName>_<Column(s)Name(s)>_<Unique>
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
 General comments and recommendations
– Read and understand how indexes are implemented in practice

SQL 2K and 2005 have many differences, including:
– Rebuilding indexes offline
– Storing column data at the leaf level of every index
– Differences between unique index and unique constraint



Both implemented and stored in the DB data file as indexes
Support different properties and features, see OBJECTPROPERTY
Constraint can be disabled
– sysindexes - what do these entries mean?



indid = 0 - table does not have a CI. This entry reflects the data pages
indid = 1 - this entry is reserved for the clustered index
indid = 255 - reserved for all TEXT / NTEXT / IMAGE columns of the table
– Getting the status of an index

Use sp_helpindex and INDEXPROPERTY instead of accessing sysindexes
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices - Keys and Constraints
 Why use primary / unique keys and not only a unique indexes
– Indexes used for boosting query performance
– Keys used for the referential and relational integrity (RI)
– Keys that are not indexes are not treated as indexes by SQL server
 Every table must have a unique identifier
– How to determine the best primary / unique key?
Ask yourself the following:
If I was to map a foreign key constraint to another table to ensure referential
integrity, which columns would I reference? Those column(s) should be the PK.

 Foreign keys (FKs)
– Minimize the number of columns in each FK constraint
– Use the properties of the FK carefully, especially in self referencing tables



CASCADE UPDATE
CASCADE DELETE
NOT FOR REPLICATION
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
 Naming conventions - simple and self-explanatory
– Primary keys - PK_<TableName>
– Unique constraints - UQ_<TableName>_<Column(s)Name(s)>
– Foreign keys - FK_<ForeignTable>_<PrimaryTable>
 Checking and querying keys and constraints info
– Use the SQL API and not system tables








sp_helpconstraint
OBJECTPROPERTY
INFORMATION_SCHEMA.CHECK_CONSTRAINTS
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE
INFORMATION_SCHEMA.KEY_COLUMN_USAGE
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
INFORMATION_SCHEMA.TABLE_CONSTRAINTS
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
CREATE CLUSTERED INDEX CI_utbPhoneBook_LastName_FirstName
ON dbo.utbPhoneBook (LastName, FirstName)
WITH FILLFACTOR = 80, PAD_INDEX
ON [DEFAULT]
GO
CREATE NONCLUSTERED INDEX IX_utbPhoneBook_FirstName
ON dbo.utbPhoneBook (FirstName)
WITH FILLFACTOR = 80, PAD_INDEX
ON [DEFAULT]
GO
ALTER TABLE dbo.utbPhoneBook
ADD CONSTRAINT PK_utbPhoneBook PRIMARY KEY NONCLUSTERED (PersonID)
WITH FILLFACTOR = 80 ON [DEFAULT],
CONSTRAINT UQ_CountryCode_AreaCode_NumberBody_Extension UNIQUE
(CountryCode, AreaCode, NumberBody, Extension)
WITH FILLFACTOR = 80
ON [DEFAULT]
GO
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - Views
 Naming conventions - simple and self-explanatory
– e.g., ‘vw’ prefix to view names
 Avoid indexed views where possible
– Requires schema binding

Altering views requires more work
– Well-index the underlying tables instead
 Partitioned views
– Use carefully
– Examine execution plans to verify that views are used correctly

Ensure that parameter sniffing works as needed
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
CREATE TABLE dbo.utbPartView2005 (
TimeCol DATETIME NOT NULL CONSTRAINT CK_utbPartView2005_TimeCol
CHECK (TimeCol >= '1/1/2005' and TimeCol < '1/1/2006'),
Info
VARCHAR(1000) NOT NULL)
GO
ALTER TABLE dbo.utbPartView2005
ADD CONSTRAINT PK_utbPartView2005 PRIMARY KEY CLUSTERED (TimeCol)
GO
CREATE TABLE dbo.utbPartView2006 (
TimeCol DATETIME NOT NULL CONSTRAINT CK_utbPartView2006_TimeCol
CHECK (TimeCol >= '1/1/2006' and TimeCol < '1/1/2007'),
Info
VARCHAR(1000) NOT NULL)
GO
ALTER TABLE dbo.utbPartView2006
ADD CONSTRAINT PK_utbPartView2006 PRIMARY KEY CLUSTERED (TimeCol)
GO
CREATE VIEW dbo.vwPartView AS
SELECT * FROM dbo.utbPartView2005
UNION ALL
SELECT * FROM dbo.utbPartView2006
GO
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Practices for Data Definitions - cont’d
SELECT *
FROM dbo.vwPartView
WHERE TimeCol = '3/5/2005'
DECLARE @Time DATETIME
SET @Time = '3/5/2005'
SELECT *
FROM dbo.vwPartView
WHERE TimeCol = @Time
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices
 Standardize naming convention
– e.g., ‘fn’ prefix for functions, ‘usp’ prefix for store procedures
 Self-explanatory code
– Well written comments throughout the code lines
– Headers - functions, procedures, views
GO
/*==================================================================================
NAME:
uspGetDuplicateIndexes
DESCRIPTION:
Duplicate indexes are defined as distinct indexes that contain
the same set of columns, in the same order. This script
detects whether there are any such user defined indexes in the
database, and returns their following information:
(01) The object (table or indexed view) name that has
a duplicate index
(02) The object type (table or indexed view)
(03) The columns that participate in the duplicate index
(04) Index name
(05) Index description (i.e., clustered, non-clustered,
ON PRIMARY, etc.)
.
.
==================================================================================*/
CREATE PROCEDURE uspMyProc
AS
. . .
GO
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - cont’d
/*==================================================================================
NAME:
uspGetDuplicateIndexes
DESCRIPTION:
Duplicate indexes are defined as distinct indexes that contain
the same set of columns, in the same order. This script
detects whether there are any such user defined indexes in the
database, and returns their following information:
(01) The object (table or indexed view) name that has
a duplicate index
(02) The object type (table or indexed view)
(03) The columns that participate in the duplicate index
(04) Index name
(05) Index description (i.e., clustered, non-clustered,
ON PRIMARY, etc.)
The variable @IncludeSystemObjects can be set by the user
as follows: Set @IncludeSystemObjects = 1 to return results
for both system objects and user objects. To return
only user tables and indexed view column info, set
@IncludeSystemObjects = 0 (which is the variable default).
Note: This analysis only considers user defined indexes, and
not internal SQL indexes (i.e., indexes created by the
auto-statistics server configuration).
USER PARAMETERS:
NA
RESULTSET:
ObjectName (name of either table or indexed view)
ObjectType (table or indexed view)
IndexColumnsDelimList, IndexName, IndexDescription
RESULTSET SORT:
ObjectName ASC, IndexColumnsDelimList ASC
USING TABLES/VIEWS:
sysindexes
sysindexkeys
USING PROCS/FNS:
NA
REVISIONS:
DATE
DEVELOPER
DESCRIPTION OF REVISION
VERSION
=========
===============
=================================
===========
04/18/2005
Omri Bahat
Initial release
1.00
==================================================================================
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - cont’d
 First line in every stored procedure
– SET NOCOUNT ON


Reduced processing overhead
Crucial in applications that connect via ADO 2.X (e.g., VB 6.0)
– SET NOCOUNT OFF


Should be applied before returning resultsets
Reapply SET NOCOUNT ON as needed
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - Do’s and Dont’s
 Always specify the referenced object owner (tables, procs, fns, etc.)
 Retrieving TOP X records
– Don’t:
– Do:
SET ROWCOUNT X
SELECT TOP X …
(X can be a calculated in 2005)
 Always use “new” SQL
– Don’t (“old” SQL):
D
SELECT
FROM
WHERE
– Do (“new” SQL):
F
FullName = a.LastName + ', ' + a.FirstName,
b.Address
dbo.utbPhoneBook a WITH (NOLOCK),
dbo.utbAddresses b WITH (NOLOCK)
a.PersonID = b.PersonID
SELECT
a.LastName + ', ' + a.FirstName AS FullName,
b.Address
FROM dbo.utbPhoneBook a WITH (NOLOCK)
INNER JOIN dbo.utbAddresses b WITH (NOLOCK)
ON a.PersonID = b.PersonID
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - Cont’d
 Only use SELECT in data retrieval operations
– Don’t:
DECLARE @MyIntVar INT
DECLARE @MyTableVar TABLE (MyCol INT)
D
SELECT
@MyIntVar = 3
INSERT INTO @MyTableVar
SELECT 4
– Do:
F
DECLARE @MyIntVar INT
DECLARE @MyTableVar TABLE (MyCol INT)
SET @MyIntVar = 3
INSERT INTO @MyTableVar(MyCol)
VALUES(4)
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - Cont’d
 Don’t be lazy!
– Write more code to save confusion
– Shortcuts affect code clarity and lead to ambiguities and errors
SELECT
D
a.LastName + ', ' + a.FirstName AS FullName,
a.FirstName
FROM
dbo.utbPhoneBook a WITH (NOLOCK)
ORDER BY 1
F
D
SELECT
a.LastName + ', ' + a.FirstName AS FullName,
a.FirstName
FROM
dbo.utbPhoneBook a WITH (NOLOCK)
ORDER BY a.LastName + ', ' + a.FirstName
EXEC uspMyProc @Val1, @Val2, @Val3 OUTPUT
F
EXEC dbo.uspMyProc
@Param1 = @Val1,
@Param2 = @Val2,
@Param3 = @Val3 OUTPUT
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - Heads up!
 Rule of thumb, especially in high-volume environments
Anything that can go wrong, will go wrong
 NEVER(!) use cursors in code
– Slow performance
– GLOBAL cursors will result in error if referenced by several code objects
– Anything that can be done with cursors can be done with WHILE loops
 Fully understand and know the impact of called procedures
– e.g., xp_sendmail - has memory leaks! Can crash the server!
– Instead, use xp_sendsmtp
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices -cont’d
 Fully understand the functionality and overhead in each SQL command
– e.g., Checking for NULL values
DECLARE @MyIntVar INT
IF @MyIntVar = NULL
PRINT 'Y'
ELSE
PRINT 'N'
N
IF @MyIntVar IS NULL
PRINT 'Y'
ELSE
PRINT 'N'
Y
F
IF ISNULL(@MyIntVar, 1) = 1
PRINT 'Y'
ELSE
PRINT 'N'
Y
IF COALESCE(@MyIntVar, -999) = -999
PRINT 'Y'
ELSE
PRINT 'N'
Y
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - cont’d
 Dynamic SQL - EXEC vs. sp_executesql
– sp_executesql - can cache and reuse execution plans
– EXEC cannot
– Warning: both commands can prompt procedure recompilation
 Table variables vs. temp tables
– Table variables



Not transacted
Non-indexed
No referential integrity
– Temp tables



May contain statistics, thus prompt procedure recompilation
Support parallelism
Support INSERT … EXEC …
INSERT INTO #utbMyTable
EXEC sp_helpconstraint @objname = ‘utbPhoneBook', @nomsg = 'nomsg'
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - cont’d
 Do not query system tables whenever possible
– Use SQL server APIs instead

INFORMATION_SCHEMA objects
– e.g., INFORMATION_SCHEMA.TABLES, .COLUMNS, …

Service stored procedures
– e.g., sp_helpjob, sp_helpconstraint, sp_helpindex…

The property methods (meta-data functions)
– OBJECTPROPERTY, COLUMNPROPERTY, INDEXPROPERTY, …

Meta data, system functions and variables
– @@PROCID, @@SERVERNAME, …
 NEVER(!) use non-documented stored procedures
– They are not guaranteed to be supported in upcoming service packs
– e.g., sp_msforeachdb, xp_sqlagent_enum_jobs
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - Locking
 Use the least restrictive locking / transaction mode
– NOLOCK reads wherever possible:


Reduce locking and contention
Reduce transactional consistency overhead
SELECT * FROM dbo.utbPhoneBook WITH (NOLOCK)
– Remember to


SET TRANSACTION ISOLATION LEVEL
Crucial when querying over linked servers
Wherever possible use READ UNCOMMITTED
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - Security
 Grant permissions to roles, not individuals
– Map individual users to roles as needed
 Grant minimum permissions possible to support functionality
– Special care with db_owner, db_ddladmin, db_accessadmin
 Never use sp_OACreate/Destroy - vulnerable code!
 Watch out for pwdencrypt and pwdcompare
– Use of these commands hints password crackers
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - Security
 Leave the use of sp_configure to DBAs
– Do not use it in procedures
 Avoid using non-secure procedures (partial list)
sp_sdidebug
xp_dirtree
xp_enumerrorlogs
xp_findnextmsg
xp_grantlogin
xp_makewebtask
xp_perfsample
xp_revokelogin
xp_servicecontrol
xp_sqlinventory
xp_startmail
xp_execresultset
xp_regdeletekey
xp_regenumvalues
xp_availablemedia
xp_dropwebtask
xp_enumqueuedtasks
xp_fixeddrives
xp_logevent
xp_msver
xp_perfstart
xp_runwebtask
xp_snmp_getstate
xp_sqlregister
xp_stopmail
sp_execresultset
xp_regdeletevalue
xp_regread
xp_cmdshell
xp_dsninfo
xp_enumgroups
xp_getfiledetails
xp_loginconfig
xp_perfend
xp_readerrorlog
xp_schedulersignal
xp_snmp_raisetrap
xp_sqltrace
xp_subdirs
xp_printstatements
xp_regenumkeys
xp_regwrite
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
xp_deletemail
xp_enumdsn
xp_eventlog
xp_getnetname
xp_logininfo
xp_perfmonitor
xp_readmail
xp_sendmail
xp_sprintf
xp_sscanf
xp_unc_to_drive
xp_displayparamstmt
xp_regaddmultistring
xp_regremovemultistring
Best SQL Coding Practices - Errors & logging
 Standardize error handling and logging policies
– Make sure that errors could be captured by any caller to the proc
CREATE PROC dbo.uspMyProc
...
@ErrCode INT = 0 OUTPUT,
@ErrMsg NVARCHAR(4000) = N'' OUTPUT
AS
SET NOCOUNT ON
DECLARE @LogCaller NVARCHAR(128)
...
SET @LogCaller = OBJECT_NAME(@@PROCID)
SET @ErrMsg = N''
...
EXEC @RetErr = dbo.uspCalledProc
@Param1 = @Val1,
@ErrCode = @tmpErrCode OUTPUT,
@ErrMsg = @tmpErrMsg OUTPUT
IF @@ERROR <> 0 OR @RetErr > 0 OR @tmpErrCode > 0
BEGIN
SET @ErrMsg = @ErrMsg + CHAR(10) + @tmpErrMsg
IF @tmpErrCode > @RetErr
SET @ErrCode = @tmpErrCode
ELSE
SET @ErrCode = @RetErr
EXEC dbo.uspLogError @LogCaller = @LogCaller, @ErrCode = @ErrCode, @ErrMsg = @ErrMsg
END
IF @ErrCode > 2
RETURN @ErrCode
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best SQL Coding Practices - Errors handling
 SQL 2005 error handling features
– TRY & CATCH
– New error functions
CREATE PROCEDURE uspGetErrorInfo
AS
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
GO
BEGIN TRY
-- Generate divide-by-zero error.
SELECT 1/0
END TRY
BEGIN CATCH
-- Execute error retrieval routine.
EXECUTE dbo.uspGetErrorInfo
END CATCH
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Preparing for code deployment:
- Rollout / rollback packages
- Rollout results and verification
- Testing database code
Best Code Deployment Practices
 Every release MUST have a rollout and a rollback package
– Production must be restored to previous state upon an error
– Write rollout scripts so that they could be run multiple times
IF OBJECT_ID(‘utbMyTable', 'U') IS NOT NULL
DROP TABLE dbo.utbMyTable
GO
CREATE TABLE dbo.utbMyTable ...
 Write rollout verification - to be returned to dev from QA/production
SET @TableName = ‘utbMyTable'
IF OBJECT_ID(@TableName, 'U') IS NOT NULL
BEGIN
SELECT 'Table ' + @TableName + ' created successfully on ' + db_name() AS Result
PRINT('Table ' + @TableName + ' created successfully on ' + db_name())
END
ELSE
BEGIN
SELECT 'Table ' + @TableName + ' creation error on ' + db_name() AS Result
PRINT('Table ' + @TableName + ' creation error on ' + db_name())
END
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Code Deployment Practices - Heads up!
 Ensure that scripts are run in correct order
– Make sure that all dependencies are released correctly


A proc that depends on a table can be release before the table is available
Not recommended under best practices - sysdepends will not be updated
 Do not trust the data in sysdepends system table
– Not a reliable source of data
IF OBJECT_ID(‘utbPhoneBook', 'U') IS NOT NULL
DROP TABLE dbo.utbPhoneBook
GO
CREATE PROC dbo.uspMyProc
AS
SELECT * FROM dbo.utbPhoneBook WITH (NOLOCK)
GO
CREATE TABLE dbo.utbPhoneBook ...
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Code Deployment Practices - cont’d
 Creating new objects
– CREATE statement can be used safely
 Altering existing objects
– Do not DROP and (re)CREATE

Results in loss of permissions, downtime
– Use ALTER instead


Minimizes downtime
No loss of permissions
– Altering views - Heads up!
Must run this immediately after view is altered
EXEC sp_recompile @objname = <ViewName>

Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Code Deployment Practices - cont’d
 Renaming existing objects
– Do not rename procedures, views, triggers - ALTER them instead



syscomments stores the code of those (and other) objects
syscomments is not updated to reflect the rename
When object is scripted from the database - old name is used!
– Renaming views, tables, columns, and other objects


Find all dependencies first
Do not use syscomments or sp_helptext
– SELECT object_name(id) from syscomments where text like ‘%utbPhoneBook%’
– syscomments chops the code line at 8000 chars
– sp_helptext chops the code line at 256 chars
– Code comments not omitted
Using syscomments or sp_helptext will result
in false negatives and false positives
Reliable dependency scripts available on http://education.sqlfarms.com
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Code Deployment Practices - cont’d
 Before releasing functions, procedures, and views, tables
– Check execution plans of proc/function queries



Especially on performance sensitive objects
Tune queries as needed
DO NOT force queries to use specific indexes
– See the BOL for the SELECT and WHERE clause
– Let the optimizer do its job
– Simulate production data-volume where possible

Volume, statistics, and cached plans impact the execution plan
– Revisit table design (e.g., indexes) based on execution plans

Volume, statistics, and cached plans impact the execution plan
 Make sure to pass all needed documentation and info
– Schema changes, users / logins, new features
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Best Code Deployment Practices - Attention
 Pay special attention to various scenarios
– DB and server names in QA / Production may not be the same as dev
– Code may be release on a different number of DBs in production than in dev

e.g.,
Production has 7 Web databases, for load balancing
Dev has 1 database for simulation purposes
– Production user / login names may be different
Prepare and pass run-time variables that will be
set by DBAs before deployment
– Make sure that the release code is clean and executes smoothly

Keep your DBAs happy!
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
QA - Testing database releases
 Doubt everything!
 Document DB objects and schema, if possible
 Read the DB code carefully
– Only then deploy release to QA
 Compose automatic DB tests
– Check for all rules and best practices listed so far
– Check functionality through automated tests
– Check high data volumes and performance
 Consult developers and DBAs as needed
 Return non-satisfactory code to dev
 Eventually, release code to production
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Production - Deploying DB code by DBAs
 Read the DB code carefully
 Identify potential issues
– Consult developers as needed
– DBAs typically understand SQL server better than developers
 Clear all ambiguities and open issues
 Consult developers and DBAs as needed
 Set run-time variables as dictated by developers
 Deploy the code to production, and prepare for rollback
 Monitor the rollout and verify results. Rollback if needed.
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Comments and questions
Remember - this is just the tip of the iceberg…
Copyright © 2005-2006 SQL Farms, Inc. All Rights Reserved.
Thank you
SQL Farms Solutions, Inc.
128 Roberts Lane, Suite 201
Alexandria, VA 22314
www.sqlfarms.com