70
Simple Programming Part 1 SECTION 7 Procedures and Functions

Simple Programming Part 1 SECTION 7 Procedures and Functions

Embed Size (px)

Citation preview

Simple ProgrammingPart 1

SECTION 7

Procedures and Functions

Introduction

• SQL is only a query language

• T-SQL (SQL) does not have features that allow sophisticated computations

• Microsoft SQL solution• T-SQL Procedures and Functions

• Looking at basics

• Users need more sophisticated SQL-oriented programming capabilities

Stored Procedures and Functions

• Lets you use all the SQL data manipulations

• Fully SQL data types

• Allows you to do sophisticated processing

The Front End

• Lets you create SQL data manipulations

• Also lets you do programming

• The usual front-end displayed to the user

Stored Procedures

• Stored in the database

• A stored procedure is a group of Transact-SQL statements compiled into a single execution plan.

IF (@QuantityOrdered < (SELECT QuantityOnHand

FROM Inventory

WHERE PartID = @PartOrdered) )

BEGIN

-- SQL statements to update tables and process order.

END

ELSE

BEGIN

-- SELECT statement to retrieve the IDs of alternate items

-- to suggest as replacements to the customer.

END

A Generic Example

Stored Functions

• A function is designed to return a value used within a larger SQL statemen

• Functions cannot be used to make changes to the database, whereas stored procedures allow you to do inserts and updates, etc.

Triggers

• EG: When users log on or off

• Gets executed automatically– Need a triggering event

Basic Procedure Structure

• Four sections– Header section (optional)– Declaration section (optional)– Execution section– Exception section (optional)

Header Section

• Anonymous block header

• The specification of the function-- ==================

-- Author

-- Create date:

-- Description

-- ==================

• Block labels make it easier to read codes

Declaration Section (Optional)

• Ends at keyword – BEGIN

• Starts with keyword– DECLARE

• Contains declarations for• Variables, constants, cursors, exceptions

• What are we doing here?

• When a procedure has finished executing– Declarations stop existing

DECLARE @num_a NUMERIC = 6,@num_b NUMERIC;

Execution Section

• Ends with END

• Starts with keyword– BEGIN

Exception Section

• Ends with END CATCH

• Starts with keyword– BEGIN CATCH

In our example:

BEGIN try

-- Generate a divide-by-zero error.

SET @num_b = 0;

SET @num_a = @num_a / @num_b;

PRINT @num_a;

END try

BEGIN catch

SELECT ERROR_MESSAGE() AS ErrorMessage;

END catch

The TRY statement lets you test a block of code for errors

The CATCH statement lets you handle the error

Creating a Simple Procedure

Create procedure test_procasSelect * from customer;

• We will try the following code

• Use

• CREATE procedure_name

• AS procedure_body

CREATE PROCEDURE test_procASDECLARE @alpha nVARCHAR(30)BEGINSET @alpha = ‘HELLO WORLD’PRINT @alphaEND

Notice the different colouring

Calling Procedures or Functions

Without any parameters

Execute procedure_name;

With formal parameters

Execute procedure_name @alpha = 50, @bravo = 20;

• A procedure or function may not have formal parameters or default values

Variables

• Storing numbers– NUMERIC datatype

• Storing text– CHAR, VARCHAR, nVARCHAR datatypes

• Variables:• Essentially containers with name tags

Unicode Characters• Unicode is a computing industry standard for the consistent encoding,

representation and handling of text expressed in most of the world's writing systems.

• Unicode's success at unifying character sets has led to its widespread and predominant use in the internationalization of computer software.

• nVARCHAR

• All modern operating systems and development platforms use Unicode internally.

Declaring Variables

• A valid variable_name

– Up to 30 characters

– Letters, 0-9, underscore(_), $, and #

– Starts with @

– Cannot use a reserved word that is used by the DBMS

• The syntax@variable_name datatype or

@variable_name (datatype) = default_value_expression

e.g. @num_b NUMERIC or

@num_a NUMERIC = 6

@num_c NUMERIC(4,2)

• Datetime2

• Text – non-Unicode

CREATE PROCEDURE increase_prices @old_price NUMERIC, @percent_increase NUMERIC = 5ASDECLARE@new_price NUMERICBEGINSET @new_price = @old_price + @old_price * @percent_increase/100PRINT 'New Price: $' + CAST(@new_price as nVARCHAR)END

A Simple Procedure – calculates a percent price increase

CREATE PROCEDURE increase_prices @old_price NUMERIC, @percent_increase NUMERIC = 5AS

DECLARE@new_price NUMERICBEGINSET @new_price = @old_price + @old_price * @percent_increase/100PRINT 'New Price: $' + CAST(@new_price as nVARCHAR)END

CASTThe PRINT will print a numeric by itself if there are no other items to be printed. If there are two or more data types that are numeric you must use CAST or CONVERT. @new_price is numeric. Therefore CAST converts @new_price to a nvarchar datatype.

CONVERTWorks like CAST but structured differently

Control Structures

• One can do conditional processing

• Also can do iterations

• Many times you may want to do one thing if something is true or something else if it is not true

IF Statement

• The syntax:

IF condition_1

BEGIN (SET) Actions_1 END

ELSE IF condition_2

BEGIN (SET) Actions_2 END

……..

ELSE

BEGIN (SET) Actions_last END

Zodiac Sign

YEAR OF BIRTH

Rat 2008 1996 1984 1972 1960 1948 1936 1924 1912 1900

Bull 2009 1997 1985 1973 1961 1949 1937 1925 1913 1901

Tiger 2010 1998 1986 1974 1962 1950 1938 1926 1914 1902

Rabbit 2011 1999 1987 1975 1963 1951 1939 1927 1915 1903

Dragon 2012 2000 1988 1976 1964 1952 1940 1928 1916 1904

Snake 2013 2001 1989 1977 1965 1953 1941 1929 1917 1905

Horse 2014 2002 1990 1978 1966 1954 1942 1930 1918 1906

Goat 2015 2003 1991 1979 1967 1955 1943 1931 1919 1907

Monkey 2016 2004 1992 1980 1968 1956 1944 1932 1920 1908

Rooster 2017 2005 1993 1981 1969 1957 1945 1933 1921 1909

Dog 2018 2006 1994 1982 1970 1958 1946 1934 1922 1910

Pig 2019 2007 1994 1983 1971 1959 1947 1935 1923 1911

• Want to develop a procedure to calculate your Chinese birth sign.

Create procedure CZP @birthyear numeric

AS

IF @birthyear IN(1900,1912,1924,1936,1948,1960,1972,1984,1996,2008)

BEGIN

PRINT 'You are a rat'

END

ELSE

BEGIN

PRINT 'You are not a rat'

END

CREATE PROCEDURE Chinese_Zodiac_Proc (@BirthDate NUMERIC)--This procedure deals with birth years and the Chinese ZodiacASPRINT ('*****');IF @BirthDate IN( 1924, 1936, 1948, 1960, 1972, 1984, 1996)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Rat.') ENDELSE IF @BirthDate IN( 1925, 1937, 1949, 1961, 1973, 1985, 1997)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Bull.') ENDELSE IF @BirthDate IN( 1926, 1938, 1950, 1962, 1974, 1986, 1998)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Tiger.') ENDELSE IF @BirthDate IN( 1927, 1939, 1951, 1963, 1975, 1987, 1999)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Rabbit.') ENDELSE IF @BirthDate IN( 1928, 1940, 1952, 1964, 1976, 1988, 2000)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Dragon.') ENDELSE IF @BirthDate IN( 1929, 1941, 1953, 1965, 1977, 1989, 2001)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Snake.') ENDELSE IF @BirthDate IN( 1930, 1942, 1954, 1966, 1978, 1990, 2002)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Horse.') ENDELSE IF @BirthDate IN( 1931, 1943, 1955, 1967, 1979, 1991, 2003)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Sheep.') ENDELSE IF @BirthDate IN( 1932, 1944, 1956, 1968, 1980, 1992, 2004)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Monkey.') ENDELSE IF @BirthDate IN( 1933, 1945, 1957, 1969, 1981, 1993, 2005)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Rooster.') ENDELSE IF @BirthDate IN( 1934, 1946, 1958, 1970, 1982, 1994, 2006)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Dog.') ENDELSE IF @BirthDate IN( 1935, 1947, 1959, 1971, 1983, 1995, 2007)BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @BirthDate) + ', the year of the Pig.') ENDELSEBEGIN PRINT (' Your birth date is out of the program range!') ENDPRINT ('*****')

Now to develop the procedure using a calculation for birth sign

1944/12 = 162.00 MONKEY1945/12 = 162.083333 ROOSTER1946/12 = 162.166667 DOG1947/12 = 162.25 PIG1948/12 = 162.33333 RAT1949/12 = 162.416667 BULL1950/12 = 162.5 TIGER1951.12 = 162.583333 RABBIT1952/12 = 162.666667 DRAGON1953/12 = 162.75 SNAKE1954/12 = 162.833333 HORSE1955/12 = 162.916667 SHEEP1956/12 = 163.00 MONKEY

Therefore:

Sign Remainder (R) R x 12

MONKEY 0 0

ROOSTER 0.083333 1

DOG 0.166667 2

PIG 0.25 3

RAT 0.33333 4

BULL 0.416667 5

TIGER 0.5 6

RABBIT 0.583333 7

DRAGON 0.666667 8

SNAKE 0.75 9

HORSE 0.833333 10

SHEEP 0.916667 11

Thus have to calculate the remainder for each birth year

Use @birthyear = 1950

Declare three variables:@X NUMERIC(10,6)@Y NUMERIC(4)@Z NUMERIC(3,2)

Now SET @X =@birthyear/12 (162.5)SET @Y = @birthyear/12 (162)

SET @Z = @X - @Y (0.50)

Multiply by 12. Gets rid of decimal points

Only need two significant digits

CREATE PROCEDURE Chinese_Zodiac_Proc02 (@birthyear NUMERIC)--This procedure deals with birth years and the Chinese ZodiacASDECLARE@X NUMERIC(10,6), @Y NUMERIC(4), @Z NUMERIC(2)SET @X = @birthyear/12SET @Y = @birthyear/12BEGINIF @Y > @X SET @Y = @Y-1SET @Z = (@X - @Y)*12ENDPRINT ('*****');IF @Z = 0BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Monkey.') ENDELSE IF @Z = 1BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Rooster.') ENDELSE IF @Z = 2BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Dog.') ENDELSE IF @Z = 3BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Pig.') ENDELSE IF @Z = 4BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Rat.') ENDELSE IF @Z = 5BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Bull.') ENDELSE IF @Z = 6BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Tiger.') ENDELSE IF @Z = 7BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Rabbit.') ENDELSE IF @Z = 8BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Dragon.') ENDELSE IF @Z = 9BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Snake.') ENDELSE IF @Z = 10BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Horse.') ENDELSE IF @Z = 11BEGIN PRINT ('You were born in ' + CONVERT(nVARCHAR(20), @birthyear) + ', the year of the Sheep.') ENDPRINT ('*****')

No correction if @Y > @X

Correction if @Y > @X

@Z is negative @Z is positive

How can @Y be greater than @X?

There is a problem with BCE year as there is no year zero.

If the procedure uses ‘0’, the answer is:

****You were born in 0, the year of the Monkey****

This is incorrect as 1 BCE is the year of the Monkey

This is corrected in the next slide

Correction for year 0

As there is no year 0 you have to increment any

BCE years by 1

WHILE LOOP

• An iteration construct

• The Syntax:

Declare @counter intSet @counter = 1While @counter < 10Begin     print 'The counter is ' + cast(@counter as nvarchar)    Set @counter = @counter + 1End

OR:

Declare @counter int = 1While @counter < 10Begin     print 'The counter is ' + cast(@counter as nvarchar)    Set @counter = @counter + 1End

• Will use the following table:1. For another loop example; and

2. For a discussion with CURSORS.

CREATE TABLE CHINESE_ZODIAC(Number NUMERIC(2) CONSTRAINT cz_pk PRIMARY KEY, ZodiacSign nVARCHAR(10))

INSERT INTO CHINESE_ZODIAC VALUES (0,'Monkey')INSERT INTO CHINESE_ZODIAC VALUES (1,'Rooster')INSERT INTO CHINESE_ZODIAC VALUES (2,'Dog')INSERT INTO CHINESE_ZODIAC VALUES (3,'Pig')INSERT INTO CHINESE_ZODIAC VALUES (4,'Rat')INSERT INTO CHINESE_ZODIAC VALUES (5,'Bull')INSERT INTO CHINESE_ZODIAC VALUES (6,'Tiger')INSERT INTO CHINESE_ZODIAC VALUES (7,'Rabbit')INSERT INTO CHINESE_ZODIAC VALUES (8,'Dragon')INSERT INTO CHINESE_ZODIAC VALUES (9,'Snake')INSERT INTO CHINESE_ZODIAC VALUES (10,'Horse')INSERT INTO CHINESE_ZODIAC VALUES (11,'Goat')

Declare @counter intSet @counter = 0While @counter < 7Begin    Select * from Chinese_Zodiac where rounding = @counter    Set @counter = @counter + 1End

Simple example of using a While Loop

GOTO LOOP

• Once again an iteration construct

• The Syntax:

DECLARE @counter INTEGER = 0EPSILON:BEGINPRINT 'Hello World'SET @counter = @counter + 1ENDIF @Counter < 11 GOTO EPSILON

According to Microsoft:

Use GOTO statement sparingly. Excessive use of the GOTO statement adds difficult to understand the logic of the T-SQL batch. You can almost always implement the logic using other control-of-flow statements.

According to Wikipedia:

Spaghetti code is a derogatory term for source code that has a complex and tangled control structure, especially one using many GOTO statements, exceptions, threads, or other unstructured branching constructs. It is named such because program flow is conceptually like a bowl of spaghetti, i.e. twisted and tangled. Spaghetti code can be caused by several factors, such as continuous modifications by several people over a long life cycle. Structured programming greatly decreases the incidence of spaghetti code.

Problems with GOTO

Spaghetti Code

• An example. Create a function that:

• Compute discounts on orders

• Input order amounts

• Returns discount amount

(zero for wrong inputs)

• The RETURN keyword

FUNCTIONS

*

See Part 2 Now