|
Microsoft Visual C#: Common Table Expressions (CTE) |
|
|
A common table expression, or CTE, is a temporary
selection or other query operation of records from one or more tables. You
use it to get an idea of what the query operation would produce if performed
on a table. You can generate a CTE to create, select, merge, or delete
records.
|
There are two types of common table expressions:
recursive and non-recursive.
Practical
Learning: Introducing Common Table Expressions
|
|
- Start Microsoft Visual Studio
- To create a new application, on the main menu, click File -> New
Project...
- In the middle list, click Windows Forms Application
- Change the Name to HotelManagement1
- Click OK
- In the Solution Explorer, right click Form1.cs and click Rename
- Type HotelManagement.cs and press enter
- Double-click the middle of the form to generate its Load event
- To create a new database, implement the event as follows:
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 HotelManagement1
{
public partial class HotelManagement : Form
{
public HotelManagement()
{
InitializeComponent();
}
void CreateHotelRooms()
{
using (SqlConnection conHotelManagement =
new SqlConnection("Data Source=(local);" +
"Integrated Security=SSPI;"))
{
SqlCommand cmdHotelManagement =
new SqlCommand("IF EXISTS(SELECT name " +
" FROM sys.databases " +
" WHERE name = N'HotelManagement1') " +
"DROP DATABASE HotelManagement1;" +
"CREATE DATABASE HotelManagement1;",
conHotelManagement);
conHotelManagement.Open();
cmdHotelManagement.ExecuteNonQuery();
MessageBox.Show("The HotelManagement1 database has been created.",
"Ceil Inn - Hotel Management", MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
using (SqlConnection conHotelManagement =
new SqlConnection("Data Source=(local);" +
"Database=HotelManagement1;" +
"Integrated Security=SSPI;"))
{
SqlCommand cmdHotelManagement =
new SqlCommand("CREATE TABLE Bedrooms(" +
"RoomNumber nchar(10) not null," +
"RoomType nvarchar(20) default N'Bedroom'," +
"BedType nvarchar(40) default N'Queen'," +
"Rate money default 75.85, Available bit default 0);",
conHotelManagement);
conHotelManagement.Open();
cmdHotelManagement.ExecuteNonQuery();
MessageBox.Show("A table named Bedrooms has been created.",
"Ceil Inn - Hotel Management", MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
using (SqlConnection conHotelManagement =
new SqlConnection("Data Source=(local);" +
"Database=HotelManagement1;" +
"Integrated Security=SSPI;"))
{
SqlCommand cmdHotelManagement =
new SqlCommand("INSERT INTO Bedrooms(RoomNumber, BedType, Rate, Available)" +
"VALUES(N'104', N'Queen', 80.25, 0)," +
" (N'105', N'King', 95.50, 1)," +
" (N'106', N'Queen', 65.95, 1)," +
" (N'107', N'Queen', 65.95, 1)," +
" (N'108', N'King', 92.50, 1)," +
" (N'109', N'Queen', 68.95, 0)," +
" (N'110', N'Queen', 74.95, 1);",
conHotelManagement);
conHotelManagement.Open();
cmdHotelManagement.ExecuteNonQuery();
MessageBox.Show("Records have been added to the Bedrooms table.",
"Ceil Inn - Hotel Management", MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
using (SqlConnection cnnHotelManagement =
new SqlConnection("Data Source=(local);" +
"Database=HotelManagement1;" +
"Integrated Security=SSPI;"))
{
SqlCommand cmdHotelManagement =
new SqlCommand("CREATE TABLE ConferenceRooms(" +
"RoomNumber nchar(10) not null," +
"RoomType nvarchar(20) default N'Conference'," +
"BedType nvarchar(40), Rate money default 75.85," +
"Available bit default 0);", cnnHotelManagement);
cnnHotelManagement.Open();
cmdHotelManagement.ExecuteNonQuery();
MessageBox.Show("A table named ConferenceRooms has been created.",
"Ceil Inn - Hotel Management", MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
using (SqlConnection conHotelManagement =
new SqlConnection("Data Source=(local);" +
"Database=HotelManagement1;" +
"Integrated Security=SSPI;"))
{
SqlCommand cmdHotelManagement =
new SqlCommand("INSERT INTO ConferenceRooms(RoomNumber, Rate, Available)" +
"VALUES(N'C-120', 525.00, 1);" +
"INSERT INTO Bedrooms(RoomNumber, RoomType, BedType, Rate, Available)" +
"VALUES(N'116', N'Studio', N'King', 112.95, 0);" +
"INSERT INTO ConferenceRooms(RoomNumber, Rate, Available)" +
"VALUES(N'C-122', 450.00, 1);" +
"INSERT INTO Bedrooms(RoomNumber, RoomType, BedType, Rate, Available)" +
"VALUES(N'202', N'Studio', N'King', 105.95, 1)," +
" (N'203', N'Studio', N'Queen', 102.50, 1);" +
"INSERT INTO Bedrooms(RoomNumber, BedType, Rate, Available)" +
"VALUES(N'204', N'Double', 115.95, 1)," +
" (N'205', N'Queen', 82.95, 0)," +
" (N'206', N'King', 98.50, 1)" +
"INSERT INTO ConferenceRooms(RoomNumber, Rate, Available)" +
"VALUES(N'C-302', 650.00, 1);",
conHotelManagement);
conHotelManagement.Open();
cmdHotelManagement.ExecuteNonQuery();
MessageBox.Show("Records have been added to the ConferenceRooms table.",
"Ceil Inn - Hotel Management", MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
}
private void HotelManagement_Load(object sender, EventArgs e)
{
CreateHotelRooms();
}
}
}
- Press F5 to execute
- After clicking OK on the message boxes, close the form and return to
your programming environment
Creating a Common Table
Expression
|
|
The formula to create a common table expression (CTE)
is:
[ WITH <common_table_expression> [ ,...n ] ]
<common_table_expression>::=
expression_name [ ( column_name [ ,...n ] ) ]
AS
( CTE_query_definition )
You start with the WITH keyword followed by a
name for the temporary set. The name must be different from any table that
will be used in the CTE's expression. Later we will see the parameters you
can add after the name. After the name, type AS followed by
parentheses. In the parentheses, create a simple or composite SELECT
expression.
After the code that defines the CTE, that is, after the
AS(CTE_query_definition) expression, create a SELECT
statement that will produce the results.
Practical
Learning: Creating a Common Table Expression
|
|
- Change the design of the form as follows:
|
Control |
Text |
Name |
Anchor |
Button |
Show Rooms |
btnAllBedrooms |
|
DataGridView |
|
dgvRooms |
Top, Bottom, Left, Right |
|
- Double-click the Show Rooms button and change the file as follows:
private void HotelManagement_Load(object sender, EventArgs e)
{
//CreateHotelRooms();
}
private void btnAllBedrooms_Click(object sender, EventArgs e)
{
using (SqlConnection conHotelManagement =
new SqlConnection("Data Source=(local);" +
"Database='HotelManagement1';" +
"Integrated Security='SSPI';"))
{
SqlCommand cmdHotelManagement =
new SqlCommand("WITH SleepingRooms AS ( " +
"SELECT * FROM Bedrooms) " +
"SELECT * FROM SleepingRooms;",
conHotelManagement);
SqlDataAdapter sdaHotelManagement =
new SqlDataAdapter(cmdHotelManagement);
BindingSource bsHotelManagement = new BindingSource();
DataSet dsHotelManagement = new DataSet("RoomsSet");
sdaHotelManagement.Fill(dsHotelManagement);
conHotelManagement.Open();
bsHotelManagement.DataSource = dsHotelManagement.Tables[0];
dgvRooms.DataSource = bsHotelManagement;
}
}
- Press F5 to see the result
- Click Show Rooms
- Close the form and return to your programming environment
- Change the design of the form as follows:
|
Control |
Text |
Name |
Anchor |
Button |
All Bedrooms |
btnAllBedrooms |
|
Button |
Available Bedrooms |
btnAvailableBedrooms |
|
DataGridView |
|
dgvRooms |
Top, Bottom, Left, Right |
|
- Double-click the Available Bedrooms button
- To be able to see a list of available rooms, implement its event as
follows:
private void btnAvailableBedrooms_Click(object sender, EventArgs e)
{
using (SqlConnection conHotelManagement =
new SqlConnection("Data Source=(local);" +
"Database='HotelManagement1';" +
"Integrated Security='SSPI';"))
{
SqlCommand cmdHotelManagement =
new SqlCommand("WITH SleepingRooms AS" +
"(" +
" SELECT * FROM Bedrooms WHERE Available = 1" +
")" +
"SELECT * FROM SleepingRooms;",
conHotelManagement);
SqlDataAdapter sdaHotelManagement =
new SqlDataAdapter(cmdHotelManagement);
BindingSource bsHotelManagement = new BindingSource();
DataSet dsHotelManagement = new DataSet("RoomsSet");
sdaHotelManagement.Fill(dsHotelManagement);
conHotelManagement.Open();
bsHotelManagement.DataSource = dsHotelManagement.Tables[0];
dgvRooms.DataSource = bsHotelManagement;
}
}
- Press F5 to execute
- To see a list of all rooms, click the Show All Rooms button
- To see available rooms, click the other button
- Close the form and return to your programming environment
To make sure you can externally control the results of a
CTE, you can pass a type of parameter to it. To do this, after the name of
the CTE and before the AS operator, add the parentheses and pass one
or more parameters, each represented by a name. The names of parameters must
be the exact same names of columns of the table(s) from which the CTE's
statement will be based. The number of columns must be the same as the
number of columns that will be involved in the final SELECT
statement.
In the body of the CTE, use the parameter(s) as you
wish. For example, you can involve the parameter(s) in a condition in the
CTE.
Practical
Learning: Passing Parameters to a CTE
|
|
- Change the design of the form as follows:
|
Control |
Text |
Name |
Button |
All Bedrooms |
btnAllBedrooms |
Button |
All Queen Size Rooms |
btnAllQueenRooms |
Button |
Available Bedrooms |
btnAvailableBedrooms |
Button |
Available Queen Rooms |
btnAvailableQueenRooms |
|
- Double-click the All Queen Size Rooms button
- To be able to see a list of available rooms, implement its event as
follows:
private void btnAllQueenRooms_Click(object sender, EventArgs e)
{
using (SqlConnection conHotelManagement =
new SqlConnection("Data Source=(local);" +
"Database='HotelManagement1';" +
"Integrated Security='SSPI';"))
{
SqlCommand cmdHotelManagement =
new SqlCommand("WITH SleepingRoomt(RoomNumber, RoomType, BedType, Rate, Available)" +
"AS" +
"(" +
" SELECT RoomNumber, RoomType, BedType, Rate, Available " +
" FROM Bedrooms " +
" WHERE BedType = N'Queen'" +
")" +
"SELECT RoomNumber, RoomType, Rate, Available FROM BedRooms;",
conHotelManagement);
SqlDataAdapter sdaHotelManagement =
new SqlDataAdapter(cmdHotelManagement);
BindingSource bsHotelManagement = new BindingSource();
DataSet dsHotelManagement = new DataSet("RoomsSet");
sdaHotelManagement.Fill(dsHotelManagement);
conHotelManagement.Open();
bsHotelManagement.DataSource = dsHotelManagement.Tables[0];
dgvRooms.DataSource = bsHotelManagement;
}
}
- Press F5 to execute
- To see a list of all rooms, click the Show All Rooms button
- To see a list of queen size rooms, click the All Queen Size Rooms
button
- Close the form and return to your programming environment
- Double-click the Available Queen Rooms button
- Implement its event as follows:
private void btnAvailableQueenRooms_Click(object sender, EventArgs e)
{
using (SqlConnection conHotelManagement =
new SqlConnection("Data Source=(local);" +
"Database='HotelManagement1';" +
"Integrated Security='SSPI';"))
{
SqlCommand cmdHotelManagement =
new SqlCommand("WITH SleepingRooms(RoomNumber, RoomType, BedType, Rate, Available)" +
"AS" +
"(" +
" SELECT RoomNumber, RoomType, BedType, Rate, Available " +
" FROM Bedrooms " +
" WHERE BedType = N'Queen'" +
")" +
"SELECT RoomNumber, RoomType, Rate, Available " +
"FROM BedRooms " +
"WHERE Available = 1;",
conHotelManagement);
SqlDataAdapter sdaHotelManagement =
new SqlDataAdapter(cmdHotelManagement);
BindingSource bsHotelManagement = new BindingSource();
DataSet dsHotelManagement = new DataSet("RoomsSet");
sdaHotelManagement.Fill(dsHotelManagement);
conHotelManagement.Open();
bsHotelManagement.DataSource = dsHotelManagement.Tables[0];
dgvRooms.DataSource = bsHotelManagement;
}
}
- Press F5 to execute
- To see a list of all rooms, click the Show All Rooms button
- To see a list of queen size rooms, click the Show Queen Rooms button
- To see a list of available queen size rooms, click the Available
Queen Rooms button
- Close the form and return to your programming environment
Topics on Common Table Expressions
|
|
In all of our SELECT expressions so far, we considered
all records of the intended table. In some cases, you can set a condition
that would select only some records. You can use the condition in one or
both SELECT statements.
Recursive Common Table Expressions
|
|
A recursive common table expression is a CTE that can
contain more than one SELECT statement. In the body of the CTE, you
can create as many SELECT statements as you want but those statements
must be joined. To join them, you can use a UNION, UNION ALL,
or MERGER operator.
Practical
Learning: Creating a Recursive CTE
|
|
- Change the design of the form as follows:
|
Control |
Text |
Name |
Anchor |
Button |
All Hotel Rooms |
btnAllHotelRooms |
|
Button |
All Bedrooms |
btnAllBedrooms |
|
Button |
All Queen Rooms |
btnAllQueenRooms |
|
Button |
Available Hotel Rooms |
btnAvailableHotelRooms |
|
Button |
Available Bedrooms |
btnAvailableBedrooms |
|
Button |
Available Queen Rooms |
btnAvailableQueenRooms |
|
DataGridView |
|
dgvRooms |
Top, Bottom, Left, Right |
|
- Double-click All Hotel Rooms
- Implement its event as follows:
private void btnHotelRooms_Click(object sender, EventArgs e)
{
using (SqlConnection conHotelManagement =
new SqlConnection("Data Source=(local);" +
"Database='HotelManagement1';" +
"Integrated Security='SSPI';"))
{
SqlCommand cmdHotelManagement =
new SqlCommand("WITH HotelRooms " +
"AS" +
"(" +
" SELECT * FROM Bedrooms " +
" UNION " +
" SELECT * FROM ConferenceRooms" +
")" +
"SELECT * FROM HotelRooms;",
conHotelManagement);
SqlDataAdapter sdaHotelManagement =
new SqlDataAdapter(cmdHotelManagement);
BindingSource bsHotelManagement = new BindingSource();
DataSet dsHotelManagement = new DataSet("RoomsSet");
sdaHotelManagement.Fill(dsHotelManagement);
conHotelManagement.Open();
bsHotelManagement.DataSource = dsHotelManagement.Tables[0];
dgvRooms.DataSource = bsHotelManagement;
}
}
- Press F5 to execute
- Click the All Hotel Rooms button
- Close the form and return to your programming environment
- Double-click the Available Hotel Room button
- Implement its event as follows:
private void btnAvailableHotelRooms_Click(object sender, EventArgs e)
{
using (SqlConnection conHotelManagement =
new SqlConnection("Data Source=(local);" +
"Database='HotelManagement1';" +
"Integrated Security='SSPI';"))
{
SqlCommand cmdHotelManagement =
new SqlCommand("WITH HotelRooms " +
"AS" +
"(" +
" SELECT * FROM Bedrooms " +
" UNION " +
" SELECT * FROM ConferenceRooms" +
")" +
"SELECT RoomNumber, RoomType, BedType, Rate " +
"FROM HotelRooms " +
"WHERE Available = 1;",
conHotelManagement);
SqlDataAdapter sdaHotelManagement =
new SqlDataAdapter(cmdHotelManagement);
BindingSource bsHotelManagement = new BindingSource();
DataSet dsHotelManagement = new DataSet("RoomsSet");
sdaHotelManagement.Fill(dsHotelManagement);
conHotelManagement.Open();
bsHotelManagement.DataSource = dsHotelManagement.Tables[0];
dgvRooms.DataSource = bsHotelManagement;
}
}
- Click the Available Hotel Rooms button
- Close the form and return to your programming environment
Non-Recursive Common Table Expressions
|
|
A non-recursive common table expression is a CTE that
can be followed by only one SELECT, INSERT, UPDATE, or
DELETE statement that involves a column from inside the CTE's body.
|
|