g. green 1. options include: script files already covered apis last course topic ...
TRANSCRIPT
INTRODUCTION TO T-SQL
G. Green 1
ACCESSING DATABASES FROM APPLICATION PROGRAMS
Options include: Script Files already covered APIs last course topic Database-Stored Code our focus
2
INTERNET RESOURCES T-SQL Basicshttp://www.sql-server-performance.com/articles/dba/stored_procedures_basics_p2.aspx
Cursorshttp://www.sqlteam.com/article/cursors-an-overview
Parametershttp://www.mssqltips.com/sqlservertutorial/162/how-to-create-a-sql-server-stored-procedure-with-parameters/
Good Practices look at this one!http://sqlblog.com/blogs/aaron_bertrand/archive/2008/10/30/my-stored-procedure-best-practices-checklist.aspx
3
DATABASE-STORED CODE Program code stored in database
T-SQL CLR Languages (C#, VB.net, …)
Good for: sharing code performance Enforcing security, business rules, audits
4
Procedure A------------------- SQL… SQL......-------------------end A
Application Program-------------------execute A-------------------execute B
Database
DATABASE-STORED CODE, CON’T...Stored Procedure
T-SQL blockProcedural programming featuresstored in database* invoked by name* accepts arguments
Database Trigger T-SQL blockProcedural programming featuresstored in database* invoked by DML (Insert, Update, or Delete)* accepts no arguments
5
CREATE STORED PROCEDURE: FROM SCRATCH
6
CREATE PROCEDURE <procedure_name>[parameter_information]
AS
DECLARE
/* program variables defined here */
BEGIN
/* program logic goes here */
END
EXAMPLE 1: SIMPLE PROC
7
/* retrieves and displays all customer records */
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE NAME = 'show_all_customers' AND TYPE = 'P') DROP PROCEDURE show_all_customers;GO
CREATE PROCEDURE show_all_customers
AS
BEGIN
SELECT customer_id, customer_name, postal_code FROM customer_t;
END;
INVOKE EXAMPLE 1 PROCEDURE
8
execute show_all_customers;
-- OR
Exec show_all_customers;
EXAMPLE 2: PARAMETERS, VARIABLES, PROGRAM LOGIC, & PRINTING
9
/* retrieves a specific customer record based on a given customer ID. *//* if the customer lives in the state of FL, then append “-1111” after the zip code & print a message to user *//* CONVERTs needed since we're concatenating numeric data to text data */
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE NAME = 'alter_zip_and_print' AND TYPE = 'P') DROP PROCEDURE alter_zip_and_print;GO
CREATE PROCEDURE alter_zip_and_print @desired_customer numeric(5) = null
AS
DECLARE @ID numeric(4), @state varchar(2), @pcode varchar(12);
BEGIN SELECT @ID = customer_id, @pcode = postal_code, @state = state FROM customer_t WHERE customer_id = @desired_customer;
IF @state = 'fl' BEGIN SET @pcode = @pcode + '-1111' UPDATE customer_t SET postal_code = @pcode WHERE customer_id = @desired_customer; print 'cust#: ' + convert(varchar, @desired_customer)+' zipcode changed to: ' + @pcode; END;END;GO
EXAMPLE 2: INVOKE AND VERIFY PROCEDURE
10
/* statement below included ONLY so I can undo changes after demo. You DO NOT need to do this */
Set implicit_transactions onGO
/* show customer 9's record before calling procedure */
Select * from customer_t where customer_id = 9;
exec alter_zip_and_print @desired_customer = 9;-or-exec alter_zip_and_print 9GO
/* check to see if procedure updated customer 9's record */
Select * from customer_t where customer_id = 9;GO
/* statement below included ONLY so I can undo changes after demo. You DO NOT need to do this */
Rollback;Set implicit_transactions off
MULTIPLE-RECORD RETRIEVALS
Require cursors1. Declare CURSOR2. OPEN cursor3. FETCH data from cursor4. CLOSE & DEALLOCATE cursor
Use control structures to process each record WHILE <expression>
…[BREAK can be used to force exit from WHILE
loop]END;
IF <expression> <statement> ELSE <statement>
IF <expression> BEGIN <statements> END;
ELSE BEGIN <statements> END;
11
EXAMPLE 3: CURSOR
12
/* retrieve customer records based on NAME; if customer(s) live in FL, ‘-1111’ is appended to zip */IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE NAME = 'getcust' AND TYPE = 'P') DROP PROCEDURE getcust; GO
CREATE PROCEDURE getcust @name varchar(25)ASDECLARE custcursor CURSOR FORSELECT customer_id, state, postal_code from customer_t WHERE customer_name like '%' + @name + '%';
DECLARE @cid numeric (11), @cstate varchar(2), @pcode varchar(12);
BEGIN -- logic OPEN custcursor; --find customers meeting criteria
IF @@CURSOR_ROWS = 0 BEGIN RAISERROR ('no customer found', 10,1) RETURN; END; FETCH FROM custcursor INTO
@cid, @cstate, @pcode;
/* code continued here… */
WHILE @@FETCH_STATUS = 0 BEGIN -- loop thru each customer record found
IF @cstate = 'fl'
BEGIN -- process and display old & new zip
PRINT 'id: ' + convert(varchar, @cid) + ' , name: ' + @name; PRINT 'old zip: ' + @pcode;
SET @pcode= @pcode + '-1111' UPDATE customer_t SET postal_code = @pcode WHERE customer_id = @cid;
PRINT 'new zip: ' + @pcode; PRINT ' ======================= ';
END; -- processing and displaying of zip FETCH NEXT FROM custcursor INTO
@cid, @cstate, @pcode;
END; -- looping thru records
CLOSE custcursor;DEALLOCATE custcursor;END; -- logic
EXAMPLE 3: INVOKE AND VERIFY PROCEDURE
13
Set implicit_transactions onGO
Update customer_t set state='fl' where customer_id=2;
Select * from customer_t where customer_name like '%furn%';
Exec getcust 'furniture'GO
Select * from customer_t where customer_name like '%furn%';GO
Rollback;Set implicit_transactions off
EXAMPLE 4: ANOTHER CURSOR
14
/* for a given order, show the total number of products on the order, and the description of each product on the order */IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE NAME = 'showordereditems' AND TYPE = 'P') DROP PROCEDURE showordereditems;GO
CREATE PROCEDURE showordereditems @orderid numeric(11)ASDECLARE ordercursor CURSOR FOR select ol.order_id, ol.product_id, p.product_description from order_line_t ol, product_t p where ol.product_id = p.product_id and ol.order_id = @orderid;DECLARE @oloid numeric(11), -- storing order # @olpid numeric(11), -- storing product # @pdesc varchar(50), -- storing product description @mycount numeric(4); -- to store the number of products on orderBEGIN -- logic SET @mycount=0; -- initialize the counter
SELECT @mycount = count(*) FROM order_line_t ol WHERE ol.order_id = @orderid; -- calculate total # of products on given order
PRINT '** order# ' + convert(varchar,@orderid) + ' has ' + convert(varchar,@mycount) + ' products:**'; -- print the total # of products on the order OPEN ordercursor; -- find the products associated with the given order
IF @@CURSOR_ROWS=0 BEGIN RAISERROR ('order not found',10,1) RETURN; END;
FETCH FROM ordercursor INTO @oloid, @olpid, @pdesc;
WHILE @@FETCH_STATUS = 0 -- loop thru each product on the order BEGIN PRINT 'product#: ' + convert (varchar, @olpid ) + ' product desc: ' + @pdesc; -- print each product on the order FETCH NEXT FROM ordercursor INTO @oloid, @olpid, @pdesc; END; CLOSE ordercursor; DEALLOCATE ordercursor; END; -- logic
EXAMPLE 4: INVOKE PROCEDURE
15
Exec showordereditems 1002GO
SUMMARY: STEPS TO CREATE / INVOKE PROCEDURES
Store code that creates procedure in a script Run and debug script in SSMS
Creates & stores procedure in database
Invoke procedureIssue "execute" command
Include parameter values where required
16
TRIGGERS
Common Uses: Implementing RI Complex defaults Interrelation constraints/updates Updating views Auditing business activities
2 Kinds in SQL Server: After Instead of (see
http://blog.sqlauthority.com/2013/01/24/sql-server-how-to-use-instead-of-trigger-guest-post-by-vikas-munjal-koenig-solutions/)
17
CREATE TRIGGER: FROM SCRATCH
18
CREATE TRIGGER <trigger_name> ON <table_name><AFTER | INSTEAD OF><INSERT [,] UPDATE [,] DELETE>
AS
DECLARE
/* program variables defined here */
BEGIN
/* program logic goes here */
END
EXAMPLE 1: MAINTAIN COUNTER
19
/* maintain the orders placed counter in the customer table *//* add 1 to the counter each time a customer places a new order */
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'add_order_placed' AND type = 'TR') DROP TRIGGER add_order_placed;GO
CREATE TRIGGER add_order_placedON order_t AFTER INSERTASDECLARE @customer AS numeric(11,0)BEGIN SELECT @customer = customer_ID FROM INSERTED;
UPDATE customer_t SET orders_placed = orders_placed+1 WHERE customer_t.customer_ID = @customer;END;GO
EXAMPLE 1: MAINTAIN COUNTER, CONT…
20
/* Maintain the orders placed counter in the customer table *//* Every time the customer# on an order is changed, the orders_placed column in the customer table is updated *//* to reflect the # of orders placed by both the original and new customer */
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'change_order_placed' AND type = 'TR') DROP TRIGGER change_order_placed;GO
CREATE TRIGGER change_order_placedON order_t AFTER UPDATEASDECLARE@newcustomer AS numeric(11,0),@oldcustomer AS numeric(11,0)BEGIN SELECT @newcustomer = customer_ID FROM INSERTED; SELECT @oldcustomer = customer_ID FROM DELETED;
UPDATE customer_t SET orders_placed = orders_placed+1 WHERE customer_t.customer_ID = @newcustomer;
UPDATE customer_t SET orders_placed = orders_placed-1 WHERE customer_t.customer_ID = @oldcustomer;END;GO
FIRE/VERIFY TRIGGERSSet implicit_transactions onGO
/* check status of customer’s orders_placed counter before placing new orders */select customer_id, orders_placed from customer_t where customer_id=10;
/* fire insert trigger by placing orders for customer #10 */insert into order_t values (9900, '10-OCT-01', 10);insert into order_t values (9901, '10-OCT-01', 10);insert into order_t values (9902, '10-OCT-01', 10);
/* issue select statement to verify that trigger updated orders_placed counter */select customer_id, orders_placed from customer_t where customer_id=10;
/* select status of customer’s orders_placed counters before placing new orders */select customer_id, orders_placed from customer_t where customer_id=10;select customer_id, orders_placed from customer_t where customer_id=1;
/* fire update trigger by changing the customer# of one of the orders for customer #10 */update order_t set customer_id = 1 where order_id = 9901;
/* issue select statement to verify that the orders_placed counter is correct */select customer_id, orders_placed from customer_t where customer_id=10;select customer_id, orders_placed from customer_t where customer_id=1;GO
Rollback;Set implicit_transactions off
EXAMPLE 2: SETTING DEFAULT VALUE /* when a new product is added, if the standard price is NOT given, then set the product’s standard price to either: *//* the highest standard price of a product in the same product line if one exists, OR to $300 */
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'set_standard_price' AND type = 'TR') DROP TRIGGER set_standard_price;
GO
CREATE TRIGGER set_standard_price ON product_t AFTER INSERT AS
DECLARE@newproductlineid as numeric(11,0),@newstandardprice as numeric(6,2),@higheststandardprice as numeric(6,2),@productID as numeric (11,0)BEGIN SELECT @productID=product_ID, @newproductlineid = product_line_id , @newstandardprice = standard_price FROM INSERTED;
IF @newstandardprice IS NULL BEGIN
SELECT @higheststandardprice = MAX(standard_price) FROM product_t WHERE product_line_id = @newproductlineid;
IF @higheststandardprice IS NOT NULL
SET @newstandardprice = @higheststandardprice ELSE SET @newstandardprice = 300;
UPDATE product_t SET standard_price = @newstandardprice WHERE product_id = @productID;
END --end IF
END; -- end programGO
22
FIRE/VERIFY TRIGGERSet implicit_transactions onGO
/* issue select statement to view product table before adding new products */select * from product_t;
/* fire insert trigger adding new products to the product_t table*/
insert into product_t values (999,null,null,null,null,20001);insert into product_t values (998, null, null, 123, 3, 33333);Insert into product_t values (997,null,null,null,null,44444);
/* issue select statement to verify that trigger updated standard prices for products */
select product_id, product_line_id, standard_price from product_t where product_id>900;
GO
Rollback;Set implicit_transactions off
23