|
Introduction to SQL Functions |
|
Functions Fundamentals |
|
Introduction |
You are probably not familiar with the concept of functions because there are not functions in C#; but many languages support them, including C/C++, Pascal Visual Basic, etc. A function is like a method in C#, except that a function does not belong to a class. As seen in C#, a function is a relatively small task that should be performed aside but can be accessed any time to give a result. In Transact-SQL, a function is considered an object. Based on this, you must create a function and execute it before using it. The function then becomes part of a database and it can be accessed.
|
|
![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace TriStateUtilityCompany1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnDatabase_Click(object sender, EventArgs e)
{
string strConnection =
"Data Source=(local);Integrated Security=yes";
using (SqlConnection connection =
new SqlConnection(strConnection))
{
SqlCommand command =
new SqlCommand("CREATE DATABASE UtilityCompany1;",
connection);
connection.Open();
command.ExecuteNonQuery();
MessageBox.Show(
"A database named \"UtilityCompany1\" has been created.");
}
}
}
}
|
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
|
|
Function Creation Fundamentals |
There are various ways you can create a function:
In Transact-SQL, the primary formula of creating a function is:
CREATE FUNCTION FunctionName()
We mentioned already that, in SQL, a function was created as an object. As such, it must have a name. In our lessons, here are the rules we will use to name our functions:
|
Returning a Value From a Function |
For a function to be useful, it must produce a result. This is also said that the function returns a result or a value. When creating a function, you must specify the type of value that the function would return. To provide this information, after the name of the function, type the RETURNS keyword followed by a definition for a data type. Here is a simple example:
CREATE FUNCTION Addition() RETURNS Decimal(6,3)
After specifying the type of value that the function would return, you can create a body for the function. The body of a function starts with the BEGIN and ends with the END keywords. Here is an example:
CREATE FUNCTION Addition() RETURNS Decimal(6,3) BEGIN }
Optionally, you can type the AS keyword before the BEGIN keyword:
CREATE FUNCTION Addition() RETURNS Decimal(6,3) AS BEGIN }
Between the BEGIN and END keywords, which is the section that represents the body of the function, you can define the assignment the function must perform. After performing this assignment, just before the END keyword, you must specify the value that the function returns. This is done by typing the RETURN keyword followed by an expression. A sample formula is:
CREATE FUNCTION Addition()
RETURNS Decimal(6,3)
AS
BEGIN
RETURN Expression
}
Here is an example
CREATE FUNCTION GetFullName() RETURNS varchar(100) AS BEGIN RETURN 'Doe, John' }
|
|
private void btnDatabase_Click(object sender, EventArgs e)
{
string strConnection =
"Data Source=(local);" +
"Database='UtilityCompany1';" +
"Integrated Security=yes;";
string CreateFunction = "CREATE FUNCTION EvaluateInvoice() " +
"RETURNS Decimal(8, 2) " +
"AS " +
"BEGIN " +
" RETURN 8.50 " +
"END;";
using (SqlConnection connection = new SqlConnection(strConnection))
{
SqlCommand command =
new SqlCommand(CreateFunction, connection);
connection.Open();
command.ExecuteNonQuery();
MessageBox.Show(
"A function named \"EvaluateInvoice\" has been created.");
}
}
|

|
Function Calling |
After a function has been created, you can use the value it returns. Using a function is also referred to as calling it. To call a function, you must qualify its name. To do this, type the name of the database in which it was created, followed by the period operator, followed by dbo, followed by the period operator, followed by the name of the function, and its parentheses. The formula to use is:
DatabaseName.dbo.FunctionName()
Because a function returns a value, you can use that value as you see fit. For example, you can use either PRINT or SELECT to display the function's value in a query window. Here is an example that calls the above Addition() function:
PRINT Exercise.dbo.GetFullName();
As an alternative, to call a function, in the Object Explorer, right-click its name, position the mouse on Script Function As, SELECT To, and click New Query Editor Window.
|
|
private void btnEvaluate_Click(object sender, EventArgs e)
{
string strConnection =
"Data Source=(local);" +
"Database='UtilityCompany1';" +
"Integrated Security=yes;";
string ExecuteFunction = "SELECT dbo.EvaluateInvoice();";
using (SqlConnection connection = new SqlConnection(strConnection))
{
SqlCommand command =
new SqlCommand(ExecuteFunction, connection);
connection.Open();
SqlDataReader rdr = command.ExecuteReader();
while (rdr.Read())
{
txtAmountDue.Text = rdr[0].ToString();
}
rdr.Close();
}
}
|

|
Function Maintenance |
|
Introduction |
Because a function in Transact-SQL is treated as an object, it may need maintenance. Some of the actions you would take include renaming, modifying, or deleting a function.
|
Renaming a Function |
If you create a function and execute it, it is stored in the Scalar-Valued Functions node with the name you gave it. If you want, you can change that name but keep the functionality of the function.
To rename a function, in the Object Explorer, right-click it and click Rename. Type the desired new name and press Enter.
|
Deleting a Function |
If you create a function and decide that you don't need it any more, you can delete it.
To delete a function in the Object Explorer, locate the function in the Functions section, right-click it and click Delete. The Delete Object dialog box would come up. If you still want to delete the function, click OK; otherwise, click Cancel.
To programmatically delete a function:
|
|
private void btnDatabase_Click(object sender, EventArgs e)
{
string strConnection =
"Data Source=(local);" +
"Database='UtilityCompany1';" +
"Integrated Security=yes;";
string CreateFunction = "DROP FUNCTION EvaluateInvoice;";
using (SqlConnection connection = new SqlConnection(strConnection))
{
SqlCommand command =
new SqlCommand(CreateFunction, connection);
connection.Open();
command.ExecuteNonQuery();
MessageBox.Show(
"A function named \"EvaluateInvoice\" has been deleted.");
}
}
|

|
Modifying a Function |
As mentioned already, in the body of the function, you define what the function is supposed to take care of. As a minimum, a function can return a simple number, typed on the right side of the RETURN keyword. Here is an example:
CREATE FUNCTION Addition()
RETURNS int
BEGIN
RETURN 1
}
You can also declare new variables in the body of the function to help in carrying the assignment. A variable declared in the body of a function is referred to as a local variable. Once such a variable has been declared, it can be used like any other variable. Here is an example:
CREATE FUNCTION Addition()
RETURNS int
BEGIN
DECLARE @Number1 int
SET @Number1 = 588
RETURN @Number1 + 1450
}
|
Function Arguments |
|
Introduction |
In order to carry its assignment, a function can be provided with some values. Put it another way, when you create a function, instead of, or in addition to, local variables, you may want the code that will call the function to provide the values needed to perform the assignment. For example, imagine you want to create a function that would generate employees email addresses when a user has entered a first and last name. At the time you are creating the function, you cannot know or predict the names of employees, including those who have not even been hired yet. In this case, you can write the whole function but provide one or more placeholders for values that would be supplied when the function is called.
An external value that is provided to a function is called a parameter. A function can also take more than one parameter. Therefore, when you create a function, you also decide whether your function would take one or more parameters and what those parameters, if any, would be.
|
A Parameterized Function |
We have already seen that a function's name is also followed by parentheses. If the function doesn't use an external value, its parentheses can be left empty. If a function will use an external value, when you create the function, you must specify a name and the type of value of the parameters. The name of the parameter is created with the @ sign, like a variable as we saw in the previous lesson. Here is an example:
CREATE FUNCTION Addition(@Number1 Decimal(6,2))
When a function takes a parameter, in the body of the function, you can use the parameter as if you knew its value, as long as you respect the type of that value. Here is an example:
CREATE FUNCTION Addition(@Number1 Decimal(6,2))
RETURNS Decimal(6,2)
BEGIN
RETURN @Number1 + 1450
}
|
Calling a Parameterized Function |
When you call a function that takes one parameter, you must supply a value for that argument. To do this, type the value of the parameter in the parentheses of the function. Here is an example:

|
A Function With Various Arguments |
Instead of only one parameter, you can also create a function that takes more than one parameter. In this case, separate the arguments in the parentheses of the function with a comma. Here is an example:
CREATE FUNCTION Addition(@Number1 Decimal(6,2), @Number2 Decimal(6,2))
Once again, in the body of the function, you can use the parameters as if you already knew their value. You can also declare local variables and involve them with parameters as you see fit. Here is an example:
CREATE FUNCTION Addition(@Number1 Decimal(6,2),
@Number2 Decimal(6,2))
RETURNS Decimal(6,2)
BEGIN
DECLARE @Result Decimal(6,2)
SET @Result = @Number1 + @Number2
RETURN @Result
};
GO
When calling a function that takes more than one parameter, in the parentheses of the function, provide a value for each parameter, in the exact order they appear in the parentheses of the function. Here is an example:
PRINT Variables1.dbo.Addition(1450, 228);
You can also pass the names of already declared and initialized variables. Here is an example that calls the above function:
DECLARE @Nbr1 Decimal(6,2),
@Nbr2 Decimal(6,2)
SET @Nbr1 = 4268.55
SET @Nbr2 =26.83
SELECT @Nbr1 As First,
@Nbr2 As Second,
Variables1.dbo.Addition(@Nbr1, @Nbr2) AS Result
This would produce:

|
|
private void btnDatabase_Click(object sender, EventArgs e)
{
string strConnection =
"Data Source=(local);" +
"Database='UtilityCompany1';" +
"Integrated Security=yes;";
// The following function is used to calculate the customer's next bill
// Some of the empty spaces, not required,
// are meant to make the code easier to read
string CreateFunction = "CREATE FUNCTION EvaluateInvoice(@Counter int) " +
"RETURNS decimal(6, 2) " +
"AS " +
"BEGIN " +
" DECLARE @BaseCharge money, " +
" @Counter0To50 int, " +
" @Counter50To150 int, " +
" @Counter150To200 int, " +
" @CounterOver200 int, " +
" @First50 decimal(6, 2), " +
" @FiftyTo150 decimal(6, 2), " +
" @OneFiftyTo200 decimal(6, 2) ," +
" @Over200 decimal(6, 2), " +
" @TotalCharge money; " +
" SET @BaseCharge = 8.50; " +
" SET @Counter0To50 = 0; " +
" SET @Counter50To150 = 0; " +
" SET @Counter150To200 = 0; " +
" SET @CounterOver200 = 0; " +
" SET @First50 = 0.00; " +
" SET @FiftyTo150 = 0.00; " +
" SET @OneFiftyTo200 = 0.00; " +
" SET @Over200 = 0.00; " +
" SET @TotalCharge = 0.00; " +
" IF @Counter <= 50 " +
" BEGIN" +
" SET @Counter0To50 = @Counter; " +
" SET @Counter50To150 = 0; " +
" SET @Counter150To200 = 0; " +
" SET @CounterOver200 = 0; " +
" END;" +
" IF (@Counter > 50) AND (@Counter <= 150) " +
" BEGIN" +
" SET @Counter0To50 = 50; " +
" SET @Counter50To150 = @Counter - 50; " +
" SET @Counter150To200 = 0; " +
" SET @CounterOver200 = 0; " +
" END;" +
" IF (@Counter > 150) AND (@Counter <= 300) " +
" BEGIN " +
" SET @Counter0To50 = 50; " +
" SET @Counter50To150 = 100; " +
" SET @Counter150To200 = @Counter - 150; " +
" SET @CounterOver200 = 0; " +
" END; " +
" IF @Counter > 300 " +
" BEGIN " +
" SET @Counter0To50 = 50; " +
" SET @Counter50To150 = 100; " +
" SET @Counter150To200 = 100; " +
" SET @CounterOver200 = @Counter - 300; " +
" END;" +
" SET @First50 = @Counter0To50 * 0.7675; " +
" SET @FiftyTo150 = @Counter50To150 * 0.6248; " +
" SET @OneFiftyTo200 = @Counter150To200 * 0.5825; " +
" SET @Over200 = @CounterOver200 * 0.5037; " +
" SET @TotalCharge = @BaseCharge + @First50 + @FiftyTo150 + " +
" @OneFiftyTo200 + @Over200; " +
" RETURN @TotalCharge; " +
"END;";
using (SqlConnection connection = new SqlConnection(strConnection))
{
SqlCommand command =
new SqlCommand(CreateFunction, connection);
connection.Open();
command.ExecuteNonQuery();
MessageBox.Show(
"A function named \"EvaluateInvoice\" has been created.");
}
}
|
private void btnEvaluate_Click(object sender, EventArgs e)
{
int StartCounter = 0, EndCounter = 0;
int Consumption;
try
{
StartCounter = int.Parse(txtCounterLastMonth.Text);
}
catch (FormatException)
{
MessageBox.Show("Invalid Start Counter");
}
try
{
EndCounter = int.Parse(txtCounterThisMonth.Text);
}
catch (FormatException)
{
MessageBox.Show("Invalid End Counter");
}
if (StartCounter > EndCounter)
{
MessageBox.Show("Invalid Values");
return;
}
Consumption = EndCounter - StartCounter;
string strConnection =
"Data Source=(local);" +
"Database='UtilityCompany1';" +
"Integrated Security=yes;";
string ExecuteFunction = "DECLARE @Difference int " +
"SET @Difference = " + Consumption.ToString() +
"SELECT dbo.EvaluateInvoice(@Difference);";
using (SqlConnection connection = new SqlConnection(strConnection))
{
SqlCommand command =
new SqlCommand(ExecuteFunction, connection);
connection.Open();
SqlDataReader rdr = command.ExecuteReader();
txtConsumption.Text = Consumption.ToString();
while (rdr.Read())
txtAmountDue.Text = rdr[0].ToString();
rdr.Close();
}
}
|

private void btnDatabase_Click(object sender, EventArgs e)
{
string strConnection =
"Data Source=(local);Integrated Security=yes";
using (SqlConnection connection = new SqlConnection(strConnection))
{
SqlCommand command =
new SqlCommand("DROP DATABASE UtilityCompany1;",
connection);
connection.Open();
command.ExecuteNonQuery();
MessageBox.Show(
"The UtilityCompany1 database has been deleted.");
}
}
|
|
Introduction to Built-Functions |
|
Overview |
While your primary job as a database developer consists of creating lists, probably your second most important job is to assist your users with the various assignments they must perform on your application. One way you can assist is to use functions that perform otherwise complex tasks. To assist your development with the different tasks of a database, Transact-SQL ships with various already created and tested functions. You just need to be aware of these functions, their syntax, and the results they produce.
Because of their complexities, some values can be easily recognized or fixed. For example, a date such as January 6, 1995 is constant and can never change. This type of value is referred to as deterministic because it is always the same. In the same way, a time value such as 5 PM is constant and cannot change. There are other values that cannot be known in advance because they change based on some circumstances. For example, the starting date of the school year changes from one year to another but it always occurs. This means that, you know it will happen but you do not know the exact date. Such a value is referred to as non-deterministic.
To support determinism and non-determinism, Transact-SQL provides two broad categories of functions. A function that always returns the same or known value is referred to as deterministic. A function whose returned value may depend on a condition is referred to as non-deterministic.
|
|
private void button1_Click(object sender, EventArgs e)
{
string strConnection =
"Data Source=(local);Integrated Security=yes";
using (SqlConnection connection = new SqlConnection(strConnection))
{
SqlCommand command =
new SqlCommand("CREATE DATABASE Payroll;", connection);
connection.Open();
command.ExecuteNonQuery();
MessageBox.Show("A database named \"Exercise4\" has been created.");
}
}
|
|
Casting a Value |
In most cases, a value the user submits to your database is primarily considered a string. This is convenient if that's what you are expecting. If the value the user provides must be treated as something other than a string, for example, if the user provides a number, before using such a value, you should first convert it to the appropriate type, that is, from a string to the expected type.
To assist with conversion, you can use either the CAST() or the CONVERT() function. The syntax of the CAST() function is:
CAST(Expression AS DataType)
The Expression is the value that needs to be cast. The DataType factor is the type of value you want to convert the Expression to. The DataType can be one of those we reviewed in Lesson 20.
In the following example, two variables are declared and initialzed as strings. Because they must be involved in a multiplication, each is converted to a Decimal type.
|
|
![]() |
||||||||||||||||||||||||||||||||||||
|
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace Exernamespace Payroll10
{
public partial class Exercise : Form
{
public Exercise()
{
InitializeComponent();
}
private void btnCalculate_Click(object sender, EventArgs e)
{
double HourlySalary = 0.00, WeeklyHours = 0.00;
try {
HourlySalary = double.Parse(txtHourlySalary.Text);
}
catch(FormatException)
{
MessageBox.Show("Invalid Weekly Hours");
}
try {
WeeklyHours = double.Parse(txtWeeklyHours.Text);
}
catch(FormatException)
{
MessageBox.Show("Invalid Weekly Hours");
}
string strConnection =
"Data Source=(local);" +
"Database='UtilityCompany1';" +
"Integrated Security=yes;";
string ExecuteFunction =
"DECLARE @StrSalary Varchar(10), " +
"@StrHours Varchar(6), " +
"@WeeklySalary Decimal(6,2) " +
"SET @StrSalary = '" + HourlySalary.ToString() + "'; " +
"SET @StrHours = '" + WeeklyHours.ToString() + "'; " +
"SET @WeeklySalary = CAST(@StrSalary As Decimal(6,2)) * " +
"CAST(@StrHours As Decimal(6,2)); " +
"SELECT @WeeklySalary;";
using (SqlConnection connection = new SqlConnection(strConnection))
{
SqlCommand command =
new SqlCommand(ExecuteFunction, connection);
connection.Open();
SqlDataReader rdr = command.ExecuteReader();
while (rdr.Read())
{
txtWeeklySalary.Text = rdr[0].ToString();
}
rdr.Close();
}
}
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
}
}
|

|
Converting a Value |
Like CAST(), the CONVERT() function is used to convert a value. Unlike CAST(), CONVERT can be used to convert a value its original type into a non-similar type. For example, you can use CONVERT to cast a number into a string and vice-versa.
The syntax of the CONVERT() function is:
CONVERT(DataType [ ( length ) ] , Expression [ , style ])
The first argument must be a known data type, such as those we reviewed in Lesson 4. If you are converting the value into a string (varchar, nvarchar, char, nchar) or a binary type, you should specify the number of allowed characters the data type's own parentheses. As reviewed for the CAST() function, the Expression is the value that needs to be converted.
|
|
![]() |
||||||||||||||||||||||||||||||||||||
|
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace Exercise1
{
public partial class Exercise : Form
{
public Exercise()
{
InitializeComponent();
}
private void btnCalculate_Click(object sender, EventArgs e)
{
double dSide = 0.00;
try {
dSide = double.Parse(txtSide.Text);
}
catch(FormatException)
{
MessageBox.Show("Invalid Side Value");
}
string strConnection =
"Data Source=(local);" +
"Database='UtilityCompany1';" +
"Integrated Security=yes;";
string ExecuteFunction =
"DECLARE @Side As Decimal(10,3), " +
" @Perimeter As Decimal(10,3), " +
" @Area As Decimal(10,3); " +
"SET @Side = " + dSide.ToString() + "; " +
"SET @Perimeter = @Side * 4; " +
"SET @Area = @Side * @Side; " +
"SELECT CONVERT(varchar(10), @Perimeter, 10), " +
" CONVERT(varchar(10), @Area, 10);";
using (SqlConnection connection =
new SqlConnection(strConnection))
{
SqlCommand command =
new SqlCommand(ExecuteFunction, connection);
connection.Open();
SqlDataReader rdr = command.ExecuteReader();
while (rdr.Read())
{
txtPerimeter.Text = rdr[0].ToString();
txtArea.Text = rdr[1].ToString();
}
rdr.Close();
}
}
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
}
}
|

|
Lesson Summary |
|
Exercises |
|
|
||
| Previous | Copyright © 2008-2009 Yevol.com | Next |
|
|
||