Database Programmin - Cursors Triggers and Stored Procedures
Database Programmin - Cursors Triggers and Stored Procedures
OPEN curProduct
At this point, the record pointer is positioned before the first row. The
FETCH NEXT command navigates the pointer to the next record and
returns a comma-delimited list of column values. In this case, the
pointer is moved to the first row. Individual variables can be used to
capture the values of the current row's column values:
OPEN curProduct
FETCH NEXT FROM curProduct INTO @ProdID, @ProdName
WHILE @@Fetch_Status = 0
BEGIN
PRINT @ProdName
FETCH NEXT FROM curProduct INTO @ProdID, @ProdName
END
CLOSE curProduct
DEALLOCATE curProduct
Use of Cursors
Use conditional statements to decide
whether to perform related operations, such
as inserting or deleting records.
Use cursors to conditionally call different
stored procedures under different
conditions, to perform practically any
combination of operations.
User-Defined Functions
Scalar functions
Multi-statement table-valued functions
Inline table-valued functions
Scalar functions
A scalar function accepts any number of parameters and returns one value.
Input parameters are declared within parentheses followed by the return value
declaration.
All statements must be enclosed in a BEGIN. . . END block.
Calculate the age by getting the number of days between the birth date and
today's date. Because my function can't call the nondeterministic GETDATE()
function, this value must be passed into the function using the @Today
parameter.
The number of days is divided by the average number of days in a year to
determine the result:
EXECUTE spProductCosts 1 or
EXECUTE spProductCosts @SubCategory = 1
SP with Multiple Parameters
CREATE PROCEDURE spProductsByCost
@SubCategoryID Int, @Cost Money
AS
SELECT ProductID, Name, ProductNumber, StandardCost
FROM Product WHERE ProductSubCategoryID =
@SubCategoryID AND StandardCost > @Cost
Using SQL, the multiple parameters can be passed in a
comma-delimited list in the order they were declared:
EXECUTE spProductCosts 1 or
EXECUTE spProductCosts @SubCategory = 1
Use Parameters to Return Values
This example shows how to pass the SubCategoryID using
an input parameter and return the record count using an
output parameter:
CREATE PROCEDURE spProductCountBySubCategory
@SubCategoryID Int, @ProdCount Int OUTPUT
AS
SELECT @ProdCount = COUNT(*) FROM Product
WHERE ProductSubCategoryID = @SubCategoryID
EXECUTE spProductCountBySubCategory
@SubCategoryID = 2, @ProdCount = @Out OUTPUT
ProductCountBySubCategory
-------------------------
184
An Alternative Method for Return a
Value from SP
CREATE PROCEDURE
spProductCountBySubCategory
@SubCategoryID Int
AS
DECLARE @Out Int
SELECT @Out = Count(*) FROM Product WHERE
ProductSubCategoryID = @SubCategoryID
RETURN @Out
Use SPs to Manage Records
Any program code written to perform record
operations should do so using stored
procedures and not ad-hoc SQL
expressions
– Insert, Update, Delete, and Select
Insert Procedure
Define parameters for all non-default or auto-populated
columns.
In the case of the Product table, the ProductID primary key
column will automatically be incremented because it's
defined as an identity column; the rowguid and ModifiedDate
columns have default values assigned in the table definition.
The MakeFlag and FinishedGoodsFlag columns also have
default values assigned in the table definition, but it may be
appropriate to set these values differently for some records.
For this reason, these parameters are set to the same
default values in the procedure.
Several columns are nullable and the corresponding
parameters are set to a default value of null.
If a parameter with a default assignment isn't provided when
the procedure is executed, the default value is used.
Otherwise, all parameters without default values must be
supplied
Declaring Variables for Insert
Procedure
CREATE PROCEDURE spProduct_Insert
@Name nVarChar(50) , @ProductNumber nVarChar(25) ,
@MakeFlag Bit = 1 , @FinishedGoodsFlag Bit = 1 ,
@Color nVarChar(15) = Null , @SafetyStockLevel SmallInt ,
@ReorderPoint SmallInt ,
@StandardCost Money , @ListPrice Money ,
@Size nVarChar(5) = Null ,
@SizeUnitMeasureCode nChar(3) = Null ,
@WeightUnitMeasureCode nChar(3) = Null ,
@Weight Decimal = Null , @DaysToManufacture Int ,
@ProductLine nChar(2) = Null , @Class nChar(2) = Null ,
@Style nChar(2) = Null , @ProductSubcategoryID SmallInt = Null ,
@ProductModelID Int = Null , @SellStartDate DateTime ,
@SellEndDate DateTime = Null , @DiscontinuedDate DateTime = Null
Insert Statements
AS
INSERT INTO Product ( Name , ProductNumber ,
MakeFlag , FinishedGoodsFlag , Color ,
SafetyStockLevel , ReorderPoint , StandardCost ,
ListPrice , Size , SizeUnitMeasureCode ,
WeightUnitMeasureCode , Weight ,
DaysToManufacture , ProductLine , Class , Style ,
ProductSubcategoryID , ProductModelID ,
SellStartDate , SellEndDate , DiscontinuedDate )
Select Statements
SELECT @Name , @ProductNumber ,
@MakeFlag , @FinishedGoodsFlag , @Color ,
@SafetyStockLevel , @ReorderPoint ,
@StandardCost , @ListPrice , @Size ,
@SizeUnitMeasureCode ,
@WeightUnitMeasureCode , @Weight ,
@DaysToManufacture , @ProductLine , @Class ,
@Style , @ProductSubcategoryID ,
@ProductModelID , @SellStartDate ,
@SellEndDate , @DiscontinuedDate
Execute the SP
EXECUTE spProduct_
Insert
@Name = 'Widget' , @ProductNumber = '987654321' ,
@SafetyStockLevel = 10 , @ReorderPoint = 15 ,
@StandardCost = 23.50 , @ListPrice = 49.95 ,
@DaysToManufacture = 30 , @SellStartDate = '10/1/04'
Or
EXECUTE spProduct_
Insert 'Widget', '987654321', 1, 1, Null, 10, 15, 23.50,
49.95, Null, Null, Null, Null, 30, Null, Null, Null, Null, Null,
'10/1/04'
Update Procedure: Declare all Variables
CREATE PROCEDURE spProduct_Update
@ProductID Int , @Name nVarChar(50) ,
@ProductNumber nVarChar(25) , @MakeFlag Bit = 1 ,
@FinishedGoodsFlag Bit = 1 ,
@Color nVarChar(15) = Null , @SafetyStockLevel SmallInt
, @ReorderPoint SmallInt , @StandardCost Money ,
@ListPrice Money , @Size nVarChar(5) = Null ,
@SizeUnitMeasureCode nChar(3) = Null ,
@WeightUnitMeasureCode nChar(3) = Null ,
@Weight Decimal = Null , @DaysToManufacture Int ,
@ProductLine nChar(2) = Null , @Class nChar(2) = Null ,
@Style nChar(2) = Null , @ProductSubcategoryID SmallInt
= Null , @ProductModelID Int = Null , @SellStartDate
DateTime , @SellEndDate DateTime = Null ,
@DiscontinuedDate DateTime = Null
Update Statements
AS
UPDATE Product
SET
Name = @Name , ProductNumber = @ProductNumber ,
MakeFlag = @MakeFlag , FinishedGoodsFlag = @FinishedGoodsFlag ,
Color = @Color , SafetyStockLevel = @SafetyStockLevel ,
ReorderPoint = @ReorderPoint , StandardCost = @StandardCost ,
ListPrice = @ListPrice , Size = @Size ,
SizeUnitMeasureCode = @SizeUnitMeasureCode ,
WeightUnitMeasureCode = @WeightUnitMeasureCode ,
Weight = @Weight , DaysToManufacture = @DaysToManufacture ,
ProductLine = @ProductLine , Class = @Class , Style = @Style ,
ProductSubcategoryID = @ProductSubcategoryID ,
ProductModelID = @ProductModelID , SellStartDate = @SellStartDate ,
SellEndDate = @SellEndDate , DiscontinuedDate = @DiscontinuedDate
Exec spProduct_Delete 2
Triggers
DML Triggers:
– A special type of SP, executed automatically
based on occurrence of a database event.
– Data manipulation: insert, update, delete
DDL triggers: Also on DDL events in 2005
DML Triggers
Compare before and after versions of data.
Roll back invalid modifications.
Read from other tables, including those in
other databases.
Modify other tables, including those in other
databases.
Execute local and remote stored
procedures.
Creating DML Triggers
Using system trigger templates
– SELECT * FROM sys.triggers
AFTER trigger
– Invoked when any data modification takes place but before data
are committed to the database
Basic Syntax
GO
UPDATE products
SET stock_level = stock_level + 3
WHERE state = ‘UT’
GO
UPDATE authors
SET au_fname = au_fname
WHERE state = ‘CA’
GO
--TRIGGER OUTPUT: 37 rows were updated.
Limitations of AFTER Triggers
The following restrictions apply to AFTER
triggers:
AFTER triggers can be placed only on
tables, not on views.
An AFTER trigger cannot be placed on more
than one table.
The text, ntext, and image columns cannot
be referenced in the AFTER trigger logic.
Displaying Deleted or Inserted
Records within an AFTER Trigger
Using Inserted table and Deleted table
Both tables are available to the trigger.
The changes displayed are not committed
until the trigger completes.
Codes
--Create a copy of the titles table in the BigPubs2005
database
SELECT *
INTO titles_copy
FROM titles
GO
--add an AFTER trigger to this table for testing purposes
CREATE TRIGGER tc_tr ON titles_copy
FOR INSERT, UPDATE, DELETE
AS
PRINT ‘Inserted:’
SELECT title_id, type, price FROM inserted
PRINT ‘Deleted:’
SELECT title_id, type, price FROM deleted
ROLLBACK TRANSACTION
Results of Firing the Trigger
UPDATE titles_copy
SET price = $15.05
WHERE type LIKE ‘%cook%’
Inserted:
title_id type price
-------- ------------ ---------------------
TC7777 trad_cook 15.05
TC4203 trad_cook 15.05
TC3218 trad_cook 15.05
MC3021 mod_cook 15.05
MC2222 mod_cook 15.05
Deleted:
title_id type price
-------- ------------ ---------------------
TC7777 trad_cook 14.3279
TC4203 trad_cook 14.595
TC3218 trad_cook 0.0017
MC3021 mod_cook 15.894
MC2222 mod_cook 14.9532
References
http://msdn.microsoft.com/en-us/library/ms1
89799(classic).aspx
http://msdn.microsoft.com/en-us/library/ms3
45415.aspx
http://msdn.microsoft.com/en-us/library/ms1
80169.aspx