A Stored
Procedure is a set of Structured Query Language (SQL) statements with an
assigned name, stored in the database in compiled form so that it can be
shared by a number of programs.
CREATE Procedure
Creating a new Stored Procedure using the CREATE PROCEDURE command as given below.
Stored Procedure consists of :
·
Header comments, Which includes author, date, purpose and
change history with example.
·
Procedure Name.
·
Input parameters, Output parameters if any.
·
Body of Stored Procedure
1. BEGIN
2. SET NOCOUNT
ON;
3. DECLARE Local
variables
4. T-SQL [Collection
of SQL Statements]
5. SET NOCOUNT OFF;
6. END
EXAMPLE:
/*======================================================================
AUTHOR
: Govind
CREATE DATE :
22-Aug-2014
DESCRIPTION :
Logging Error.
SNO ALTERED DATE AUTHOR DESCRIPTION
--- ---------------------- ------------- ----------------------------------------------------------------
1 09-APR-2015 Govind Changed
Condition with @@TRANCOUNT
Instead
of @ERROR
2 25-JUN-2015 Govind Added
additional parameter
@ErrorLogMethodName
@ErrorLogMethodName
SET STATISTICS TIME ON
EXEC [USP_PP_ErrorLog_Insert] 1, '1', 23, 'This is Error due to invalid
data', 'Action Table', 'Action.js','getAction'
SET STATISTICS TIME OFF
=====================================================================*/
CREATE PROCEDURE
[dbo].[USP_PP_ErrorLog_Insert]
--
Parameters for the stored procedure
@OperatorID INT,
@SystemMessageID INT = 0,
@ErrorLogLineNumber INT,
@ErrorLogMessage VARCHAR(1000) = null,
@ErrorLogFunction VARCHAR(50) = null,
@ErrorLogClassName VARCHAR(30) = null,
@ErrorLogMethodName VARCHAR(30) = null
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
BEGIN
TRANSACTION
INSERT INTO [dbo].[ErrorLog]
([ErrorLogDate]
,[SystemMessageID]
,[ErrorLogMessage]
,[OperatorID]
,[ErrorLogFunction]
,[ErrorLogClassName]
,[ErrorLogMethodName]
,[ErrorLogLineNumber])
VALUES
(GETDATE()
,@SystemMessageID
,@ErrorLogMessage
,@OperatorID
,@ErrorLogFunction
,@ErrorLogClassName
,@ErrorLogMethodName
,@ErrorLogLineNumber)
COMMIT TRANSACTION
RETURN -- 'SUCCESS'
END TRY
BEGIN CATCH
IF @@TRANCOUNT
> 0 --
@@ERROR>0
ROLLBACK
SELECT
@ErrorLogLineNumber = ERROR_LINE(),
@ErrorLogFunction
= ERROR_PROCEDURE(),
@ErrorLogMessage = CAST(ERROR_NUMBER() AS VARCHAR(15)) + '-' + ERROR_MESSAGE()
INSERT
INTO [dbo].[ErrorLog]
([ErrorLogDate]
,[SystemMessageID]
,[ErrorLogMessage]
,[OperatorID]
,[ErrorLogFunction]
,[ErrorLogClassName]
,[ErrorLogMethodName]
,[ErrorLogLineNumber])
VALUES
( GETDATE()
,@SystemMessageID
,@ErrorLogMessage
,@OperatorID
,@ErrorLogFunction
,@ErrorLogClassName
,@ErrorLogMethodName
,@ErrorLogLineNumber)
--SELECT @OutputText
AS ErrorCode
RETURN --'ERROR'
END CATCH
SET NOCOUNT OFF;
END
ALTER Procedure
Example for modifying Stored Procedure using the ALTER PROCEDURE command is given below.
ALTER PROCEDURE [dbo].[USP_PP_ErrorLog_Insert]
EXECUTE Procedure
Executing Stored Procedure consists of:
EXEC <<Procedure Name>> <<Parameters>>
EXAMPLE:
EXEC [USP_PP_ErrorLog_Insert] 1, '1', 23, 'This is Error due to
invalid data', 'Action
Table', 'Action.js','getAction'
DROP Procedure
Example for deleting the existing Stored Procedure using the DROP PROCEDURE command is given below.
EXAMPLE1:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[USP_PP_ErrorLog_Insert]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[USP_PP_ErrorLog_Insert]
GO
EXAMPLE1:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[USP_PP_ErrorLog_Insert]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[USP_PP_ErrorLog_Insert]
GO
RENAME Procedure
Example for renaming the existing Stored Procedure (from USP_PP_ErrorLog_Insert to USP_PP_ErrorLog_Upsert) is given
below.
EXAMPLE:
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[USP_PP_ErrorLog_Upsert]') AND type in (N'P', N'PC'))
AND EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[USP_PP_ErrorLog_Insert]') AND type in (N'P', N'PC'))
EXEC sp_rename 'USP_PP_ErrorLog_Insert',
'USP_PP_ErrorLog_Upsert'
Another way of renaming the existing Stored Procedure (from
USP_PP_ErrorLog_Insert to USP_PP_ErrorLog_Upsert) is, CREATE a new Stored Procedure, and then DROP the
existing Stored Procedure as given below.
EXAMPLE:
CREATE PROCEDURE [dbo].[USP_PP_ErrorLog_Upsert]
……….
……….
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[USP_PP_ErrorLog_Insert]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[USP_PP_ErrorLog_Insert]
GO
General Rules:
·
Follow the naming conventions.
·
Do not use spaces in the name of database objects.
·
Write neat, readable and meaningful comments wherever needed.
o
Use -- for single line comment
o
Use /* ……*/ for block comments.
·
Do not use SQL keywords as the name of database objects, In cases
where this is necessary, surround the object name with brackets, such as [Year].
Coding:
Good database design and coding will achieve all the required
project functionality and deliver acceptable performance. It takes into quality
delivery to your customer.
·
Optimize queries
using the tools provided by SQL Server.
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.
EXAMPLE
1:
IF EXISTS (SELECT 1 FROM
dbo.Action WITH (NOLOCK) WHERE
ActionID = 50)
Instead Of:
IF EXISTS (SELECT COUNT(ActionID) FROM dbo.Action WHERE
ActionID = 50)
EXAMPLE
2:
Consider the following query to
find the second highest offer MaxManPayAmount from the Operator table:
SELECT MIN(MaxManPayAmount) FROM Operator WHERE OperatorID IN
(SELECT
TOP 2 OperatorID FROM Operator ORDER BY MaxManPayAmount Desc)
The same query can be re-written
using a derived table, as shown below, and it performs generally as fast as the
above query:
SELECT MIN(opr.MaxManPayAmount) FROM
(SELECT
TOP 2 MaxManPayAmount FROM dbo.Operator WITH (NOLOCK) ORDER BY
MaxManPayAmount DESC) AS opr
·
Do not use SELECT *, instead practice writing required column names
after the SELECT statement.
·
Do not use SQL keywords as the name of database objects, In cases
where this is necessary, surround the object name with brackets, such as [Year].
·
Use table WITH
(NOLOCK) command for SELECT statement which avoids a
deadlock occurrence.
·
Avoid dynamic SQL
statements as much as possible.
o
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.
·
Avoid using <> as
a comparison operator.
o
Use ID IN (1,3,4,5)
instead of ID <> 2.
·
Avoid unnecessary use of temporary tables.
o
Use 'Derived tables' or CTE
(Common Table Expressions) wherever possible, as they perform better.
·
Use SET NOCOUNT ON at
the beginning of stored procedures, SQL batches and Triggers. This improves the
performance of stored procedures.
o
SET
NOCOUNT ON 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.
·
Place all DECLARE
statements before any other code in the stored procedure.
·
Do not use cursors or application loops to do inserts.
o
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.
·
Fully qualify tables and column names.
o
Prefix table names with the owner name. This improves readability
and avoids unnecessary confusion. Microsoft SQL Server Books Online states that
qualifying table names with owner names help in execution plan reuse, further
boosting performance.
Example: dbo.FeatureAction
·
Use ANSI 92 Joins instead
of old style joins his improves readability and avoids unnecessary confusion.
False code:
SELECT * FROM dbo.FeatureAction,
Feature
WHERE
Feature.FeatureID =
FeatureAction.FeatureID
True code:
SELECT FeatureAction.FeatureID, Feature.FeatureName FROM dbo.FeatureAction
INNER JOIN dbo.Feature WITH (NOLOCK) ON Feature.FeatureID = FeatureAction.FeatureID
·
Avoid the use of cross
joins, if possible.
·
Avoid to define default
values for parameters in stored procedure unless or until it is needed.
o
If a default is needed, the front end will supply the value.
·
Do not use the RECOMPILE
option for stored procedures.
·
Do not use column numbers in the ORDER BY clause. Use appropriate column name.
·
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.
·
Create STORED PROCEDURE
as much as possible with business logic on the same database for accessing data.
o
Do not prefix stored procedures with ‘sp_’, prefix.
o
The prefix sp_ is
reserved for system stored procedures that ship with SQL Server. Whenever SQL
Server encounters a procedure name starting with sp_, it first tries to locate
the procedure in the master database, then it looks for any qualifiers (database, owner) provided, then it tries dbo
as the owner. Time spent locating the stored procedure can be saved by avoiding
the "sp_" prefix.
o
Do prefix stored procedures with “USP_”.(user defined stored
procedure)
·
Prefix table names with the owner name.
o
Example: dbo.Action instead
of Action
·
You might need the length of a string variable in many places of
your stored 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.
· If Multiple records to be
stored /deleted to table at an attempt, pass XML data as parameter value to stored procedure for BULK INSERT OR BULK UPDATE OR BULK DELETE.
XML data should be created/formed from application server and pass it to xml.
Example: Bulk Insert.
DECLARE @XML
AS XML
--SET @XML =
(select * from ED for xml auto)
SET @XML
= '<ED
EID="1" DID="1" SN="1"/>
<ED
EID="1" DID="2" SN="2"/>
<ED
EID="1" DID="3" SN="3"/>
<ED
EID="2" DID="4" SN="1"/>
<ED
EID="2" DID="5" SN="2"/>
<ED
EID="3" DID="7" SN="2"/>
<ED
EID="4" DID="7" SN="1"/>
<ED
EID="4" DID="8" SN="2"/>
<ED
EID="5" DID="4" SN="1"/>
<ED
EID="5" DID="5" SN="2"/>
<ED
EID="5" DID="6" SN="3"/>
<ED
EID="6" DID="7" SN="1"/>
<ED
EID="6" DID="8" SN="2"/>
<ED
EID="6" DID="9" SN="3"/>
<ED
EID="7" DID="0" SN="1"/>'
INSERT INTO EmployeeDegree
SELECT
DOC.col.value('@EID', 'INT') as EmployeeID,
DOC.col.value('@DID', 'INT') as DegreeID,
DOC.col.value('@SN', 'INT') as Sequence
FROM @XML.nodes('ED') DOC(col)
·
Access tables in the same
order in your stored procedures and triggers consistently.
·
Do not call functions
repeatedly within your stored procedures, triggers, functions and batches.
·
The RETURN statement is
meant for returning the execution status only, but not data.
·
Return multiple result sets
from one stored procedure to avoid trips from the application server to SQL
server.
Query the list of Stored Procedure
EXAMPLE:
SELECT * FROM sysobjects
WHERE xtype = 'P' --'TR', FN, 'P', 'V'
EXAMPLE:
SELECT DISTINCT so.name, so.xtype, sc.TEXT
FROM syscomments sc
INNER JOIN sysobjects so ON sc.id=so.id
WHERE sc.TEXT LIKE '%Chk%'
AND so.xtype IN ('P', 'TR', 'FN', 'P', 'V')
No comments:
Post a Comment