SQL Server Questions
SQL Server Questions
.
Click the Connect button, you should see the SQL Server Management Studio Express window
comes up.
How to run Queries with SQL Server Management Studio Express?
1. Launch and connect SQL Server Management Studio Express to the local SQL Server 2005
Express.
2. Click on the "New Query" button below the menu line. Enter the following SQL statement in the
query window:
SELECT 'Welcome to FYIcenter.com SQL Server!'
3. Click the Execute button in the toolbar area. You should get the following in the result window:
Welcome to FYIcenter.com SQL Server!
See the following picture to know where the query and result windows are:
.
How to download and install SQL Server 2005 Books Online?
1. Go to the SQL Server 2005 Books Online download page.
2. Click the download button, the File Download box shows up. Save the download file to c:\temp.
3. Double click on the downloaded file: c:\temp\SqlServer2K5_BOL_Feb2007.msi. The
installation setup window shows up. Follow the instructions to finish the installation.
4. When the installation is done. You will see a new entry in the Start menu: Start > Programs >
Microsoft SQL Server 2005 > Documentation and Tutorials
How to run SQL Server 2005 Books Online on your local system?
SQL Server 2005 Books Online can be accessed by a Web browser over the Internet. But you
can also download it and read it on your local system. If you have downloaded and installed SQL
Server 2005 Books Online package, you follow this tutorial to run it:
1. Click Start > Programs > Microsoft SQL Server 2005 > Documentation and Tutorials >
Tutorials > SQL Server Tutorials. The SQL Server 2005 Books Online window shows up.
2. Click the plus sign (+) next to "SQL Server 2005 Tutorials in the Contents window".
3. Click the plus sign (+) next to "SQL Server Tools Tutorials".
4. Click "Lesson 1: Basic Navigation in SQL Server Management Studio". The book content
shows up for you to read.
.
How to use Transact-SQL statements to access the database engine?
Transact-SQL statements can be used to access the database engine directly. Here are some
good tutorials provided by the SQL Server 2005 Books Online. See the SQL Server 2005
Tutorials > Database Engine Tutorials > Writing Transact-SQL Statements Tutorial section in the
SQL Server 2005 Books Online document.
This tutorial is intended for users who are new to writing SQL statements. It will help new users
get started by reviewing some basic statements for creating tables and inserting data. This
tutorial uses Transact-SQL, the Microsoft implementation of the SQL standard. This tutorial is
intended as a brief introduction to the Transact-SQL language and not as a replacement for a
Transact-SQL class. The statements in this tutorial are intentionally simple, and are not meant to
represent the complexity found in a typical production database.
How to create new databases with "CREATE DATABASE" statements?
This is the first tutorial of a quick lesson on creating database objects with Transact-SQL
statements. This lesson shows you how to create a database, create a table in the database, and
then access and change the data in the table. Because this lesson is an introduction to using
Transact-SQL, it does not use or describe the many options that are available for these
statements. This tutorial assumes that you are running SQL Server Management Studio Express.
Like many Transact-SQL statements, the CREATE DATABASE statement has a required
parameter: the name of the database. CREATE DATABASE also has many optional parameters,
such as the disk location where you want to put the database files. When you execute CREATE
DATABASE without the optional parameters, SQL Server uses default values for many of these
parameters. This tutorial uses very few of the optional syntax parameters.
To create a database - In a Query Editor window, type but do not execute the following code:
CREATE DATABASE TestData
GO
Use the pointer to select the words CREATE DATABASE, and then press F1. The CREATE
DATABASE topic in SQL Server 2005 Books Online should open. You can use this technique to
find the complete syntax for CREATE DATABASE and for the other statements that are used in
this tutorial.
In Query Editor, press F5 to execute the statement and create a database named TestData.
When you create a database, SQL Server makes a copy of the model database, and renames
the copy to the database name. This operation should only take several seconds, unless you
specify a large initial size of the database as an optional parameter.
How to create new table with "CREATE TABLE" statements?
This is the second tutorial of a quick lesson on creating database objects with Transact-SQL
statements. This lesson shows you how to create a database, create a table in the database, and
then access and change the data in the table. Because this lesson is an introduction to using
Transact-SQL, it does not use or describe the many options that are available for these
statements. This tutorial assumes that you are running SQL Server Management Studio Express.
To create a table, you must provide a name for the table, and the names and data types of each
column in the table. It is also a good practice to indicate whether null values are allowed in each
column.
Most tables have a primary key, made up of one or more columns of the table. A primary key is
always unique. The Database Engine will enforce the restriction that any primary key value
cannot be repeated in the table.
For a list of data types and links for a description of each, see Data Types (Transact-SQL).
Note: The Database Engine can be installed as case sensitive or non-case sensitive. If the
Database Engine is installed as case sensitive, object names must always have the same case.
For example, a table named OrderData is a different table from a table named ORDERDATA. If
the Database Engine is installed as non-case sensitive, those two table names are considered to
be the same table, and that name can only be used one time.
Before you create the table in this tutorial, execute the USE command to change the database
context to the TestData database. Otherwise, you will create the table in the database you were
connected to earlier. That was probably your default database. Unless your default database has
been changed, the default database is the master database. You should not create objects in the
master database.
Switch the Query Editor connection to the TestData database - In a Query Editor window,
type and execute the following code to change your connection to the TestData database.
USE TestData
GO
To create a table - In a Query Editor window, type and execute the following code to create a
simple table named Products. The columns in the table are named ProductID, ProductName,
Price, and ProductDescription. The ProductID column is the primary key of the table. int,
varchar(25), money, and text are all data types. Only the Price and ProductionDescription
columns can have no data when a row is inserted or changed. This statement contains an
optional element (dbo.) called a schema. The schema is the database object that owns the table.
If you are an administrator, dbo is the default schema. dbo stands for database owner.
CREATE TABLE dbo.Products
(ProductID int PRIMARY KEY NOT NULL,
ProductName varchar(25) NOT NULL,
Price money NULL,
ProductDescription text NULL)
GO
How to insert and update data into a table with "INSERT" and "UPDATE" statements?
This is the third tutorial of a quick lesson on creating database objects with Transact-SQL
statements. This lesson shows you how to create a database, create a table in the database, and
then access and change the data in the table. Because this lesson is an introduction to using
Transact-SQL, it does not use or describe the many options that are available for these
statements. This tutorial assumes that you are running SQL Server Management Studio Express.
Now that you have created the Products table, you are ready to insert data into the table by using
the INSERT statement. After the data is inserted, you will change the content of a row by using
an UPDATE statement. You will use the WHERE clause of the UPDATE statement to restrict the
update to a single row. The four statements will enter the following data.
ProductID ProductName Price ProductDescription
1 Clamp 12.48 Workbench clamp
50 Screwdriver 3.17 Flat head
75 Tire Bar Tool for changing tires
3000 3mm Bracket .52
The basic syntax is: INSERT, table name, column list, VALUES, and then a list of the values to
be inserted. The two hyphens in front of a line indicate that the line is a comment and the text will
be ignored by the compiler. In this case, the comment describes a permissible variation of the
syntax.
To insert data into a table - Execute the following statement to insert a row into the Products
table that was created in the previous task. This is the basic syntax.
-- Standard syntax
INSERT dbo.Products (ProductID, ProductName, Price, ProductDescription)
VALUES (1, 'Clamp', 12.48, 'Workbench clamp')
GO
The following statement shows how you can change the order in which the parameters are
provided by switching the placement of the ProductID and ProductName in both the field list (in
parentheses) and in the values list.
-- Changing the order of the columns
INSERT dbo.Products (ProductName, ProductID, Price, ProductDescription)
VALUES ('Screwdriver', 50, 3.17, 'Flat head')
GO
The following statement demonstrates that the names of the columns are optional, as long as the
values are listed in the correct order. This syntax is common but is not recommended because it
might be harder for others to understand your code. NULL is specified for the Price column
because the price for this product is not yet known.
-- Skipping the column list, but keeping the values in order
INSERT dbo.Products
VALUES (75, 'Tire Bar', NULL, 'Tool for changing tires.')
GO
The schema name is optional as long as you are accessing and changing a table in your default
schema. Because the ProductDescription column allows null values and no value is being
provided, the ProductDescription column name and value can be dropped from the statement
completely.
-- Dropping the optional dbo and dropping the ProductDescription column
INSERT Products (ProductID, ProductName, Price)
VALUES (3000, '3mm Bracket', .52)
GO
To update the products table - Type and execute the following UPDATE statement to change
the ProductName of the second product from Screwdriver, to Flat Head Screwdriver.
UPDATE dbo.Products
SET ProductName = 'Flat Head Screwdriver'
WHERE ProductID = 50
GO
How to read data in a table with "SELECT" statements?
This is the fourth tutorial of a quick lesson on creating database objects with Transact-SQL
statements. This lesson shows you how to create a database, create a table in the database, and
then access and change the data in the table. Because this lesson is an introduction to using
Transact-SQL, it does not use or describe the many options that are available for these
statements. This tutorial assumes that you are running SQL Server Management Studio Express.
Use the SELECT statement to read the data in a table. The SELECT statement is one of the most
important Transact-SQL statements, and there are many variations in the syntax. For this tutorial,
you will work with five simple versions.
To read the data in a table - Type and execute the following statements to read the data in the
Products table.
-- The basic syntax for reading data from a single table
SELECT ProductID, ProductName, Price, ProductDescription
FROM dbo.Products
GO
You can use an asterisk to select all the columns in the table. This is often used in ad hoc
queries. You should provide the column list in you permanent code so that the statement will
return the predicted columns, even if a new column is added to the table later.
-- Returns all columns in the table
-- Does not use the optional schema, dbo
SELECT * FROM Products
GO
You can omit columns that you do not want to return. The columns will be returned in the order
that they are listed.
-- Returns only two of the columns from the table
SELECT ProductName, Price
FROM dbo.Products
GO
Use a WHERE clause to limit the rows that are returned to the user.
-- Returns only two of the records in the table
SELECT ProductID, ProductName, Price, ProductDescription
FROM dbo.Products
WHERE ProductID < 60
GO
You can work with the values in the columns as they are returned. The following example
performs a mathematical operation on the Price column. Columns that have been changed in this
way will not have a name unless you provide one by using the AS keyword.
-- Returns ProductName and the Price including a 7% tax
-- Provides the name CustomerPays for the calculated column
SELECT ProductName, Price * 1.07 AS CustomerPays
FROM dbo.Products
GO
How to create a login to access the database engine using "CREATE LOGIN" statements?
This is the first tutorial of a quick lesson on creating login and configure users for databases with
Transact-SQL statements. Granting a user access to a database involves three steps. First, you
create a login. The login lets the user connect to the SQL Server Database Engine. Then you
configure the login as a user in the specified database. And finally, you grant that user permission
to database objects. This lesson shows you these three steps, and shows you how to create a
view and a stored procedure as the object. This tutorial assumes that you are running SQL
Server Management Studio Express.
To access the Database Engine, users require a login. The login can represent the user's identity
as a Windows account or as a member of a Windows group, or the login can be a SQL Server
login that exists only in SQL Server. Whenever possible you should use Windows Authentication.
By default, administrators on your computer have full access to SQL Server. For this lesson, we
want to have a less privileged user; therefore, you will create a new local Windows Authentication
account on your computer. To do this, you must be an administrator on your computer. Then you
will grant that new user access to SQL Server. The following instructions are for Windows XP
Professional.
To create a new Windows account - Click Start, click Run, in the Open box, type %SystemRoot
%\system32\compmgmt.msc /s, and then click OK to open the Computer Management program.
Under System Tools, expand Local Users and Groups, right-click Users, and then click New
User.
In the User name box type Mary.
In the Password and Confirm password box, type a strong password, and then click Create to
create a new local Windows user.
To create a login - In a Query Editor window of SQL Server Management Studio, type and
execute the following code replacing computer_name with the name of your computer. FROM
WINDOWS indicates that Windows will authenticate the user. The optional
DEFAULT_DATABASE argument connects Mary to the TestData database, unless her
connection string indicates another database. This statement introduces the semicolon as an
optional termination for a Transact-SQL statement.
CREATE LOGIN [computer_name\Mary]
FROM WINDOWS
WITH DEFAULT_DATABASE = [TestData];
GO
This authorizes a user name Mary, authenticated by your computer, to access this instance of
SQL Server. If there is more than one instance of SQL Server 2005 on the computer, you must
create the login on each instance that Mary must access.
How to create a user to access a database using "CREATE USER" statements?
This is the second tutorial of a quick lesson on creating login and configure users for databases
with Transact-SQL statements. Granting a user access to a database involves three steps. First,
you create a login. The login lets the user connect to the SQL Server Database Engine. Then you
configure the login as a user in the specified database. And finally, you grant that user permission
to database objects. This lesson shows you these three steps, and shows you how to create a
view and a stored procedure as the object. This tutorial assumes that you are running SQL
Server Management Studio Express.
Mary now has access to this instance of SQL Server 2005, but does not have permission to
access the databases. She does not even have access to her default database TestData until
you authorize her as a database user.
To grant Mary access, switch to the TestData database, and then use the CREATE USER
statement to map her login to a user named Mary.
To create a user in a database - Type and execute the following statements (replacing
computer_name with the name of your computer) to grant Mary access to the TestData database.
USE [TestData];
GO
CREATE USER [Mary] FOR LOGIN [computer_name\Mary];
GO
Now, Mary has access to both SQL Server 2005 and the TestData database
How to create a view and a stored procedure using "CREATE VIEW/PROCEDURE"
statements?
This is the third tutorial of a quick lesson on creating login and configure users for databases with
Transact-SQL statements. Granting a user access to a database involves three steps. First, you
create a login. The login lets the user connect to the SQL Server Database Engine. Then you
configure the login as a user in the specified database. And finally, you grant that user permission
to database objects. This lesson shows you these three steps, and shows you how to create a
view and a stored procedure as the object. This tutorial assumes that you are running SQL
Server Management Studio Express.
Now that Mary can access the TestData database, you may want to create some database
objects, such as a view and a stored procedure, and then grant Mary access to them. A view is a
stored SELECT statement, and a stored procedure is one or more Transact-SQL statements that
execute as a batch.
Views are queried like tables and do not accept parameters. Stored procedures are more
complex than views. Stored procedures can have both input and output parameters and can
contain statements to control the flow of the code, such as IF and WHILE statements. It is good
programming practice to use stored procedures for all repetitive actions in the database.
For this example, you will use CREATE VIEW to create a view that selects only two of the
columns in the Products table. Then, you will use CREATE PROCEDURE to create a stored
procedure that accepts a price parameter and returns only those products that cost less than the
specified parameter value.
To create a view - Execute the following statement to create a very simple view that executes a
select statement, and returns the names and prices of our products to the user.
CREATE VIEW vw_Names
AS
SELECT ProductName, Price FROM Products;
GO
Test the view - Views are treated just like tables. Use a SELECT statement to access a view.
SELECT * FROM vw_Names;
GO
To create a stored procedure - The following statement creates a stored procedure name
pr_Names, accepts an input parameter named @VarPrice of data type money. The stored
procedure prints the statement Products less than concatenated with the input parameter that is
changed from the money data type into a varchar(10) character data type. Then, the procedure
executes a SELECT statement on the view, passing the input parameter as part of the WHERE
clause. This returns all products that cost less than the input parameter value.
CREATE PROCEDURE pr_Names @VarPrice money
AS
BEGIN
-- The print statement returns text to the user
PRINT 'Products less than ' + CAST(@VarPrice AS varchar(10));
-- A second statement starts here
SELECT ProductName, Price FROM vw_Names
WHERE Price < @varPrice;
END
GO
Test the stored procedure - To test the stored procedure, type and execute the following
statement. The procedure should return the names of the two products entered into the Products
table in Lesson 1 with a price that is less than 10.00.
EXECUTE pr_Names 10.00;
GO
How to grant a permission using "GRANT EXECUTE" statements?
This is the fourth tutorial of a quick lesson on creating login and configure users for databases
with Transact-SQL statements. Granting a user access to a database involves three steps. First,
you create a login. The login lets the user connect to the SQL Server Database Engine. Then you
configure the login as a user in the specified database. And finally, you grant that user permission
to database objects. This lesson shows you these three steps, and shows you how to create a
view and a stored procedure as the object. This tutorial assumes that you are running SQL
Server Management Studio Express.
As an administrator, you can execute the SELECT from the Products table and the vw_Names
view, and execute the pr_Names procedure; however, Mary cannot. To grant Mary the necessary
permissions, use the GRANT statement.
Procedure Title - Execute the following statement to give Mary the EXECUTE permission for the
pr_Names stored procedure.
GRANT EXECUTE ON pr_Names TO Mary;
GO
In this scenario, Mary can only access the Products table by using the stored procedure. If you
want Mary to be able to execute a SELECT statement against the view, then you must also
execute GRANT SELECT ON vw_Names TO Mary. To remove access to database objects, use
the REVOKE statement.
Note: If the table, the view, and the stored procedure are not owned by the same schema,
granting permissions becomes more complex. For information about how to configure
permissions on objects with different owners, see Ownership Chains.
About GRANT You must have EXECUTE permission to execute a stored procedure. You must
have SELECT, INSERT, UPDATE, and DELETE permissions to access and change data. The
GRANT statement is also used for other permissions, such as permission to create tables.
How to delete database objects with "DROP" statements?
To remove all database objects created by previous tutorials, you could just delete the database.
However, in this tutorial, you will go through the steps to reverse every action you took doing the
tutorial.
Removing permissions and objects - Before you delete objects, make sure you are in the
correct database:
USE TestData;
GO
Use the REVOKE statement to remove execute permission for Mary on the stored procedure:
REVOKE EXECUTE ON pr_Names FROM Mary;
GO
Use the DROP statement to remove permission for Mary to access the TestData database:
DROP USER Mary;
GO
Use the DROP statement to remove permission for Mary to access this instance of SQL Server
2005:
DROP LOGIN [\Mary];
GO
Use the DROP statement to remove the store procedure pr_Names:
DROP PROC pr_Names;
GO
Use the DROP statement to remove the view vw_Names:
DROP View vw_Names;
GO
Use the DELETE statement to remove all rows from the Products table:
DELETE FROM Products;
GO
Use the DROP statement to remove the Products table:
DROP Table Products;
GO
You cannot remove the TestData database while you are in the database; therefore, first switch
context to another database, and then use the DROP statement to remove the TestData
database:
USE MASTER;
GO
DROP DATABASE TestData;
GO
What is a database?
To find out the location of database files, you can query the "sys.database_files" view as shown in
this tutorial example:
USE FyiCenterData
GO
If you don't like the default behavior of the CREATE DATABASE statement, you can specify the
physical database files with a longer statement:
CREATE DATABASE database_name
ON (NAME = logical_data_name,
FILENAME = physical_data_name,
SIZE = x, MAXSIZE = y, FILEGROWTH = z)
LOG ON (NAME = logical_log_name,
FILENAME = physical_log_name,
SIZE = x, MAXSIZE = y, FILEGROWTH = z)
For example, the following statement will create a database with database files located in the C:\temp
directory:
USE master
GO
If don't like the name of a database, you can change it by using the "ALTER DATABASE" statement
with the following syntax:
ALTER DATABASE database_name
MODIFY NAME = new_database_name
The tutorial example below shows you how change the database name from "FyiCenterData" to
"FyiCenterComData":
ALTER DATABASE FyiCenterData
MODIFY NAME = FyiCenterComData
GO
The database name 'FyiCenterComData' has been set
If you are trying to rename a database that is in use, you will get an error message like this: "The
database could not be exclusively locked to perform the operation."
Before renaming a database, you must stop all client sessions using this database. Otherwise, you
will get an error as shown in this tutorial example:
2. Keep the first instance running and launch another instance of SQL Server Management Studio:
ALTER DATABASE FyiCenterComData
MODIFY NAME = FyiCenterData
GO
Msg 5030, Level 16, State 2, Server LOCALHOST\SQLEXPRESS
The database could not be exclusively locked to perform
the operation.
A database is always in one specific state. For example, these states include ONLINE, OFFLINE, or
SUSPECT. To verify the current state of a database, select the state_desc column in the
sys.databases catalog view. The following table defines the database states.
ONLINE - Database is available for access. The primary filegroup is online, although the undo
phase of recovery may not have been completed.
OFFLINE - Database is unavailable. A database becomes offline by explicit user action and
remains offline until additional user action is taken. For example, the database may be taken
offline in order to move a file to a new disk. The database is then brought back online after the
move has been completed.
RESTORING - One or more files of the primary filegroup are being restored, or one or more
secondary files are being restored offline. The database is unavailable.
RECOVERING - Database is being recovered. The recovering process is a transient state; the
database will automatically become online if the recovery succeeds. If the recovery fails, the
database will become suspect. The database is unavailable.
RECOVERY PENDING - SQL Server has encountered a resource-related error during recovery.
The database is not damaged, but files may be missing or system resource limitations may be
preventing it from starting. The database is unavailable. Additional action by the user is required
to resolve the error and let the recovery process be completed.
SUSPECT - At least the primary filegroup is suspect and may be damaged. The database cannot
be recovered during startup of SQL Server. The database is unavailable. Additional action by the
user is required to resolve the problem.
EMERGENCY - User has changed the database and set the status to EMERGENCY. The
database is in single-user mode and may be repaired or restored. The database is marked
READ_ONLY, logging is disabled, and access is limited to members of the sysadmin fixed server
role. EMERGENCY is primarily used for troubleshooting purposes. For example, a database
marked as suspect can be set to the EMERGENCY state. This could permit the system
administrator read-only access to the database.
You can use the "ALTER DATABASE" to change database update options as shown in the tutorial
below:
USE FyiCenterComData
GO
As you can see from the output, inserting data into a table is not allowed if the database is in
READ_ONLY mode.
How to set database to be SINGLE_USER?
You can use the "ALTER DATABASE" to change database user access options as shown in the
tutorial below:
USE FyiCenterComData
GO
System databases are created by the SQL Server itself during the installation process. System
databases are used by the SQL server to help manage other user databases and client execution
sessions. SQL Server 2005 Express Edition uses 4 system databases:
master - The brain of a SQL server - Stores server configuration, runtime information, and
database metadata.
model - An empty database model - Used to clone new databases.
msdb - The background job scheduler - Used for background jobs and related tasks.
tempdb - The temporary database - Used by the server as a scratch pad.
What is a table?
A table in database is a data object used to store data. Tables have the following features:
Data is stored in a table with a structure of rows and columns.
Columns must be pre-defined with names, types and constrains.
A table object may have other associated data objects like, constrains, triggers, indexes, and
statistics.
For example, a table called Address may have columns defined to store different elements of an
address like, street number, city, country, postal code, etc.
DDL (Data Definition Language) statements are statements to create and manage data objects in the
database. The are three primary DDL statements to create and manage tables:
CREATE TABLE - Creating a new table.
ALTER TABLE - Altering the definition of an existing table.
DROP TABLE - Dropping an existing table.
DML (Data Manipulation Language) statements are statements to change data values in database
tables. The are 3 primary DML statements:
INSERT - Inserting new rows into database tables. For example "INSERT INTO fyi_links
VALUES (101, 'dev.fyicenter.com', NULL, 0, '2006-04-30')" inserts a single new row in the
fyi_links table.
UPDATE - Updating existing rows in database tables .
DELETE - Deleting existing rows from database tables.
If you want to practice DML statements, like INSERT, UPDATE and DELETE statements, you should
create a testing table. The tutorial exercise shows you a good example:
CREATE TABLE fyi_links (id INTEGER PRIMARY KEY,
url VARCHAR(80) NOT NULL,
notes VARCHAR(1024),
counts INT,
created DATETIME NOT NULL DEFAULT(getdate()))
GO
You should keep this table to practice other tutorial exercises presented in this collection.
How To Insert a New Row into a Table with "INSERT INTO" Statements?
To insert a new row into a table, you can use the INSERT INTO statement with values specified for all
columns as in the following syntax:
INSERT INTO table_name VALUES (list_of_values_of_all columns)
Note that the list of values of all columns must be specified in the same order as how columns are
defined in the CREATE TABLE statement. The following tutorial example inserts a row into "fyi_links":
INSERT INTO fyi_links VALUES (101,
'dev.fyicenter.com',
NULL,
0,
'2006-04-30')
GO
(1 row(s) affected)
If a column is defined with a default value in a table, you can use the key word DEFAULT in the
INSERT statement to take the default value for that column. The following tutorial exercise gives a
good example:
INSERT INTO fyi_links VALUES (102,
'dba.fyicenter.com',
NULL,
0,
DEFAULT)
GO
(1 row(s) affected)
The default value, getdate(), is used for "created" column, which gives the current date
If you don't want to specify values for columns that have default values, or you want to specify values
to columns in an order different than how they are defined, you can provide a column list in the
INSERT statement. If a column is omitted in the column, SQL Server applies 3 rules:
If default value is defined for the column, that default value will be used.
If no default value is defined for the column and NULL is allowed, NULL will be used.
If no default value is defined for the column and NULL is not allowed, SQL Server will reject the
insert statement with an error.
The first INSERT statement shows that: the order of the columns is reversed; the default value is
taken for the un-specified column "created"; the NULL value is taken for the un-specified column
"counts", since is has no default value defined and null is allowed.
The second INSERT statement shows the error you get for the un-specified column "url", because it
has no default value, and null is not allowed.
What Happens If You Insert a Duplicate Key for the Primary Key Column?
If your table has a primary key column, and you are trying to insert a new row with duplicate key value
on the primary key column, you will get an error. The reason is simple - Primary key column does not
allow duplicate values. The following tutorial exercise gives you a good example:
SELECT * FROM fyi_links
INSERT INTO fyi_links VALUES (101,
'sql.fyicenter.com',
NULL,
0,
'2006-04-30')
GO
Msg 2627, Level 14, State 1, Line 1
Violation of PRIMARY KEY constraint
'PK__fyi_links__03317E3D'. Cannot insert duplicate
key in object 'dbo.fyi_links'.
The statement has been terminated.
You are getting this error, because value "101" has already been used by an existing row.
If you want to insert multiple rows with a single INSERT statement, you can use a subquery instead of
the VALUES clause. Rows returned from the subquery will be inserted the target table. The following
tutorial exercise gives you a good example:
INSERT INTO fyi_links SELECT id+500, REVERSE(url),
notes, counts, created FROM fyi_links
GO
(3 row(s) affected)
As you can see, "INSERT INTO ... SELECT ..." is powerful statement. you can use it build up data in
tables quickly.
If you want to update some values in one row or multiple rows in a table, you can use the UPDATE
statement. The tutorial script below shows a good example:
SELECT * FROM fyi_links WHERE id = 101
GO
id url notes counts created
101 dev.fyicenter.com NULL 0 2006-04-30
As you can see, the SET clause takes column and value pairs to provide new values, while the
WHERE clause defines which row to apply the update
If the WHERE clause in an UPDATE statement matches multiple rows, the SET clause will be applied
to all matched rows. This rule allows you to update values on multiple rows in a single UPDATE
statement. Here is a good example:
SELECT * FROM fyi_links WHERE id >= 500
GO
id url notes counts created
601 moc.retneciyf.ved NULL 0 2006-04-30
602 moc.retneciyf.abd NULL 0 2007-05-19
603 moc.retneciyf.aqs NULL NULL 2007-05-19
The UPDATE statement updated 3 rows with the same new values.
This statement increased values in the id column by 200. It also updated the counts column with the
newly increased id value.
The answer is NO. The order of columns in the SET clause of the UPDATE statement is NOT
important. You probably already noticed from the previous tutorial. There is a BIG DIFFERENCE
among SQL Server, MySQL and Oracle on update multiple columns with previous values:
SQL Server provides you the existing values from the database on columns names used in new
value expressions. So the order of columns in the SET clause is NOT important
MySQL provides you the updated values on columns names used in new value expressions. So
the order of columns in the SET clause is important.
Oracle provides you the existing values from the database on columns names used in new value
expressions. So the order of columns in the SET clause is NOT important
Notice that the "id" in the "counts" new value expression is taking the old value of the "id" column, not
the updated value, even the "id" column is updated before the "counts" column.
Now try this on a MySQL server, you will get different result.
If you want to update values in one table with values from another table, you can use a subquery as
an expression in the SET clause. The subquery should return only one row for each row in the update
table that matches the WHERE clause. The tutorial exercise below shows you a good example:
-- Create another table
CREATE TABLE fyi_rates (id INTEGER,
comment VARCHAR(16))
Go
Note that if column names are confusing between the inner table and the outer table, you need to
prefix column names with table names, like "fyi_rates.id = fyi_links.id".
If you use a subquery to assign new values in the SET clause in an UPDATE statement, and the
subquery returns no rows for an outer row, SQL Server will provide a NULL value to the SET clause.
The tutorial exercise below shows you a good example:
-- insert a new row
INSERT INTO fyi_links (id, url, notes)
VALUES (0, 'www.fyicenter.com', 'Number one')
GO
(1 row(s) affected)
Column "notes" gets updated with NULL if there is no return rows in the subquery
If a subquery is used in a UPDATE statement, it must return exactly one row for each row in the
update table that matches the WHERE clause. If it returns multiple rows, SQL Server will give you an
error message. To test this out, you can try the following tutorial exercise:
-- insert two rows to fyi_rates
INSERT INTO fyi_rates VALUES (0, 'Number 1')
GO
INSERT INTO fyi_rates VALUES (0, 'Number 2')
GO
It is clear that we are using subquery as an expression, and it must return 0 or 1 row. Otherwise, we
will get an error.
How To Delete an Existing Row with DELETE Statements?
If you want to delete an existing row from a table, you can use the DELETE statement with a WHERE
clause to identify that row. Here is good sample of DELETE statements:
-- insert a row for this test
INSERT INTO fyi_links (url, id)
VALUES ('www.myspace.com', 301)
GO
(1 row(s) affected)
You can delete multiple rows from a table in the same way as deleting a single row, except that the
WHERE clause will match multiple rows. The tutorial exercise below deletes 3 rows from the fyi_links
table:
-- view rows to be deleted
SELECT id, url, notes, counts FROM fyi_links
WHERE id > 300
GO
id url notes counts
801 moc.retneciyf.ved Wrong 1202
802 moc.retneciyf.abd Wrong 1204
803 moc.retneciyf.aqs Wrong 1206
If you want to delete all rows from a table, you have two options:
Use the DELETE statement with no WHERE clause.
Use the TRUNCATE TABLE statement.
If you want to delete all rows from a table, you have two options:
Use the DELETE statement with no WHERE clause.
Use the TRUNCATE TABLE statement.
The TRUNCATE statement is more efficient the DELETE statement. The tutorial exercise shows you
a good example of TRUNCATE statement:
SELECT COUNT(*) FROM fyi_rates
GO
5
If you want to query from two tables with a full outer join, you can use the FULL OUTER JOIN ... ON
clause in the FROM clause. The following query returns output with a full outer join from two tables:
fyi_links and fyi_rates. The join condition is that the id in the fyi_links table equals to the id in the
fyi_rates table:
SELECT l.id, l.url, r.comment FROM fyi_links l
FULL OUTER JOIN fyi_rates r ON l.id = r.id
GO
id url comment
101 dev.fyicenter.com The best
102 dba.fyicenter.com Well done
103 sqa.fyicenter.com Thumbs up
104 www.mysql.com NULL
105 www.oracle.com NULL
106 www.php.net NULL
107 www.winrunner.com NULL
NULL NULL Number 1
NULL NULL Not bad
NULL NULL Good job
NULL NULL Nice tool
A subquery is a SELECT statement used as part of the selection criteria of the main SELECT
statement. The subquery specified in the WHERE clause will be evaluated repeated on each row of
the selection base table. The output of the subquery will be used in the final evaluation of the criteria.
Usually, subqueries are used in the following Boolean operations:
"expression IN (subquery)" - True if the expression matches one of the returned values from the
subquery.
"expression NOT IN (subquery)" - True if the expression does not match any of the returned
values from the subquery.
"EXISTS (subquery)" - True if the subquery returns one or more rows.
"NOT EXISTS (subquery)" - True if the subquery returns no rows.
If you need to sort the output from two queries grouped together with a UNION operator, you need to
apply the ORDER BY clause at the group level, not at the subquery level.
Note that SQL Server and MySQL react differently to the ORDER BY clause used in a subquery of a
UNION operator:
SQL Server will give error if ORDER BY is used inside a subquery of a UNION operator.
MySQL will ignore the ORDER BY clause inside a subquery of a UNION operator.
The following tutorial exercise shows you how to use ORDER BY clause with UNION operator:
(SELECT * FROM fyi_links WHERE tag = 'DBA'
ORDER BY created)
UNION
(SELECT * FROM fyi_links WHERE tag = 'DEV'
ORDER BY created)
GO
Msg 156, Level 15, State 1, Line 2
Incorrect syntax near the keyword 'ORDER'.
Msg 156, Level 15, State 1, Line 5
Incorrect syntax near the keyword 'ORDER'.
Note that the ORDER BY works nicely. Rows returned from both subqueries are sorted together.
The SELECT statement is also called the query statement. It is the most frequently used SQL
statement in any database application. SELECT statements allows you to retrieve data from one or
more tables or views, with different selection criteria, grouping criteria and sorting orders.
If you want to follow the tutorial exercises presented in this collection, you need to create a testing
table and insert some test data, as shown in the following sample script:
CREATE TABLE fyi_links (id INTEGER PRIMARY KEY,
url VARCHAR(80) NOT NULL,
notes VARCHAR(1024),
counts INT,
created DATETIME NOT NULL DEFAULT(getdate()))
GO
You should keep this table and its data to practice other tutorial exercises presented in this collection.
How To Select All Columns of All Rows from a Table with a SELECT statement?
The simplest query statement is the one that selects all columns of all rows from a single table:
"SELECT * FROM tableName". The (*) in the SELECT clause tells the query to return all columns.
The missing WHERE clause tells the query to return all rows in specified table. The tutorial exercise
below returns all columns and all rows from table "fyi_links":
SELECT * FROM fyi_links
id url notes counts created
101 dev.fyicenter.com NULL 0 2006-04-30
102 dba.fyicenter.com NULL 0 2007-05-19
103 sqa.fyicenter.com NULL NULL 2007-05-19
If you want explicitly tell the query to return some specific columns, you can specify the column
names in the SELECT clause. The following select statement returns only three columns, "id",
"created" and "url" from the table "fyi_links":
SELECT id, created, url FROM fyi_links
id created url
101 2006-04-30 dev.fyicenter.com
102 2007-05-19 dba.fyicenter.com
103 2007-05-19 sqa.fyicenter.com
If you don't want select all rows from a table, you can specify a WHERE clause to tell the query to
return only the rows that meets the condition defined in the WHERE clause. The WHERE clause
condition is a normal Boolean expression. If any data from the table needs to be used in the Boolean
expression, column names should be used to represent the table data.
The first select statement below only returns rows that have url names containing the letter "a". The
second select statement returns no rows, because the WHERE clause results FALSE for all rows in
the table.
SELECT * FROM fyi_links WHERE url LIKE '%a%'
GO
id url notes counts created
102 dba.fyicenter.com NULL 0 2007-05-19
103 sqa.fyicenter.com NULL NULL 2007-05-19
If you want to continue with other tutorial exercises in this FAQ collection, you need to add more data
to the testing table. Follow the script below to add a new column and more rows:
ALTER TABLE fyi_links ADD tag VARCHAR(8)
GO
UPDATE fyi_links
SET counts = CAST(LOG(id)*1000000 AS INT) % 1000
GO
If you want the returning rows to be sorted, you can specify a sorting expression in the ORDER BY
clause. The simplest sort expression is column name who's values will be sorted by. The following
select statement returns rows sorted by the values in the "counts" column:
SELECT * FROM fyi_links ORDER BY counts
GO
id url notes counts created tag
101 dev.fyicenter.com NULL 120 2006-04-30 DEV
104 www.mysql.com 390 2006-01-01 DBA
106 www.php.net 439 2004-01-01 DEV
103 sqa.fyicenter.com NULL 728 2007-05-19 SQA
107 www.winrunner.com 828 2003-01-01 SQA
105 www.oracle.com 960 2005-01-01 DBA
102 dba.fyicenter.com NULL 972 2007-05-19 DBA
You can specifying multiple columns in the ORDER BY clause as shown in the following example
statement, which returns rows sorted by "tag" and "counts" values:
SELECT tag, counts, url, created
FROM fyi_links ORDER BY tag, counts
GO
tab counts url created
DBA 390 www.mysql.com 2006-01-01
DBA 960 www.oracle.com 2005-01-01
DBA 972 dba.fyicenter.com 2007-05-19
DEV 120 dev.fyicenter.com 2006-04-30
DEV 439 www.php.net 2004-01-01
SQA 728 sqa.fyicenter.com 2007-05-19
SQA 828 www.winrunner.com 2003-01-01
If you want to sort a column in descending order, you can specify the DESC keyword in the ORDER
BY clause. The following SELECT statement first sorts the "tag" in descending order, then sorts the
"counts" in ascending order:
SELECT tag, counts, url, created
FROM fyi_links ORDER BY tag DESC, counts
GO
tab counts url created
SQA 728 sqa.fyicenter.com 2007-05-19
SQA 828 www.winrunner.com 2003-01-01
DEV 120 dev.fyicenter.com 2006-04-30
DEV 439 www.php.net 2004-01-01
DBA 390 www.mysql.com 2006-01-01
DBA 960 www.oracle.com 2005-01-01
DBA 972 dba.fyicenter.com 2007-05-19
If you want to count the number of rows, you can use the COUNT(*) function in the SELECT clause.
The following tutorial exercise shows you some good examples:
SELECT COUNT(*) FROM fyi_links
GO
7
SELECT COUNT(*) FROM fyi_links
WHERE url LIKE '%fyi%'
GO
3
So there are 7 rows in total in table "fyi_links", and 3 rows that have 'fyi' as part of their url names.
Select (query) statements can be used on views in the same way as tables. The following tutorial
exercise helps you creating a view and running a query statement on the view:
CREATE VIEW myLinks AS SELECT * FROM fyi_links
WHERE url LIKE '%fyi%'
GO
If there are duplications in the returning rows, and you want to remove the duplications, you can use
the keyword DISTINCT in the SELECT clause. The DISTINCT applies to the combination of all data
fields specified in the SELECT clause. The tutorial exercise below shows you how DISTINCT works:
CREATE TABLE fyi_team (first_name VARCHAR(8),
last_name VARCHAR(8))
GO
Group functions are functions applied to a group of rows. Examples of group functions are:
COUNT(*) - Returns the number of rows in the group.
MIN(exp) - Returns the minimum value of the expression evaluated on each row of the group.
MAX(exp) - Returns the maximum value of the expression evaluated on each row of the group.
AVG(exp) - Returns the average value of the expression evaluated on each row of the group.
SUM(exp) - Returns the sum value of the expression evaluated on each row of the group.
COUNTDISTINCT(exp) - Returns the number of distinct values of the expression evaluated on
each row of the group.
How To Divide Query Output into Multiple Groups with the GROUP BY Clause?
Sometimes, you want to divide the query output into multiple groups, and apply group functions on
each individual groups. Dividing query output into multiple groups can be done with the GROUP BY
clause. Here is the syntax of a SELECT statement with a GROUP BY clause.
SELECT group_level_fields FROM source_tables
WHERE search_condition
GROUP BY group_by_expression
group_by_express - An list of columns to be used as the group criteria - Rows that have the same
combination of values of there columns form a single group.
group_level_fields - An list of selection expressions that can be evaluated at the group level.
The final output of the SELECT statement is the resulting values of group_level_fields for each group.
The following script gives you a good GROUP BY example with a single column as the
group_by_expression. In this case, rows with the same value of this column will be considered as a
single group.
SELECT tag, COUNT(*), MAX(counts), MIN(created)
FROM fyi_links GROUP BY tag
GO
tag COUNT(*) MAX(counts) MIN(created)
DBA 3 972 2005-01-01
DEV 2 439 2004-01-01
SQA 2 828 2003-01-01
Notice that, column "tag" can also be used in group_level_fields, because it is used as the
group_by_expression, and becomes a constant for any given group.
How To Apply Filtering Criteria at Group Level with The HAVING Clause?
Let's say you have divided the query output into multiple groups with the GROUP BY clause. Now
you are only interested in some of the groups, not all the groups. If you want to filter out some groups
from the query, you can apply filtering criteria at the group level by using the HAVING clause inside
the GROUP BY clause with this syntax:
SELECT group_level_fields FROM source_tables
WHERE search_condition
GROUP BY group_by_expression
HAVING group_filtering_condition
Since group_filtering_condition applies to groups, only group level expressions can be used in
group_filtering_condition. The following tutorial exercise gives you some good examples of HAVING
clause:
SELECT tag, COUNT(*), MIN(created), AVG(counts)
FROM fyi_links
GROUP BY tag HAVING AVG(counts) > 300
GO
tag COUNT(*) MIN(created) AVG(counts)
DBA 3 2005-01-01 774
SQA 2 2003-01-01 778
Note that the more criteria you have in the HAVING clause, the less groups you will get.
If you have a column with duplicated values, and you want to know what are those duplicated values
are and how many duplicates are there for each of those values, you can use the "GROUP BY ...
HAVING" clause as shown in the following example. It returns how many duplicated first names in the
fyi_team table:
SELECT first_name, COUNT(*) FROM fyi_team
GROUP BY first_name HAVING COUNT(*) > 1
GO
first_name count(*)
John 5
If you want to break your output into smaller groups, you can specify multiple column names or
expressions in the GROUP BY clause. Output in each group must satisfy a specific combination of
the expressions listed in the GROUP BY clause. The more columns or expressions entered in the
GROUP BY clause, the smaller the groups will be.
The tutorial exercise below shows you how to break data into groups per "tag" and per year when
they were created. Then the group function COUNT(*) is applied on each group:
SELECT tag, YEAR(created), COUNT(*)
FROM fyi_links GROUP BY tag, YEAR(created)
GO
tag year(created) count(*)
SQA 2003 1
DEV 2004 1
DBA 2005 1
DBA 2006 1
DEV 2006 1
DBA 2007 1
SQA 2007 1
If the query output is aggregated as groups, you can sort the groups by using group functions in the
ORDER BY clause. The following statement returns the maximum "counts" in each group, determined
by a unique combination of tag and year. The group output is sorted by the maximum "counts" in
each group in ascending order:
SELECT tag, YEAR(created), MAX(counts)
FROM fyi_links GROUP BY tag, YEAR(created)
ORDER BY MAX(counts)
GO
tag year(created) max(counts)
DEV 2006 120
DBA 2006 390
DEV 2004 439
SQA 2007 728
SQA 2003 828
DBA 2005 960
DBA 2007 972
What Is SQL Language?
SQL, SEQUEL (Structured English Query Language), is a language for RDBMS (Relational Database
Management Systems).
During the 1970s, a group at IBM's San Jose research center developed a database system "System
R" based upon Codd's model. Structured English Query Language ("SEQUEL") was designed to
manipulate and retrieve data stored in System R. The acronym SEQUEL was later condensed to
SQL.
SQL was adopted as a standard by ANSI (American National Standards Institute) in 1986 and ISO
(International Organization for Standardization) in 1987. Since then, SQL standard has gone through
a number of revisions:
1986, SQL-86 or SQL-87 - First published by ANSI. Ratified by ISO in 1987.
1989, SQL-89 - Minor revision.
1992, SQL-92 or SQL2 - Major revision (ISO 9075).
1999, SQL:1999 or SQL3 - Added regular expression matching, recursive queries, triggers, non-
scalar types and some object-oriented features.
2003, SQL:2003 - Introduced XML-related features, window functions, standardized sequences
and columns with auto-generated values (including identity-columns).
2006, SQL:2006 - ISO/IEC 9075-14:2006 defines ways in which SQL can be used in conjunction
with XML.
In order to make it more powerful, SQL has been enhanced with additional features such as:
Control-of-flow language - Like BEGIN and END, BREAK, CONTINUE, GOTO, IF and ELSE,
RETURN, WAITFOR, and WHILE statements.
Local variables - Like DECLARE and SET statements
Various support functions for string processing, date processing, mathematics, etc. - Like SIN(),
ASIN(), LOG(), etc.
Improvements to DELETE and UPDATE statements - Both the DELETE and UPDATE
statements allow a FROM clause to be added which allows joins to be included.
A Transact-SQL statement is a basic execution unit of the Transact-SQL language. Here are some
examples of Transact-SQL statements:
"CREATE TABLE ...;" - A data definition language statement that defines a table.
"INSERT INTO ...;" - A data manipulation language statement that inserts data into a table.
"SELECT * FROM ...;" - A query statement that returns data from a table.
"DROP TABLE ...;" - A data definition language statement that deletes a table.
"DECLARE @name data_type;" - A declaration statement that defines a local variable.
"SET @name = expression;" - An assignment statement that assigns a value to a local variable.
"BEGIN TRANSACTION;" - A transaction management statement that marks the beginning of a
transaction.
"ROLLBACK TRANSACTION;" - A transaction management statement that rolls back all changes
of a transaction.
A batch is a group of one or more Transact-SQL statements sent at the same time from an
application to SQL Server 2005 for execution. SQL Server compiles the statements of a batch into a
single executable unit, called an execution plan. The statements in the execution plan are then
executed one at a time.
How to define and send a batch is depending on the client application you are using. For example:
You need to use the GO command in "sqlcmd" tool to end a batch and send it to SQL server.
SQL Server Management Studio also uses GO command to separate batches when multiple
statements are selected for execution.
In ADO, a batch is defined as all the statements entered in the CommandText property of a Command
object.
If a statement batch has multiple statements, and one of them has compilation error, all statements in
the batch will not be executed. The tutorial exercise below gives you some good examples:
SELECT getdate();
SELECT getdates();
SELECT getdate();
GO
Msg 195, Level 15, State 10, Line 2
'getdates' is not a recognized built-in function name.
As you can see, the compilation error on the second statement stops the execution of all statements.
"sqlcmd" is a command line client application to run Transact-SQL statements on a target SQL
Server.
When "sqlcmd" is started and connected to a SQL Server, it will start a new batch and prompt you to
enter the first statement of the batch. You can enter one or more statements in one or more lines to
form a Transact-SQL statement batch.
To end a batch of statements and send it to the SQL Server for execution, you need to enter the GO
command. The following "sqlcmd" tutorial session sends two batches to the SQL Server:
C:\>sqlcmd -S localhost\sqlexpress -U sa -P FYIcenter
1> SELECT getdate();
2> SELECT getdates();
3> SELECT getdate();
4> GO
Msg 195, Level 15, State 10, Line 2
'getdates' is not a recognized built-in function name.
1> SELECT getdate();
2> SELECT getdate();
3> SELECT getdate();
4> GO
-----------------------
2007-05-19 22:55:07.233
(1 rows affected)
-----------------------
2007-05-19 22:55:07.233
(1 rows affected)
-----------------------
2007-05-19 22:55:07.233
(1 rows affected)
1>QUIT
C:\
Normally, messages are generated by SQL Server and returned to the client applications associated
with the execution result of statement batches. But you can define your messages and ask the SQL
Server to your client session with the PRINT statement, as shown in this tutorial exercise:
C:\>sqlcmd -S localhost\sqlexpress -U sa -P FYIcenter
1> PRINT 'What time is it?';
2> SELECT GETDATE();
3> GO
What time is it?
-----------------------
2007-05-19 21:51:23.797
(1 rows affected)
Note that the SELECT statement returns query result, which is very different than messages returned
by the PRINT statement.
Data types in SQL Server 2005 are organized into the following categories:
Exact Numerics - BIGINT, INT, SMALLINT, TINYINT, BIT, DECIMAL, NUMERIC, MONEY, and
SMALLMONEY.
Approximate Numerics - FLOAT, and REAL.
Date and Time - DATETIME and SMALLDATETIME.
Character Strings - CHAR, VARCHAR, and TEXT.
Unicode Character Strings - NCHAR, NVARCHAR, and NTEXT
Binary Strings - BINARY, VARBINARY, and IMAGE.
Other Data Types - CURSOR, SQL_VARIANT, TABLE, UNIQUEIDENTIFIER, TIMESTAMP, and
XML.
Exact numeric data types are used to store numeric values with exact precisions and scales. SQL
Server 2005 supports the following exact numeric data types:
BIGINT - 8-byte integers in the range of -2^63 (-9,223,372,036,854,775,808) to 2^63-1
(9,223,372,036,854,775,807).
INT - 4-byte integers in the range of -2^31 (-2,147,483,648) to 2^31-1 (2,147,483,647).
SMALLINT - 2-byte integers in the range of -2^15 (-32,768) to 2^15-1 (32,767).
TINYINT - 1-byte integers in the range of 0 to 255.
BIT - 1-bit integers with 2 values: 0 and 1.
DECIMAL - Decimal numbers with a fixed precision p and a fixed scale s defined as
DECIMAL(p,s). DECIMAL values are in the range of -10^38+1 to 10^38-1. DECIMAL has a
synonym of DEC.
NUMERIC - Same as DECIMAL.
MONEY - Currency values stored in 8 bytes in the range of -922,337,203,685,477.5808 to
922,337,203,685,477.5807
SMALLMONEY - Currency values stored in 4 bytes in the range of - 214,748.3648 to
214,748.3647
Date and time data types are used to store an instances of calendar dates and times. SQL Server
2005 supports the following date and time data types:
DATETIME - Date and time values stored in 8 bytes with 4 bytes for the date and 4 bytes for the
time. DATETIME values are in the range of January 1, 1753 to December 31, 9999 with a
precision of 3.33 milliseconds.
SMALLDATETIME - Date and time values stored in 4 bytes with 2 bytes for the date and 2 bytes
for the time. SMALLDATETIME values are in the range of January 1, 1900 to June 6, 2079 with a
precision of 1 minute.
Note that SQL Server does not support DATE and TIME data types separately.
Character string data types are used to store code page based character strings. SQL Server 2005
supports the following character string data types:
CHAR - Code page based character strings with a fixed length of n bytes defined as CHAR(n).
The maximum length is 8,000 bytes. CHAR has a synonym of CHARACTER.
VARCHAR - Code page based character strings with a variable length of n bytes defined as
VARCHAR(n). The maximum length is 8,000 bytes. VARCHAR has two synonyms of CHAR
VARYING and CHARACTER VARYING. VARCHAR also has special form as VARCHAR(MAX),
which can store up to 2^31-1 bytes.
TEXT - Code page based character strings with a variable length up to 2^31-1 (2,147,483,647)
bytes. TEXT is equivalent to VARCHAR(MAX).
Unicode character string data types are used to store Unicode character strings. SQL Server 2005
supports the following Unicode character string data types:
NCHAR - Unicode character strings with a fixed length of n characters defined as NCHAR(n). The
maximum length is 4,000 characters. NCHAR has two synonyms of NATIONAL CHAR and
NATIONAL CHARACTER.
VARCHAR - Unicode character strings with a variable length of n characters defined as
VARCHAR(n). The maximum length is 4,000 characters. NVARCHAR has two synonyms of
NATIONAL CHAR VARYING and NATIONAL CHARACTER VARYING. NVARCHAR also has
special form as NVARCHAR(MAX), which can store up to 2^31-1 bytes.
NTEXT - Unicode character strings with a variable length up to 2^31-1 (2,147,483,647) bytes.
NTEXT is equivalent to NVARCHAR(MAX). NTEXT has a synonym of NATIONAL TEXT.
Binary string data types are used to store binary strings. SQL Server 2005 supports the following
binary string data types:
BINARY - Binary strings with a fixed length of n bytes defined as BINARY(n). The maximum
length is 8,000 bytes.
VARBINARY - Binary strings with a variable length of n bytes defined as VARBINARY(n). The
maximum length is 8,000 bytes. VARBINARY has a synonym of BINARY VARYING.
VARBINARY also has special form as VARBINARY(MAX), which can store up to 2^31-1 bytes.
IMAGE - Binary strings with a variable length up to 2^31-1 (2,147,483,647) bytes.
Both CHAR and NCHAR are fixed length data types. But they have the following main differences:
CHAR stores characters based on the code page with 1 byte per character most of the time.
NCHAR stores characters using Unicode character set with 2 bytes per character most of the
time.
CHAR(n) specifies a length of n bytes by default.
NCHAR(n) specifies a length of n characters by default.
CHAR and VARCHAR are both used to store code page based character strings. But they have the
following main differences:
CHAR(n) stores character strings with a fixed length, n bytes, storage format.
VARCHAR(n) stores character strings with a variable length, less than n bytes, storage format.
If the input string of CHAR(n) has less than n bytes, it will be padded with space characters to
become n bytes.
If the input string of VARCHAR(n) has less than n bytes, it will not be padded with any characters.
If the input string of CHAR(n) has more than n bytes, it will be truncated to n bytes.
If the input string of VARCHAR(n) has more than n bytes, it will also be truncated to n bytes.
Date and time data types are used to store an instances of calendar dates and times. SQL Server
2005 supports the following date and time data types:
DATETIME - Date and time values stored in 8 bytes with 4 bytes for the date and 4 bytes for the
time. DATETIME values are in the range of January 1, 1753 to December 31, 9999 with a
precision of 3.33 milliseconds.
SMALLDATETIME - Date and time values stored in 4 bytes with 2 bytes for the date and 2 bytes
for the time. SMALLDATETIME values are in the range of January 1, 1900 to June 6, 2079 with a
precision of 1 minute.
Note that SQL Server does not support DATE and TIME data types separately.
A constant, or literal, is a symbol that represents a specific value of a specific data type. Constants or
literals are used commonly as the default values for table columns, variables, and parameters. The
format of constant or literal depends on the data type of the value it represents. There are x formats
used to specify literals in SQL Server:
Integer Number Literals - Strings of numbers prefixed with (+/-) as the sign if needed. They are
used for integer data types. For example: -2255.
Decimal Number Literals - Strings of numbers with a single decimal point and an optional prefix
sign (+/-). They are used for DECIMAL data type. For example: 1894.1204.
Floating Point Number Literals - Numeric values represented in the scientific notation. They are
used for FLOAT data type. For example: 9.22337e+010.
Character String Literals - Strings of characters enclosed in single quotes. They are used for
character string data types. . For example: 'Welcome to FYIcenter.com!'.
Unicode Character String Literals - Strings of Unicode characters enclosed in single quotes with a
prefix of (N). They are used for Unicode character string data types. For example: N'Welcome to
FYIcenter.com'.
Binary String Literals - Strings of bytes expressed in HEX numbers and prefixed with (0x). They
are used for binary string data types. For example: '0x69048AEFDD010E'.
Date and Time Literals - Data and time values expressed in several popular formats and
enclosed in single quotes ('). They are used for data and time data types. For example: '2007-05-
19 22:55:07.233'.
Money Literals - Strings of numbers with a single decimal point with a prefix of ($) and optional
sign (+/-). They are used for money data types. For example: $542023.14.
Character string literals are used everywhere in Transact-SQL statements. You need to learn some
important rules on writing character string literals:
Character string literals must be enclosed in single quotes as 'Welcome to FYIcenter.com!'.
An empty string must be expressed as ''.
Single quote characters inside a string must be expressed as two single quotes. For example:
'It''s Sunday!'.
Character strings use non-default character code pages must use the COLLATE clause to
provide the code page through a collate name. For example, 'Français' COLLATE French_CI_AS.
What Is a Collation?
A collation is a set of rules defining a character set and its sorting rules. SQL Server support a large
number of built-in collations. For example:
Albanian_CI_AI_KS_WS - Albanian, case-insensitive (CI), accent-insensitive (AI), kanatype-
sensitive (KS), width-sensitive (WS).
Arabic_CI_AS_KS_WS - Arabic, case-insensitive, accent-sensitive, kanatype-sensitive, width-
sensitive.
French_CI_AI - French, case-insensitive, accent-insensitive, kanatype-insensitive, width-
insensitive.
Korean_Wansung_BIN - Korean-Wansung, binary sort.
SQL_Latin1_General_CP1250_CI_AS - Latin1-General, case-insensitive, accent-sensitive,
kanatype-insensitive, width-insensitive.
If you want to get a list of all collations support on the SQL Server, run this statement:
SELECT * FROM fn_helpcollations()
GO
If you do not want to use the default collation provided by the SQL Server, you can use the
"COLLATE collation_name" clause to specify a different collation to be used at different levels:
Database Level - Used in CREATE DATABASE or ALTER DATABASE statements to set a new
default collation for the entire database.
Table Column Level - Used in CREATE TABLE or ALTER TABLE statements to override the
database default collation for this column.
Character String Expression Level - Used at the end of the expression to cast the expression to
the specified collation.
In SQL Server, different collations may use different code pages. For example:
Albanian_CI_AI_KS_WS - Albanian, Code page 1250.
Arabic_CI_AS_KS_WS - Arabic, Code page 1256.
French_CI_AI - French, Code page 1252.
Korean_Wansung_BIN - Korean-Wansung, Code page 949.
SQL_Latin1_General_CP1250_CI_AS - Latin1-General, Code page 1250.
If you are casting a string of characters from one code page to a different code page, some character
will be converted to similar. For example
PRINT 'Français: eéèê-aà-oô';
-- The default code page
Français: eéèê-aà-oô
Français: eéèê-aà-oô
Français: eéee-aa-oô
Francais: eeee-aa-oo
How find out the default Collation?
The default collation of a database comes from the server if you are not using the COLLATE clause in
the CREATE DATABASE statement. If you are not using the COLLATE clause for character string
column, it will use the default collation from the database.
Using this logic, you can find out the default collation in a database or server very easily. See the
following tutorial exercise:
CREATE DATABASE FyiCenterData
GO
CREATE TABLE faq (Name VARCHAR(80))
GO
SP_HELP FAQ
GO
Column_name ... Collation
Name ... SQL_Latin1_General_CP1_CI_AS
Now we know that the default collation for SQL Server 2005 is SQL_Latin1_General_CP1_CI_AS.
When the length of the input string does not match the storage size of the fixed length string data type
CHAR(n). SQL Server will:
If the input string of CHAR(n) has less than n bytes, it will be padded with space characters to
become n bytes.
If the input string of CHAR(n) has more than n bytes, it will be truncated to n bytes.
The tutorial exercise shows you good examples of truncating and padding fixed length character
strings:
Unicode characters are multi-byte characters. They are very hard to be entered as string literals,
because it requires:
The SQL client tool to support Unicode characters. The command line tool 'sqlcmd' does not
support Unicode. But SQL Server Management Studio does support Unicode.
A special Unicode character input tool to allow you to enter multi-byte Unicode characters.
But if you know the code value of a Unicode character, you can enter it with the help of the
NCHAR(int) function. For example:
-- A Unicode string of some interesting characters
PRINT NCHAR(9733)+NCHAR(9734)+NCHAR(9792)+NCHAR(9794);
GO
Run the sample statement with SQL Server Management Studio, you should see some Unicode
characters.
Binary string long values are normally generated by client applications by reading input channels, like
image files. But sometimes, you may need to enter some short binary strings as literals. Binary string
literals are entered as a string of bytes expressed in HEX numbers and prefixed with (0x).
Input strings will be truncated or padded to fit the storage size of fixed length binary string data type.
The padding bytes will be the zero byte: 0x00. The tutorial exercise shows you good examples of
truncating and padding fixed length binary strings:
-- Size matches
DECLARE @x BINARY(8);
SET @x = 0x2605260626402642;
PRINT @x;
GO
0x2605260626402642
-- Truncated
DECLARE @x BINARY(4);
SET @x = 0x2605260626402642;
PRINT @x;
GO
0x26052606
-- Padded
DECLARE @x BINARY(12);
SET @x = 0x2605260626402642;
PRINT @x;
GO
0x260526062640264200000000
Date and time literals are entered as character strings enclosed in single quotes ('). The string must in
one of the recognizable data and time formats. Some of the most commonly used formats are given
in the following tutorial exercise:
-- Default format for query output
DECLARE @x DATETIME;
SET @x = '2007-05-19 22:55:07.233';
SELECT @x;
GO
2007-05-19 22:55:07.233
Why I Can Not Enter 0.001 Second in Date and Time Literals?
If you enter milliseconds in data and time literals, they will be rounded up to 10/3 milliseconds
increments, because DATETIME data type uses 4 bytes to store the time of the day. A 4-byte integer
can only give an accuracy of one three-hundredth second, or 3.33 milliseconds.
So if you enter a time with 0.001 second, it will be rounded to 0.000 second. The tutorial exercise
below gives you some good examples of how milliseconds are rounded by the SQL Server.
-- No rounding
DECLARE @x DATETIME;
SET @x = '2007-05-19 22:55:07.233';
SELECT @x;
GO
2007-05-19 22:55:07.233
-- Rounded up to 0.003
DECLARE @x DATETIME;
SET @x = '2007-05-19 22:55:07.002';
SELECT @x;
GO
2007-05-19 22:55:07.003
-- Rounded up to 0.007
DECLARE @x DATETIME;
SET @x = '2007-05-19 22:55:07.006';
SELECT @x;
GO
2007-05-19 22:55:07.007
What Happens If Date-Only Values Are Provided as Date and Time Literals?
If only date value is provided in a data and time literal, the SQL Server will pad the time value with a
zero, or '00:00:00.000', representing the midnight time of the day. The tutorial exercise below gives
you some good examples:
-- 'mm/dd/yyyy' format
DECLARE @x DATETIME;
SET @x = '05/19/2007';
SELECT @x;
GO
2007-05-19 00:00:00.000
-- 'mm.dd.yy' format
DECLARE @x DATETIME;
SET @x = '05.19.07';
SELECT @x;
GO
2007-05-19 00:00:00.000
-- 'yyyy-mm-dd' format
DECLARE @x DATETIME;
SET @x = '2007-05-19';
SELECT @x;
GO
2007-05-19 00:00:00.000
-- 'dd-mon-yyyy' format
DECLARE @x DATETIME;
SET @x = '19-May-2007';
SELECT @x;
GO
2007-05-19 00:00:00.000
What Happens If Time-Only Values Are Provided as Date and Time Literals?
If only time value is provided in a data and time literal, the SQL Server will pad the date value with a
zero, representing the base date, January 1, 1900. The tutorial exercise below gives you some good
examples:
-- 'hh:mi:ss.mmm' format
DECLARE @x DATETIME;
SET @x = '22:55:07.233';
SELECT @x;
GO
1900-01-01 22:55:07.233
-- 'hh:mi:ss.mmmAM/PM' format
DECLARE @x DATETIME;
SET @x = '10:55:07.233PM';
SELECT @x;
GO
1900-01-01 22:55:07.233
-- 'hh:miAM/PM' format
DECLARE @x DATETIME;
SET @x = '10:55PM';
SELECT @x;
GO
1900-01-01 22:55:00.000
When you enter data and time literals, you may get out-of-range errors due to two common mistakes:
The date value is a valid calendar date, but it is not in the range covered by DATETIME data
type: from January 1, 1753, to December 31, 9999.
The date value is not a valid calendar date, for example: 30-Feb-2007.
The time value does not represent a valid time, for example: 24:55:07.233.
The tutorial exercise below shows you some data and time out-of-range errors:
-- Invalid date
DECLARE @x DATETIME;
SET @x = '30-Feb-2007 22:55:07.233';
GO
Msg 242, Level 16, State 3, Line 2
The conversion of a char data type to a datetime data type
resulted in an out-of-range datetime value.
-- Invalid time
DECLARE @x DATETIME;
SET @x = '19-May-2007 24:55:07.233';
GO
Msg 242, Level 16, State 3, Line 2
The conversion of a char data type to a datetime data type
resulted in an out-of-range datetime value.
If you are entering an INT data type literal with representing an integer value too big for INT data type
to store, the SQL Server will give you an arithmetic overflow error. The same error will happen on
BIGINT, INT, SMALLINT, and TINYINT data types.
Remember that INT data types uses 4 bytes to an integer value between -2^31 (-2,147,483,648) to
2^31-1 (2,147,483,647). The tutorial exercise below gives an example of arithmetic overflow errors.
-- INT value in the range
DECLARE @x INT;
SET @x = 2147483647;
SELECT @x;
GO
2147483647
How Extra Digits Are Handled with NUMERIC Data Type Literals?
Exact numeric data types defined with NUMERIC(p,s) has two limits defined by two parameters: p
(precision) and s (scale):
Maximum number of digits of the integer part (digits before the decimal point) is defined as p-s. If
this limit is passed, SQL Server will give you an arithmetic overflow error.
Maximum number of digits of the decimal part (digits after the decimal point) is defined as s. If
this limit is passed, SQL Server will perform a round operation.
The tutorial exercise below gives an example of arithmetic overflow errors and rounding operations.
-- Exact numeric value
DECLARE @x NUMERIC(9,2); -- NUMERIC(p,s)
SET @x = 1234567.12;
SELECT @x;
GO
1234567.12
By definition, FLOAT(n) should store the mantissa of the floating number in n bits. For example,
FLOAT(16) should have a precision one-byte less than FLOAT(24).
However, SQL Server 2005 only supports two precisions for floating numbers:
Single Precision: FLOAT(24) or REAL, stored in 4 bytes, giving about 7 digits of precision,
covering all types from FLOAT(1) to FLOAT(24),
Double Precision: FLOAT(53), stored in 8 bytes, giving about 15 digits of precision, covering all
types from FLOAT(25) to FLOAT(53).
The tutorial exercise below shows you some different precision and rounding examples:
-- FLOAT(1) works like FLOAT(24)
DECLARE @x FLOAT(1)
SET @x = 9.234567890E+10;
SELECT @x;
GO
9.234568E+10 -- 7 digits precision
If you enter a floating number that is too big or too small for the FLOAT data type, SQL Server 2005
will behave as:
FLOAT(24) Underflow: If a floating number is too small for FLOAT(24), it will be stored as 0
without any warning.
FLOAT(24) Overflow: If a floating number is too big for FLOAT(24), you will get an arithmetic
overflow error.
FLOAT(53) Underflow: If a floating number is too small for FLOAT(53), it will be stored as 0 with a
warning.
FLOAT(53) Overflow: If a floating number is too big for FLOAT(53), you will get a value-out-of-
range error.
The tutorial exercise below some good underflow and overflow examples:
-- Single precision underflow without warning
DECLARE @x REAL; -- FLOAT(24)
SET @x = 9.234568E-39;
SELECT @x;
GO
0
Date and time literals are entered as character strings enclosed in single quotes ('). The string must in
one of the recognizable data and time formats. Some of the most commonly used formats are given
in the following tutorial exercise:
-- Default format for query output
DECLARE @x DATETIME;
SET @x = '2007-05-19 22:55:07.233';
SELECT @x;
GO
2007-05-19 22:55:07.233
-- Default for string print output
DECLARE @x DATETIME;
SET @x = 'May 19 2007 10:55PM';
SELECT @x;
GO
2007-05-19 22:55:00.000
What Is an Expression?
A numeric expression is a combination of identifiers, values, and operators that SQL Server 2005 can
evaluate to obtain a numeric value.
An arithmetic operator performs an arithmetic operation on two expressions of numeric data types.
SQL Server supports 5 arithmetic operators:
+ (Add): Addition
- (Subtract): Subtraction
* (Multiply): Multiplication
/ (Divide): Division
% (Modulo): Modulation
There are 4 ways to convert a numeric expression from one data type to another data type:
Implicit conversion by arithmetic operations - When arithmetic operations are performed on
expressions of different data types, implicit data type conversion will be performed before the
arithmetic operation on the expression with a lower data type rank.
Implicit conversion by assignment operations - When a numeric expression is assigned to
variable, column, or parameter of different data type, the expression will be converted to match
the data type of the variable, column, or parameter.
Explicit conversion using the CAST() function - A numeric expression can be explicitly converted
to different data type using the CAST(expression AS data_type) function.
Explicit conversion using the CONVERT() function - A numeric expression can be explicitly
converted to different data type using the CONVERT(data_type, expression) function.
Some numeric data type conversion examples are provided in the tutorial exercise below:
-- Implicit conversion by an arithmetic operation
-- INT converted to NUMERIC
DECLARE @d NUMERIC(9,6);
SET @d = 1.0;
SELECT @d/3;
GO
0.33333333
Note that implicit data type conversion during assignment operation can convert a higher rank data
type to a lower rank data type, which may resulting in losing data during the conversion. The tutorial
exercise shows you some good examples:
-- INT converted to NUMERIC DECLARE @i INT; DECLARE @d NUMERIC(9,3); SET @i = 123; SET
@d = @i; SELECT @d; GO 123.000 -- INT converted to NUMERIC DECLARE @i INT; DECLARE @d
NUMERIC(9,3); SET @i = 123; SET @d = @i; SELECT @d; GO 123.000 DECLARE @pi FLOAT(24);
DECLARE @dp NUMERIC(5,2); SET @pi = 3.1415927E+00; SET @dp = @pi; SELECT @dp; GO 3.14
How To Convert Numeric Expression Data Types using the CAST() Function?
If you want to convert the data type of a numeric expression to a new data type, you can use the
CAST(expression AS data_type) function. The tutorial exercise below shows you how to use the
CAST() function:
-- FLOAT converted to NUMERIC by CAST()
DECLARE @pi FLOAT(24);
SET @pi = 3.141592E+00;
SELECT CAST(@pi AS NUMERIC(5,2));
GO
3.14
How To Convert Numeric Expression Data Types using the CONVERT() Function?
If you want to convert the data type of a numeric expression to a new data type, you can use the
CONVERT(data_type, expression) function. The tutorial exercise below shows you how to use the
CONVERT() function:
-- FLOAT converted to NUMERIC by CONVERT()
DECLARE @pi FLOAT(24);
SET @pi = 3.141592E+00;
SELECT CONVERT(NUMERIC(5,2), @pi);
GO
3.14
Sometimes you need to convert numeric values enclosed in character strings back to numeric values
by using the CONVERT() function.
When converting character strings to values with CONVERT(), you need to remember two rules:
Leading and trailing space characters are ignored.
The input string must represent a numeric literal that matches the target numeric data type.
If the input string does not represent a numeric literal that matches the target numeric data type,
you will get a conversion error.
The tutorial exercise below shows you how to use the CONVERT() function to convert strings to
values:
SELECT CONVERT(NUMERIC(10,5), ' 12345.12 ');
GO
12345.12000
If you are converting a numeric expression to an integer data type and the value is too big for integer
storage size, you will get an arithmetic overflow error as shown in the following examples:
-- Overflow error on implicit conversion
DECLARE @x FLOAT(24);
DECLARE @y TINYINT;
SET @x = 12345.12E+00;
SET @y = @x;
GO
Msg 232, Level 16, State 1, Line 4
Arithmetic overflow error for type tinyint,
value = 12345.120117.
If you are converting a numeric expression to a NUMERIC data type and the value is too big for the
storage size, you will get an arithmetic overflow error as shown in the following examples:
-- Overflow error on implicit conversion
DECLARE @x FLOAT(24);
DECLARE @y NUMERIC(5,2);
SET @x = 12345.12E+00;
SET @y = @x;
GO
Msg 8115, Level 16, State 6, Line 4
Arithmetic overflow error converting real to data type
numeric.
SQL Server 2005 supports 23 mathematical functions: ABS, ACOS, ASIN, ATAN, ATN2, CEILING,
COS, COT, DEGREES, EXP, FLOOR, LOG, LOG10, PI, POWER, RADIANS, RAND, ROUND, SIGN,
SIN, SQRT, SQUARE, and TAN.
The return data types of mathematical functions are determined by two rules:
Arithmetical functions: ABS, CEILING, DEGREES, FLOOR, POWER, RADIANS, and SIGN are
returning the same data type as the input values. No implicit data type conversions are
performed.
Other mathematical functions: COS, COT, EXP, LOG, LOG10, SIN, SQRT, SQUARE and TAN
are taking only FLOAT data type as input and returning FLOAT data type. Implicit data type
conversion will be performed if you are calling these functions with a non-FLOAT data type.
The tutorial exercise gives you some good examples on how to use mathematical functions:
-- ABS retuns the same data type as the input
DECLARE @x FLOAT(53);
DECLARE @y NUMERIC(9,2);
DECLARE @z INT;
SET @x = -12345.123456789E+20;
SET @y = -12345.12;
SET @z = -12345
SELECT ABS(@x);
SELECT ABS(@y);
SELECT ABS(@z);
GO
1.2345123456789E+24
12345.12
12345
Sometimes you need to round a numeric value into an integer. SQL Server 2005 offers you a number
of ways to do this:
FLOOR(value) - Returning the largest integer less than or equal to the input value. The returning
data type is the same as the input value.
CEILLING(value) - Returning the smallest integer greater than or equal to the input value. The
returning data type is the same as the input value.
ROUND(value, 0, 0) - Returning the integer most close to the input value. The returning data type
is the same as the input value.
CAST(value AS INT) - Returning the largest integer less than or equal to the input value. The
returning data type is INT.
CONVERT(INT, value) - Returning the largest integer less than or equal to the input value. The
returning data type is INT.
The tutorial exercise below gives some good examples of converting numeric values to
integers:
SELECT FLOOR(1234.5678);
SELECT CEILING(1234.5678);
SELECT ROUND(1234.5678, 0, 0);
SELECT CAST(1234.5678 AS INT);
SELECT CONVERT(INT, 1234.5678);
GO
1234
1235
1235.0000
1234
1234
Sometimes you need to round a numeric value to a specific precision. For example, you may want to
round values in your financial statement to the precision of 1000.00. This can be done by the
ROUND() function with the following syntax:
ROUND(value, precision, type)
The tutorial exercise below gives some good examples of how to use the ROUND() function:
SELECT ROUND(1234.5678, 0, 0);
SELECT ROUND(1234.5678, -3, 0);
SELECT ROUND(1234.5678, -4, 0);
SELECT ROUND(1234.5678, 3, 0);
SELECT ROUND(1234.5678, 3, 1);
GO
1235.0000
1000.0000
0.0000
1234.5680
1234.5670
Random numbers are very useful for generating test data, passwords, or other security related data.
SQL Server 2005 offers you the random number generator function RAND in two format:
RAND(seed) - Starting a new sequence of random numbers based on the given integer "seed"
and returning the first random number in FLOAT(53) from the sequence.
RAND() - Returning the next random number in FLOAT(53) from the current sequence. If there
has been no current sequence, SQL Server will start a new sequence with a random "seed".
Note that calling RAND(seed) with the same seed will start the same sequence and return the same
number. To avoid this repeating pattern, you should always call RAND() without any seed and let the
server to randomly pickup a sequence.
The tutorial exercise below shows some good examples on how to generate random numbers:
SELECT RAND(100), RAND(), RAND(); -- new sequence
SELECT RAND(100), RAND(), RAND(); -- same sequence again
SELECT RAND(), RAND(), RAND();
SELECT RAND(), RAND(), RAND();
GO
0.715436657367485 0.28463380767982 0.0131039082850364
0.715436657367485 0.28463380767982 0.0131039082850364
0.28769876521071 0.100505471175005 0.292787286982702
0.868829058415689 0.370366365964781 0.58334760467751
If a Unicode string NVARCHAR is concatenated with a non-Unicode string VARCHAR, SQL Server
will implicitly convert the non-Unicode string to Unicode string for concatenation.
DECLARE @regcode VARCHAR(40);
DECLARE @unicode NVARCHAR(40);
SET @regcode = 'Some Unicode characters: '
SET @unicode = NCHAR(9733)+NCHAR(9734)+NCHAR(9792)
+NCHAR(9794);
SELECT @regcode + @unicode;
SELECT DATALENGTH(@regcode);
SELECT DATALENGTH(@unicode);
SELECT DATALENGTH(@regcode + @unicode);
Some Unicode characters: ????
25
8
58
Note that the non-Unicode string @regcode has been converted to a Unicode string. The number of
bytes of @regcode changed from 25 to 50. With 8 bytes from @unicode, the number of bytes of the
concatenated string becomes 58.
How To Convert a Unicode Strings to Non-Unicode Strings?
Since Unicode character set is different than code page based (non-Unicode) character set,
converting Unicode strings to non-Unicode strings may result in wrong characters or missing
characters. So you should avoid converting Unicode strings to non-Unicode strings.
If you really want to, there are 3 ways to convert a Unicode string to a non-Unicode string:
Implicit conversion by assignment operations - When a Unicode string is assigned to a variable, a
column, or a parameter of a non-Unicode string data type, SQL Server will implicitly convert the
Unicode string to a non-Unicode string.
Explicit conversion using the CAST() function - A Unicode string can be explicitly converted to
non-Unicode string using the CAST(Unicode_string AS VARCHAR(size)) function.
Explicit conversion using the CONVERT() function - A Unicode string can be explicitly converted
to non-Unicode string using the CONVERT(VARCHAR(size), Unicdoe_string) function.
Some numeric data type conversion examples are provided in the tutorial exercise below:
-- Implicit conversion by an assignment operation
DECLARE @regcode VARCHAR(40);
SET @regcode = N'Some Unicode characters: '
+ NCHAR(9733)+NCHAR(9734)+NCHAR(9792)+NCHAR(9794);
SELECT @regcode;
GO
Some Unicode characters: ????
What Are the Character String Functions Supported by SQL Server 2005?
If you want to break a string into multiple lines, you need to insert new line characters into the string.
With some client tools like SQL Server Management Studio, it is not so easy to insert a new line
character.
One work around is to use the CHAR(int) function to generated new line character and other special
characters with their code values:
CHAR(9) - Generates the tab character.
CHAR(10) - Generates the line feed (new line) character.
CHAR(13) - Generates the carriage return character.
How To Locate and Take Substrings with CHARINDEX() and SUBSTRING() Functions?
Transact-SQL is not a language designed for manipulating strings, but it does have two simple
functions to locate and take substrings: CHARINDEX() and SUBSTRING().
The tutorial exercise below assumes two given strings: 'Pages: 18' and 'Words: 3240'. The objective
is to calculate the number of words per page. Read the script below to see how this is done by using
CHARINDEX() and SUBSTRING() functions:
DECLARE @sPages VARCHAR(40), @sWords VARCHAR(40);
SET @sPages = 'Pages: 18';
SET @sWords = 'Words: 3240';
SET @sPages = SUBSTRING(@sPages, CHARINDEX(':', @sPages)+1, 20);
SET @sWords = SUBSTRING(@sWords, CHARINDEX(':', @sWords)+1, 20);
PRINT 'Number of words per page: '
+ CONVERT(VARCHAR(20), CONVERT(INT, @sWords)/CONVERT(INT, @sPages));
GO
Number of words per page: 180
If you are a PHP developer, you can get this done in a much quick way
SQL Server 2005 allows to concatenate two binary strings into a single string with the (+) operator.
The following tutorial exercise shows you some binary string concatenation examples:
-- Concatenating two binary string literals
SELECT 0x57656C636F6D6520746F20
+ 0x46594963656E7465722E636F6D;
GO
0x57656C636F6D6520746F2046594963656E7465722E636F6D
Can binary strings be used in arithmetical operations? The answer is yes. But there are two simple
rules you need to remember:
If an arithmetical operation has one binary string operand and one integer data type operand, the
binary string operand will be converted to a integer data type to match the other operand. The
operation will be performed as an integer operation.
A + operator with two binary strings will be performed as binary string concatenation.
A -, *, or / operator with two binary strings will be performed as binary string concatenation.
SELECT 0x66 - 44
GO
58
SELECT 0x66 * 44
GO
4488
SELECT 0x66 / 44
GO
2
Binary strings and integers are convertible implicitly and explicitly. But there several rules you need to
remember:
Binary strings will be implicitly converted into an integer data type, if it is involved in an
arithmetical operation with another integer data type operand.
Binary strings will be implicitly converted into an integer data type, if it is assigned to a variable, a
column or a parameter of an integer data type.
Binary strings will be explicitly converted into integer data types using CAST() and CONVERT()
functions.
When converting binary strings that have more bytes than the target data type size, bytes on the
left hand side will be truncated.
When converting binary strings that have less bytes than the target data type size, 0x00 will be
padded on the left hand side.
Examples showing in the tutorial exercise below will help you remembering those rules.
SELECT 0x66 + 44
GO
146
Can binary strings be converted into numeric or float data types? The answer is no. Binary strings
can not be converted implicitly or explicitly into NUMERIC, DECIMAL, REAL, or FLOAT data types.
The tutorial exercise gives you some examples of errors when converting binary strings to NUMERIC
or FLOAT data types:
-- Implicit conversion to NUMERIC
SELECT 0x66 + 0.44;
GO
Msg 8114, Level 16, State 5, Line 1
Error converting data type varbinary to numeric.
Binary strings and character strings are convertible. But there are several rules you need to
remember:
Binary strings can be converted implicitly to character strings by assignment operations.
Binary strings can not be converted implicitly to character strings by concatenation operations.
Binary strings can be converted explicitly to character strings by CAST() and CONVERT()
functions.
Character strings can not be converted implicitly to binary strings by assignment operations.
Character strings can not be converted implicitly to binary strings by concatenation operations.
Character strings can be converted explicitly to binary strings by CAST() and CONVERT()
functions.
Can binary strings be converted into Unicode character strings? The answer is yes. But you need to
know how Unicode characters are represented in a binary format. Remember the following simple
rules:
An ASCII character is stored in 1 byte.
A Unicode character is stored in 2 bytes.
When an ASCII character is mapped to a Unicode character, the first type equals to the same
code value as the ASCII character, and the second type equals to 0x00.
The tutorial exercise below shows you some interesting conversion behaviors:
-- 1. Binary representation of ASCII characters
SELECT CONVERT(VARBINARY(40),'FYIcenter.com');
GO
0x46594963656E7465722E636F6D
Test 4 seems to be giving a wrong result. It should be something like "F Y I c e n t e r . c o m ". But
the client tool does not know how to display the 0x00 ASCII character and stops showing the rest of
the characters.
Result of test 5 shows real characters on the SQL Server Management Studio windows. But they can
not be represented on this Web page, because it is not set to handle Unicode characters. This is why
you see (?) characters.
Converting binary strings into hexadecimal character strings in storage is not an easy task, since
there is not built-in functions to help you. You need to write a conversion algorithm yourself. This
tutorial exercise, called bin2hex, shows you a simple example:
-- bin2hex
DECLARE @binary_string VARBINARY(40);
DECLARE @hex_string VARCHAR(40);
DECLARE @position INT; -- Loop index
DECLARE @char INT; -- Character code value
DECLARE @half_char INT; -- Character code half value
-- Initial values
SET @binary_string = CONVERT(VARBINARY(40),'FYIcenter.com');
SET @hex_string = ''; -- Output hex strings
SET @position = 1;
Bitwise operations are binary operations performed on one or two binary strings. SQL Server
supports 4 bitwise operations:
& (Bitwise AND) - Performing the single bit Boolean operation "AND" on each bit position.
| (Bitwise OR) - Performing the single bit Boolean operation "OR" on each bit position.
^ (Bitwise XOR) - Performing the single bit Boolean operation "XOR" on each bit position.
~ (Bitwise NOT) - Performing the single bit Boolean operation "NOT" on each bit position.
The table below shows you how single bit Boolean operations work:
Input 1: 0 0 1 1
Input 2: 0 1 0 1
----------------
& (AND) 0 0 0 1
Input 1: 0 0 1 1
Input 2: 0 1 0 1
----------------
| (OR) 0 1 1 1
Input 1: 0 0 1 1
Input 2: 0 1 0 1
----------------
^ (XOR) 0 1 1 0
Input 1: 0 0 1 1
----------------
~ (NOT) 1 1 0 0
SQL Server 2005 only support two operators on data and time values:
+ (Add): Adding days to a date and time value.
- (Subtract): Removing days from a date and time value.
Note that to add or subtract days on a date and time value, the other operand must be a numeric
value: an integer or a decimal number.
Here are some good examples of adding days to and subtracting days from date and time values:
-- Leap year is supported
DECLARE @birth_date DATETIME;
SET @birth_date = '29-Feb-2000 03:00:00.000';
SELECT @birth_date + 1;
SELECT @birth_date - 1;
GO
2000-03-01 03:00:00.000
2000-02-28 03:00:00.000
Can date and time values be converted into integers? The answer is yes. The resulting integer will be
the number days relative the base date: Jan 1, 1900. The time of the day will be rounded to days. But
there several rules you need to follow:
Date and time values can not be converted to integers implicitly using assignment operations.
Date and time values can be converted to integers explicitly using CAST() or CONVERT()
functions.
Can integers be converted into date and time values? The answer is yes. The input integer will be
used as the number of days relative to the base date: Jan 1, 1900. The time of the day will be set to
0, midnight of the day. But there several rules you need to follow:
Integers can be converted to date and time values implicitly using assignment operations.
Integers can be converted to date and time values explicitly using CAST() or CONVERT()
functions.
Are datetime and numeric value convertible? The answer is yes. Here are the main rules on
DATATIME and NUMERIC value conversions:
During the conversion a DATETIME value will be treated as a NUMERIC value with the number
of days relative the base date, Jan 1, 1900 being the integer part, and the time of the day being
the decimal part.
DATETIME values can not be converted to NUMERIC values implicitly using assignment
operations.
NUMERIC values can be converted to DATETIME values implicitly using assignment operations.
DATETIME values and DATETIME values can be converted to each other explicitly using CAST()
or CONVERT() functions.
Can a datetime value be subtracted from another datetime value? The answer is yes. The subtract
operation can be performed by the subtract operator (-) as:
datetime1 - datetime2: Returning a DATETIME value calculated as CONVERT(DATETIME,
CONVERT(NUMERIC(18,9),datetime1) - CONVERT(NUMERIC(18,9),datetime2)).
What Are the Date and Time Functions Supported by SQL Server 2005?
On many Web sites, news items or blog articles are displayed with a publishing data and time
represented in days, hours and minutes. To do this you can use the DATEDIFF() function with a
simple algorithm as shown in the tutorial exercise below:
-- Age in days
DECLARE @submit_date DATETIME;
SET @submit_date = '2007-05-11 16:10:41.403';
SELECT 'Posted '
+ CONVERT(VARCHAR(40),
DATEDIFF(day, @submit_date, GETDATE()))
+ ' days ago.';
GO
Posted 8 days ago.
Notice how the correct number of days, hours, and minutes are calculated using the concepts of
whole day, remaining partial day, whole hour, and remaining partial hour as shown below:
|...................|...................|...+...+..
Comparison operations return Boolean values by comparing the relative positions of two operands.
SQL server supports the following comparison operations:
= (Equal To): Returns Boolean true, if two operands are equal in value.
> (Greater Than): Returns Boolean true, if the left operand has a value greater than the right
operand.
< (Less Than): Returns Boolean true, if the left operand has a value less than the right operand.
>= (Greater Than or Equal To): Returns Boolean true, if the left operand has a value greater than
or equal to the right operand.
<= (Less Than or Equal To): Returns Boolean true, if the left operand has a value less than or
equal to the right operand.
<> (Not Equal To): Returns Boolean true, if two operands are not equal in value.
There are several rules you need to remember about comparison operations:
Comparison operations can be performed on all data types: exact numbers, approximate
numbers, character strings, and binary strings.
If two operands have different data types, the operand with a lower data type rank will be
implicitly converted to the data type of the other operand.
Character string comparison will be performed based the rules defined in the associated collation.
How To Perform Comparison on Exact Numbers?
Comparison operations on exact numbers of data types: BIT, INT, NUMERIC, etc., are very easy
to understand. Here are some simple examples:
-- BIT value comparison
DECLARE @x BIT, @y BIT;
SET @x = 0;
SET @y = 1;
SELECT CASE WHEN @x > @y THEN 'True' ELSE 'False' END;
GO
False
DECLARE @x INT, @y INT;
SET @x = -5;
SET @y = 9;
SELECT CASE WHEN @x > @y THEN 'True' ELSE 'False' END;
GO
False
DECLARE @x NUMERIC(9,2), @y NUMERIC(9,2);
SET @x = -5.25;
SET @y = -5.15;
SELECT CASE WHEN @x > @y THEN 'True' ELSE 'False' END;
GO
False
How To Perform Comparison on Floating Point Numbers?
Comparison operations on approximate (floating point) numbers are also easy to understand.
Just watch out rounding operations performed during conversions. Here are two examples of
floating point number comparisons:
-- Rounding during implicit conversion makes them equal
DECLARE @x FLOAT(24), @y FLOAT(24);
SET @x = 0.999999999E+00;
SET @y = 0.99999999E+00;
SELECT CASE WHEN @x <> @y THEN 'True' ELSE 'False' END;
GO
False
-- Floating point number literals have double precision
-- So no rounding
SELECT CASE WHEN 0.999999999E+00 <> 0.99999999E+00 THEN
'True'
ELSE
'False'
END;
GO
True
How To Perform Comparison on Date and Time Values?
Comparison operations on date and time values can be performed in the same way as numeric
values. The comparison rule is simple: a date and time value in the future has a greater value
than a date and time value in the past. The tutorial exercise below shows you a good example:
-- Future date has a greater value
DECLARE @his_birth_date DATETIME, @her_birth_date DATETIME;
SET @his_birth_date = '1987-05-19';
SET @her_birth_date = '1988-07-07';
SELECT CASE WHEN @his_birth_date < @her_birth_date THEN
'He is older.'
ELSE
'She is older.'
END;
GO
He is older.
How To Perform Comparison on Character Strings?
Comparison operations on character strings are performed based on the associated collation.
Each collation defines rules on how characters are ordered, how character cases and accents are
treated, etc. The tutorial exercise below shows you some character string comparison examples
using the default collation: SQL_Latin1_General_CP1_CI_AS.
-- Case insensitive
DECLARE @x VARCHAR(40), @y VARCHAR(40);
SET @x = 'FYIcenter.com';
SET @y = 'fyicenter.COM';
SELECT CASE WHEN @x = @y THEN 'True' ELSE 'False' END;
GO
True
-- digits has less values than letters
DECLARE @x VARCHAR(40), @y VARCHAR(40);
SET @x = '1234';
SET @y = 'abcd';
SELECT CASE WHEN @x < @y THEN 'True' ELSE 'False' END;
GO
True
-- Trailing spaces are ignored
DECLARE @x VARCHAR(40), @y VARCHAR(40);
SET @x = 'FYIcenter.com';
SET @y = 'fyicenter.COM ';
SELECT CASE WHEN @x = @y THEN 'True' ELSE 'False' END;
GO
True
-- Longer strings have greater values
DECLARE @x VARCHAR(40), @y VARCHAR(40);
SET @x = 'abcd';
SET @y = 'abcde';
SELECT CASE WHEN @x < @y THEN 'True' ELSE 'False' END;
GO
True
What To Test Value Ranges with the BETWEEN Operator?
Sometimes you want to compare a value against a value range. You can do this with two regular
comparison operations. But you can also use the special comparison operator BETWEEN to get
it done with the following syntaxes:
1. Inclusively in the range test
test_value BETWEEN range_start_value AND range_end_value
- Returns the same results as the following expression
test_value >= range_start_value
AND test_value <= range_end_value
2. Exclusively out of the range test
test_value NOT BETWEEN range_start_value AND range_end_value
- Returns the same results as the following expression
test_value < range_start_value
OR test_value > range_end_value
Here are two examples of using the BETWEEN operator:
DECLARE @my_age INT;
SET @my_age = 17;
SELECT CASE WHEN
@my_age BETWEEN 11 AND 19
THEN 'You are a teenager.'
ELSE 'You are not a teenager.'
END;
GO
You are a teenager.
DECLARE @my_age INT;
SET @my_age = 27;
SELECT CASE WHEN
@my_age NOT BETWEEN 11 AND 19
THEN 'You are not a teenager.'
ELSE 'You are a teenager.'
END;
GO
You are not a teenager.
What To Test Value Lists with the IN Operator?
Sometimes you want to test a given value against a list of values. You can do this in a loop with
the regular "equal" operator. But you can also use the special comparison operator IN to get it
done with the following syntaxes:
1. In-the-list test
test_value IN (value_1, value_2, ..., value_n)
- Returns the same results as the following expression
test_value = value_1
OR test_value = value_2
...
OR test_value = value_n
2. Not-in-the-list test
test_value NOT IN (value_1, value_2, ..., value_n)
- Returns the same results as the following expression
test_value <> value_1
AND test_value <> value_2
...
AND test_value <> value_n
Here are two examples of using the IN operator:
DECLARE @my_number INT;
SET @my_number = 767;
SELECT CASE WHEN
@my_number IN (525, 272, 532, 767, 150, 637)
THEN 'You are a winner.'
ELSE 'You are not a winner.'
END;
GO
You are a winner.
DECLARE @my_number INT;
SET @my_number = 676;
SELECT CASE WHEN
@my_number NOT IN (525, 272, 532, 767, 150, 637)
THEN 'You are not a winner.'
ELSE 'You are a winner.'
END;
GO
You are not a winner.
Pattern match is a very important operation for search records base on character string columns.
SQL Server 2005 offers the LIKE operator to perform pattern match operations in two formats:
target_string LIKE pattern
-- Returns TRUE
if the target string matches the pattern
Pattern match is a powerful operation. But you need to remember several rules:
Pattern may contain predefined wildcard characters, similar to Unix Regular Expressions. But
they are not the same.
'%' is a wildcard character that matches any string of zero or more characters.
'_' is a wildcard character that matches any single character.
'_' is a wildcard character that matches any single character.
'[abc]' is a wildcard character that matches any character listed inside the brackets.
'[a-c]' is a wildcard character that matches any character in the range defined in the brackets.
'[^abc]' is a wildcard character that matches any character not listed inside the brackets.
'[^a-c]' is a wildcard character that matches any character not in the range defined in the brackets.
Here is a simple example of LIKE operator:
SELECT CASE WHEN
'FYIcenter.com' LIKE 'FYI%'
THEN 'Pattern matched.'
ELSE 'Pattern not matched.'
END;
GO
Pattern matched.
Wildcard character '%' can be used in the pattern string for the LIKE operator to match any string of
zero or more characters. The following example uses '%Sport% Store' to search all company names
that has a partial word 'Sport' and ended with the word 'Store'. The sample database
AdventureWorksLT provided by Microsoft is used.
USE adventureWorksLT
GO
Wildcard character '%' can be used in the pattern string for the LIKE operator to match any string of
zero or more characters. The following example uses '%Sport% Store' to search all company names
that has a partial word 'Sport' and ended with the word 'Store'. The sample database
AdventureWorksLT provided by Microsoft is used.
USE adventureWorksLT
GO
Normally, the comparison operator IN is used against a list of specifie values as in the format of:
"test_value IN (value_1, value_2, ..., value_n)". But you can also replace the list of values by a
subquery as the following formats:
test_value IN (SELECT column FROM ...)
-- Returns TRUE if the test_value equals to one of
the values returned from the subquery
The following tutorial exercise shows you two examples of IN operators. The sample database
AdventureWorksLT provided by Microsoft is used.
USE adventureWorksLT
GO
Logical (Boolean) operations are performed on Boolean values with logical operators like 'AND', 'OR',
or 'NOT'. Logical operations return Boolean values. SQL Server 2005 supports the following logical
operations:
AND - Returns TRUE if both operands are TRUE.
OR - Returns TRUE if one of the operands is TRUE.
NOT - Returns TRUE if the only operand is FALSE.
Logical operations are commonly used to combine Boolean values resulted from comparison
operations. The following tutorial exercise shows you a good example:
DECLARE @income MONEY;
DECLARE @marriage_status VARCHAR(10);
SET @income = 55000.00;
SET @marriage_status = 'Single';
SELECT CASE WHEN
(@marriage_status = 'Married' AND @income < 65000)
OR (@marriage_status = 'Single' AND @income < 35000)
THEN 'Qualified for the benefit.'
ELSE 'Not qualified for the benefit.'
END;
GO
Not qualified for the benefit.
How To Use "IF ... ELSE IF ... ELSE ..." Statement Structures?
"IF ... ELSE IF ... ELSE ..." statement structure is used to select one of the specified statements to be
executed based on pecified Boolean conditions. Here is the syntax of "IF ... ELSE IF ... ELSE ..."
statement structure:
IF condition_1 statement_1;
ELSE IF condition_2 statement_2;
...
ELSE IF condition_n statement_n;
ELSE statement_o;
-- Executes statement_x is
if condition_x results in Boolean TRUE
The tutorial exercise below shows you how to use an IF ... ELSE statement structure to selectively
execute one of the CREATE TABLE statements:
USE FyiCenterData
GO
"BEGIN ... END" statement structure is used to group multiple statements into a single statement
block, which can be used in other statement structures as a single statement. For example, a
statement block can be used in an "IF ... ELSE ..." statement structure as a single statement.
The tutorial exercise below shows you how to use "BEGIN ... END" statement structures to place
multiple statements into an "IF ... ELSE" statement structure:
DECLARE @site_name VARCHAR(40);
SET @site_name = 'SQA';
IF @site_name = 'DBA'
BEGIN
PRINT 'Dropping table: dba_links';
DROP TABLE dba_links;
END
ELSE IF @site_name = 'SQA'
BEGIN
PRINT 'Dropping table: sqa_links';
DROP TABLE sqa_links;
END
ELSE
PRINT 'Unknown site name: '+@site_name;
GO
Dropping table: sqa_links
WHILE statement structure is used to create a loop to execute a statement or a statement block
repeatedly under a specific condition. WHILE statement structure has the following syntax formats:
1. Loop with a single statement
WHILE condition repeating_statement
The tutorial exercise below shows you how to use a WHILE statement structure to execute a
statement block repeatedly:
-- Counting number of days in 2000
DECLARE @date DATETIME;
DECLARE @count INT;
SET @date = '2000-01-01';
SET @count = 0;
WHILE DATEPART(YEAR, @date) = 2000 BEGIN
SET @count = @count + 1;
SET @date = DATEADD(DAY, 1, @date);
END
SELECT @count;
366
-- 2000 is a leap year!
If you want to stop a WHILE loop early, you can use the BREAK statement in the loop statement
block.
The tutorial exercise below shows you how to use a BREAK statement to stop a WHILE loop early:
-- Counting number of days in 2000
DECLARE @date DATETIME;
DECLARE @count INT;
SET @date = '2000-01-01';
SET @count = 0;
WHILE 1=1 BEGIN
IF DATEPART(YEAR, @date) > 2000 BREAK;
SET @count = @count + 1;
SET @date = DATEADD(DAY, 1, @date);
END
SELECT @count;
366
-- 2000 is a leap year!
If you want to skip the remaining statements in a loop block, you can use the CONTINUE statement.
The tutorial exercise below shows you how to use a CONTINUE statement to skip the remaining
statements and continue the next iteration:
-- Printing first 7 Sundays in 2000
DECLARE @date DATETIME;
DECLARE @count INT;
SET @date = '1999-12-31';
SET @count = 0;
WHILE DATEPART(YEAR, @date) < 2001 BEGIN
SET @date = DATEADD(DAY, 1, @date);
IF @count = 7 BREAK;
IF DATENAME(WEEKDAY, @date) <> 'Sunday' CONTINUE;
PRINT CONVERT(VARCHAR(40),@date,107);
SET @count = @count + 1;
END
GO
Jan 02, 2000
Jan 09, 2000
Jan 16, 2000
Jan 23, 2000
Jan 30, 2000
Feb 06, 2000
Feb 13, 2000
In order to help you to learn SQL Server, Microsoft provides several free sample scripts and sample
databases.
SqlServerSamples.msi - 25,469 KB: Sample scripts.
AdventureWorksDB.msi - 28,053 KB: Sample OLTP database: AdventureWorks, case-sensitive
collation version.
AdventureWorksDBCI.msi - 29,177 KB: Sample OLTP database: AdventureWorks, case-
insensitive collation version.
AdventureWorksBI.msi - 7,393 KB: Sample data warehouse database: AdventureWorks, case-
sensitive collation version.
AdventureWorksBICI.msi - 16,764 KB: Sample data warehouse database: AdventureWorks,
case-insensitive collation version.
AdventureWorksLT.msi - 2,251 KB: The scaled-down sample database AdventureWorks for
beginners.
If you want to learn from sample scripts provided by Microsoft, you should follow this tutorial to
download and install them:
1. Go to the SQL Server 2005 Samples and Sample Databases download page.
2. Go to the x86 section in the Instructions section, Click "SqlServerSamples.msi -- 25,469 KB" to
download the sample file. Save the download file to c:\temp.
3. Double click on the downloaded file: c:\temp\SqlServerSamples.msi. The installation setup
window shows up. Follow the instructions to finish the installation.
When the installation is done, all sample scripts will be installed in the C:\Program Files\Microsoft
SQL Server\90\Samples directory:
.\Analysis Services
.\Engine
.\Integrated Samples
.\Integration Services
.\Notification Services
.\Replication
.\Reporting Services
How to download and install the scaled-down database AdventureWorksLT?
If you want to practice you DBA skills with the scaled-down version of the sample database
AdventureWorksLT provided by Microsoft, you should follow this tutorial to download and install it
first:
1. Go to the SQL Server 2005 Samples and Sample Databases download page.
2. Go to the x86 section in the Instructions section, Click "AdventureWorksLT.msi -- 2,251 KB" to
download the sample file. Save the download file to c:\temp.
3. Double click on the downloaded file: c:\temp\AdventureWorksLT.msi. The installation setup
window shows up. Follow the instructions to finish the installation.
When the installation is done, two physical database files are installed in the data directory:
C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data:
AdventureWorksLT_Data.mdf 5,120 KB
AdventureWorksLT_Log.ldf 2,048 KB
How to attach AdventureWorksLT physical files to the server?
After installed the sample database AdventureWorksLT, you need to attach it to your SQL server
to make it available by follow this tutorial:
EXEC sp_attach_db @dbname=N'AdventureWorksLT',
@filename1=N'C:\Program Files\Microsoft SQL Server'
+'\MSSQL.1\MSSQL\Data\AdventureWorks_Data.mdf',
@filename2=N'C:\Program Files\Microsoft SQL Server'
+'\MSSQL.1\MSSQL\Data\AdventureWorks_Log.ldf'
GO
USE AdventureWorksLT
GO
SELECT TOP 10 CustomerID, FirstName, LastName, Phone
FROM SalesLT.Customer
GO
CustomerID FirstName LastName Phone
1 Orlando Gee 245-555-0173
2 Keith Harris 170-555-0127
3 Donna Carreras 279-555-0130
4 Janet Gates 710-555-0173
5 Lucy Harrington 828-555-0186
6 Rosmarie Carroll 244-555-0112
7 Dominic Gash 192-555-0173
10 Kathleen Garza 150-555-0127
11 Katherine Harding 926-555-0159
12 Johnny Caprio 112-555-0191
Looks like the sample database AdventureWorksLT is ready for you play
.
How to add an address record into AdventureWorksLT?
To find out if we can add data into AdventureWorksLT or not, you can try to add an address
record into the "SalesLT.Address" in AdventureWorksLT:
USE AdventureWorksLT
GO
INSERT SalesLT.Address (AddressLine1, City, StateProvince,
CountryRegion, PostalCode)
VALUES('1 Main Street', 'Java', 'Oracle',
'FYI', 'Center')
GO
SELECT * FROM SalesLT.Address
WHERE CountryRegion = 'FYI'
GO
AddressID/AddressLin1/AddressLine2/City/StateProvince
/CountryRegion/PostalCode/rowguid
/ModifiedDate
11384/1 Main Street/NULL/Java/Oracle
/FYI/Center/6073DFAE-9803-4B4F-B60E-D9742C0EED1D
/2007-05-19 19:24:44.140
What Are Indexes?
An index is a secondary database object associated with a table to improve the retrieval
performance of rows from that table.
An index can be defined for a single column or multiple columns of a given table. If an index is
defined on a single column of a table, the index can be viewed as ordered map between all
values in that column and their row locations in the table. For examples, if you have table with a
column called "company_num" and you created an index for that column. The contents of the
table and the index may look like what is presented in the following picture:
As shown in the above picture, locating the rows of company_num = 17 can be done much faster
through the index.
How To Create an Index on an Existing Table?
If you want to an index on an existing table, you can use the CREATE INDEX statement in a
simple syntax:
CREATE INDEX index_name ON table_name (column_name)
The tutorial exercise below shows you how to add an index for the "in" column of the "fyi_links"
table:
USE FyiCenterData;
GO
-- Drop the old table, if needed
DROP TABLE fyi_links;
GO
-- Create a fresh new table
CREATE TABLE fyi_links (
id INT NOT NULL,
url VARCHAR(80) NOT NULL,
notes VARCHAR(1024),
counts INT,
created DATETIME NOT NULL DEFAULT(getdate())
);
GO
-- Create an index for "id"
CREATE INDEX fyi_links_id ON fyi_links (id);
GO
-- Create an index for "url"
CREATE INDEX fyi_links_url ON fyi_links (url);
GO
How To View Existing Indexes on an Given Table using SP_HELP?
If you want to know how many indexes have been defined for a given table, you can use the
SP_HELP built-in stored procedure in the following syntax:
EXEC SP_HELP table_name
-- Returns all database objects related the given table
The tutorial exercise shows you how many indexes were defined from the previous tutorial on
table "fyi_links":
EXEC SP_HELP fyi_links;
GO
...
index_name index_description index_keys
------------ ------------------------------- ----------
fyi_links_id nonclustered located on PRIMARY id
fyi_links_url nonclustered located on PRIMARY url
...
How To View Existing Indexes on an Given Table using sys.indexes?
Another way to view existing indexes defined for a given table is to use the system view called
"sys.indexes". The tutorial exercise shows you how many indexes were defined from the previous
tutorial on table "fyi_links":
USE FyiCenterData;
GO
SELECT * FROM sys.indexes WHERE object_id = (
SELECT object_id FROM sys.tables WHERE name = 'fyi_links'
);
GO
object_id name index_id type_desc is_unique
--------- ------------- -------- ---------- ---------
421576540 NULL 0 HEAP 0
421576540 fyi_links_id 2 NONCLUSTERED 0
421576540 fyi_links_url 3 NONCLUSTERED 0
The extra line in the query result is not a real index at this moment. It will be explained in another
tutorial.
How To Drop Existing Indexes?
For some reason, if you want remove an existing index, you can use the DROP INDEX statement
with following syntax:
CREATE INDEX table_name.index_name
The tutorial exercise below shows you how to remove the index "fyi_links_id":
USE FyiCenterData;
GO
SELECT * FROM sys.indexes WHERE object_id = (
SELECT object_id FROM sys.tables WHERE name = 'fyi_links'
);
GO
object_id name index_id type_desc is_unique
--------- ------------- -------- ---------- ---------
421576540 NULL 0 HEAP 0
421576540 fyi_links_id 2 NONCLUSTERED 0
421576540 fyi_links_url 3 NONCLUSTERED 0
DROP INDEX fyi_links.fyi_links_id;
GO
SELECT * FROM sys.indexes WHERE object_id = (
SELECT object_id FROM sys.tables WHERE name = 'fyi_links'
);
GO
object_id name index_id type_desc is_unique
--------- ------------- -------- ---------- ---------
421576540 NULL 0 HEAP 0
421576540 fyi_links_url 3 NONCLUSTERED 0
Is the PRIMARY KEY Column of a Table an Index?
If you define a primary key on a table, an index for the primary key column will be created by
default. The tutorial exercise below shows you the index created as part of the primary key
column of "fyi_links":
USE FyiCenterData;
GO
-- Drop the old table, if needed
DROP TABLE fyi_links;
GO
-- Create a table with primary key
CREATE TABLE fyi_links (
id INT PRIMARY KEY,
url VARCHAR(80) NOT NULL,
notes VARCHAR(1024),
counts INT,
created DATETIME NOT NULL DEFAULT(getdate())
);
GO
-- Create an index for column "url"
CREATE INDEX fyi_links_url ON fyi_links (url);
GO
-- View indexes
EXEC SP_HELP fyi_links;
GO
index_name index_description keys
----------------------- -------------------------- ----
fyi_links_url nonclustered located url
on PRIMARY
PK__fyi_links__239E4DCF clustered, unique, primary
key located on PRIMARY id
Notice that the index created as part of the primary key is named by SQL Server as
"PK__fyi_links__239E4DCF".
Does the UNIQUE Constraint Create an Index?
If you add the UNIQUE constraint on a column, SQL Server will automatically add a non-
clustered index for that column. The tutorial exercise below shows you the index created as part
of the UNIQUE column, "id", of "fyi_links":
USE FyiCenterData;
GO
-- Drop the old table, if needed
DROP TABLE fyi_links;
GO
-- Create a table with a UNIQUE constraint
CREATE TABLE fyi_links (
id INT UNIQUE,
url VARCHAR(80) NOT NULL,
notes VARCHAR(1024),
counts INT,
created DATETIME NOT NULL DEFAULT(getdate())
);
GO
-- Create an index for column "url"
CREATE INDEX fyi_links_url ON fyi_links (url);
GO
-- View indexes
EXEC SP_HELP fyi_links;
GO
index_name index_description keys
----------------------- -------------------------- ----
fyi_links_url nonclustered located url
on PRIMARY
UQ__fyi_links__4222D4EF nonclustered, unique
key located on PRIMARY id
Notice that the index created as part of the UNIQUE constraint is named by SQL Server as
"UQ__fyi_links__4222D4EF".
SQL Server 2005 supports two types of indexes: clustered index and non-clustered index. Here are
the main differences between them:
One table can only have only one clustered index.
One table can only have many non-clustered index.
A clustered index requires no separate storage than the table storage. It forces the rows to be
stored sorted on the index key.
A non-clustered index requires separate storage than the table storage to store the index
information.
A table with a clustered index is called clustered table. Its rows are stored in a B-Tree structure
sorted.
A table without any clustered indexes is called non-clustered table. Its rows are stored in heap
structure unsorted.
The default index created as part of the primary key column is a clustered index
A view is a database object that represents the data in one or more tables in the same structure as a
separate table. Here are some basic rules about views:
Tables store real data.
Views do not store real data.
Views must have underlying tables to provide data.
Each view is based on a single SELECT statement to control what data to collect from tables, and
how data should be represented.
View's columns can be mapped directly to columns in underlying tables.
View's columns can be created expressions based multiple columns in underlying tables.
Views can be used in same way as tables in queries.
How To Create a View on an Existing Table?
If you want to a view on an existing table, you can use the CREATE VIEW statement in a simple
syntax:
CREATE VIEW view_name AS SELECT ...
The tutorial exercise below shows you how to create a view to represent sub set of data stored in
fyi_links table:
USE FyiCenterData;
GO
CREATE VIEW fyi_links_top AS
SELECT id, counts, url FROM fyi_links
WHERE counts > 100;
GO
SELECT TOP 10 * FROM fyi_link_top;
GO
id counts url
------ ------- -----------------------------------------
7600 237946 eyfndw jdt lee ztejeyx l q jdh k
19437 222337 eypx u x
55924 1877 eyq ntohxe i rtnlu riwaskzp cucoa dva c
63742 121330 ezdaeh mmgmo vaai meytbjjv f jixfsdjw pw
92455 945262 ezlmyenrw dyeb
36391 41386 f
87433 977726 f
7180 559314 f kqbqlej s xixuurcgg lh r dqqvqsstxw
2252 702033 f bkh jy sqrkttuoarxmfp idqyhyy tme d
1228 146283 f m asukh
If you want to know how many views you have created in a database, you use the system view called
sys.views to get a list of views defined in the current database. The tutorial exercise shows you how
many views in database FyiCenterData:
USE FyiCenterData;
GO
If you don't need a specific view any more, you can use the DROP VIEW statement to delete it from
the database. The following tutorial exercise shows you how to delete the view, fyi_links_view:
USE FyiCenterData;
GO
If you have an existing view, but you don't remember what are the columns defined in the view, you
can use the "sys.columns" system view to get a list of all columns of all views in the current database.
In order to a list of columns of a single view, you need to join sys.columns and sys.views as shown in
the tutorial example below:
SELECT * FROM sys.columns c, sys.views v
WHERE c.object_id = v.object_id
AND t.name = 'fyi_links_top'
GO
object_id name column_id user_type_id max_length
----------- ------- ---------- ------------ ----------
1205579333 id 1 56 4
1205579333 counts 2 56 4
1205579333 url 3 167 80
You can see the column names easily from the sys.columns view. But you can only see the column
type IDs. This requires another join to get the column type names. You may try the "sp_columns"
stored procedure to get a better list of columns shown in the next tutorial.
How To Get a List of Columns in a View using the "sp_columns" Stored Procedure?
If you have an existing table, but you don't remember what are the columns defined in the view, you
can use the "sp_columns" stored procedure to get a list of all columns of the specified view. The
following tutorial script shows you a good example:
EXEC SP_COLUMNS fyi_links_top;
GO
TABLE_OWNER TABLE_NAME COLUMN_NAME TYPE_NAME LENGTH
----------- ------------- ----------- --------- ------
dbo fyi_links_top id int 4
dbo fyi_links_top counts int 4
dbo fyi_links_top url varchar 80
(3 row(s) affected)
The "sp_columns" stored procedure returns a long list of properties for each column of the specified
view.
How To Get a List of Columns in a View using the "sp_help" Stored Procedure?
Another way to get a list of columns from a view is to use the "sp_help" stored procedure. "sp_help"
returns more than just a list of columns. It returns: the view information, the column information, the
identity column, the row GUID column. The tutorial exercise belwo shows you what you will get with
sp_help:
EXEC SP_HELP fyi_links_top;
GO
Name Owner Type Created_datetime
-------------- ------ ----- -----------------------
fyi_links_top dbo view 2007-05-19 13:43:46.983
Identity
---------------------------
No identity column defined.
RowGuidCol
-----------------------------
No rowguidcol column defined.
If you want to know how an existing view was created, you can use SQL Server Management Studio
to automatically generate a "CREATE VIEW" script The following tutorial shows you how to do this:
1. Run SQL Server Management Studio and connect to SQL server.
2. On the Object Explorer window, follow the object tree: Databases > FyiCenterData > Views >
dbo.fyi_links_top.
3. Click right mouse button on dbo.fyi_links_top. The context menu shows up.
4. Select "Script Table as" > "CREATE to" > "New Query Editor Window". The following script will be
displayed:
USE [FyiCenterData]
GO
/****** Object: View [dbo].[fyi_links_top]
Script Date: 05/19/2007 15:07:27 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[fyi_links_top] AS
SELECT id, counts, url FROM fyi_links
WHERE counts > 100;
If you want get the definition of an existing view back from the SQL Server, you can use the system
view called sys.sql_modules, which stores defitions of views and procedures.
The sys.sql_modules holds view definitions identifiable by the object id of each view. The tutorial
exercise below shows you how to retrieve the definition of view, "fyi_link_view" by joining
sys.sql_modules and sys.views:
USE FyiCenterData;
GO
SELECT m.definition
FROM sys.sql_modules m, sys.views v
WHERE m.object_id = v.object_id
AND v.name = 'fyi_links_top';
GO
definition
-------------------------------------------
CREATE VIEW fyi_links_top (LinkText) AS
SELECT CONVERT(VARCHAR(20),id)
+ ' - ' + CONVERT(VARCHAR(20),counts)
+ ' - ' + url
FROM fyi_links WHERE counts > 1000
(1 row(s) affected)
It is a common practice to normalize data into multiple tables. Then using a view to de-normalize
them into a single output.
The tutorial exercise below shows you how to create a view to normalize data from two tables
SalesOrderHeader and Customer in the sample database AdventureWorksLT.
USE AdventureWorksLT;
GO
Can You Create a View with Data from Another View? The answer is yes. A view can be used as a
table to build other views. The tutorial exercise below shows you how to create a view using data
from another view:
USE AdventureWorksLT;
GO
Assuming that you have a table which is used by a view, and you try to delete that table. SQL Server
will let you delete the table without any trouble.
But that view will become invalid. The tutorial exercise below shows you what happens to the view,
when the underlying table is deleted:
USE FyiCenterData;
GO
Sometimes you want the data in a view to be sorted and try to use the ORDER BY clause in the
SELECT statement to define the view.
But SQL Server will not allow you to use ORDER BY to define a view without the TOP clause. The
tutorial exercise below shows you what error you will get when using ORDER BY in a CREATE VIEW
statement:
USE FyiCenterData;
GO
If you have an existing view, and want to change the underlying SELECT statement, you can use the
"ALTER VIEW ..." statement to redefine the view. The tutorial exercise below shows you how modify
an existing view:
USE FyiCenterData;
GO
But if the question is "Can you insert data into the underlying table through view?" The answer is then
yes. SQL Server will allow you to insert data into the underlying table through a view with a condition:
The insert columns must be limited to columns of a single underlying table.
The tutorial exercise below shows you how to insert data into a underlying table through a view:
USE FyiCenterData;
GO
But if the question is "Can you update data in the underlying table through view?" The answer is then
yes. SQL Server will allow you to update data in the underlying table through a view. The tutorial
exercise below is a good example:
UPDATE fyi_links_top SET url = REVERSE(url)
WHERE id = 100001;
GO
But if the question is "Can you delete data from the underlying table through view?" The answer is
then yes. SQL Server will allow you to delete data from the underlying table through a view. The
tutorial exercise below is a good example:
DELETE FROM fyi_links_top WHERE id = 100001;
GO
By default, column names in a view are provided by the underlying SELECT statement.
But sometimes, the underlying SELECT statement can not provide names for output columns that
specified as expressions with functions and operations. In this case, you need to assign new names
for the view's columns. The tutorial exercise below creates a view to merge several table columns into
a single view column with a format called CSV (Comma Separated Values):
CREATE VIEW fyi_links_dump AS
SELECT CONVERT(VARCHAR(20),id)
+ ', ' + CONVERT(VARCHAR(20),counts)
+ ', ''' + url + ''''
FROM fyi_links WHERE counts > 1000
GO
Msg 4511, Level 16, State 1, Procedure fyi_links_dump,
Line 2
Create View or Function failed because no column name
was specified for column 1.
The first CREATE VIEW gives you an error, because the SELECT statement returns no column for
the concatenated value, and no view column name is specified explicitly
By default, column names in a view are provided by the underlying SELECT statement.
But sometimes, the underlying SELECT statement can not provide names for output columns that
specified as expressions with functions and operations. In this case, you need to assign new names
for the view's columns. The tutorial exercise below creates a view to merge several table columns into
a single view column with a format called CSV (Comma Separated Values):
CREATE VIEW fyi_links_dump AS
SELECT CONVERT(VARCHAR(20),id)
+ ', ' + CONVERT(VARCHAR(20),counts)
+ ', ''' + url + ''''
FROM fyi_links WHERE counts > 1000
GO
Msg 4511, Level 16, State 1, Procedure fyi_links_dump,
Line 2
Create View or Function failed because no column name
was specified for column 1.
The first CREATE VIEW gives you an error, because the SELECT statement returns no column for
the concatenated value, and no view column name is specified explicitly
By default, views are not bound to the schema of the underlying tables. This means that SQL Server
will allow you to change underlying table's schema any time. For example, you can drop the
underlying table while keep the view. Of course, this will make the view not valid any more.
If you don't want anyone to change underlying table's schema once a view has been defined, you can
create a binding view with the "WITH SCHEMABINDING" clause to bind the view to the schema of
underlying tables. A binding view has the following features:
Changing of underlying table's schema is not allowed as long as there exists one binding view.
Indexes can be created only on binding views.
The tutorial exercise below shows you how to create a binding with "WITH SCHEMABINDING":
DROP VIEW fyi_links_view;
GO
The error received in the first CREATE VIEW statement says that you must prefix the table name with
the schema name.
The error received in the DROP TABLE statement proves that you can not change the underlying
tables if there is binding view.
If you need to search and sort data in a view with a large number of row, you may want to create an
index on the view to speed up your search process.
The tutorial exercise below shows you how to create a unique clustered index on a view.
DROP VIEW fyi_links_view;
GO
A stored procedure is a collection of Transact-SQL statements that stored in the SQL Server. A
stored procedure can be executed later with an EXEC statement. SQL Server supports stored
procedures with the following features:
1. Stored procedures can be divided into 3 groups based their accessing scopes:
Permanent Procedures - Created for permanent use.
Global Temporary Procedures - Created for temporary use within all sessions.
Local Temporary Procedures - Created for temporary use within the same session.
4. Stored procedures can be mapped to references to Microsoft .NET Framework common language
runtime (CLR) methods
If you want to create a simple stored procedure with no input and output parameters, you can use the
"CREATE PROCEDURE" command with a statement batch in a simple format as shown in below:
USE FyiCenterData;
GO
EXEC Hello;
GO
-----------
Welcome to;
(1 row(s) affected)
----------------
FYIcenter.com
(1 row(s) affected)
If you want execute a stored procedure created previously, you can use the EXECUTE statement in
the following formats:
EXEC procedure_name;
EXECUTE procedure_name;
The key word EXEC is actually optional. So you can execute a stored procedure by just entering the
procedure name as the statement. See examples in the following tutorial exercise:
USE FyiCenterData;
GO
datetime;
GO
May 19, 2007 11:35PM
Looks like SQL Server allows you to reserved keywords as stored procedure names.
If you want to see a list of stored procedures in your current database, you can use the system view,
sys.procedures as shown in this tutorial exercise:
USE FyiCenterData;
GO
(3 row(s) affected)
If you have an existing procedure that you don't want to use it anymore, you should delete it from the
SQL Server by using the "DROP PROCEDURE" statement as shown in the tutorial example below:
USE FyiCenterData;
GO
(2 row(s) affected)
If you are creating a stored procedure with multiple statements, it's better to use "BEGIN ... END" to
group all statements into a single statement block.
EXEC Show;
GO
name type_desc
------------------- ---------------------
fyi_random USER_TABLE
fyi_links_indexed USER_TABLE
fyi_links USER_TABLE
fyi_links_copy USER_TABLE
name type_desc
------------------- ---------------------
fyi_links_top VIEW
fyi_links_dump VIEW
fyi_links_view VIEW
name type_desc
------------------- ---------------------
Hello SQL_STORED_PROCEDURE
date SQL_STORED_PROCEDURE
Show SQL_STORED_PROCEDURE
Even if you are using a "BEGIN ... END" statement block, the stored procedure structure is not going
to end at the end of the statement block. It will continue to the end of the statement batch, usually the
GO command. The tutorial exercise gives you a good example:
USE FyiCenterData;
GO
EXEC ShowFaq;
GO
Number of questions:
Msg 208, Level 16, State 1, Procedure ShowFaq, Line 3
Invalid object name 'Faq'.
What happened here was that the "CREATE TABLE" statement was not execueted. It was included
as part of the stored procedure "ShowFaq". This is why you were getting the error "Invalid object
name 'Faq'."
If you want to know how an existing stored procedure was created, you can use SQL Server
Management Studio to automatically generate a "CREATE PROCEDURE" script The following
tutorial shows you how to do this:
2. On the Object Explorer window, follow the object tree: Databases > FyiCenterData >
Programmability > Stored Procedures > dbo.ShowFaq.
3. Click right mouse button on dbo.ShowFaq. The context menu shows up.
4. Select "Script Stored Procedure as" > "CREATE to" > "New Query Editor Window". The following
script will be displayed:
USE [FyiCenterData]
GO
/****** Object: StoredProcedure [dbo].[ShowFaq]
Script Date: 05/19/2007 21:31:35 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[ShowFaq] AS BEGIN
PRINT 'Number of questions:';
SELECT COUNT(*) FROM Faq;
PRINT 'First 5 questions:'
SELECT TOP 5 * FROM Faq;
END;
CREATE TABLE Faq (Question VARCHAR(80));
If you want get the definition of an existing stored procedure back from the SQL Server, you can use
the system view called sys.sql_modules, which stores definitions of views and stored procedures.
The sys.sql_modules holds stored procedure definitions identifiable by the object id of each view. The
tutorial exercise below shows you how to retrieve the definition of stored procedure, "ShowFaq" by
joining sys.sql_modules and sys.procedures:
USE FyiCenterData;
GO
SELECT m.definition
FROM sys.sql_modules m, sys.procedures p
WHERE m.object_id = p.object_id
AND p.name = 'ShowFaq';
GO
definition
-----------------------------------------
CREATE PROCEDURE ShowFaq AS BEGIN
PRINT 'Number of questions:';
SELECT COUNT(*) FROM Faq;
PRINT 'First 5 questions:'
SELECT TOP 5 * FROM Faq;
END;
CREATE TABLE Faq (Question VARCHAR(80));
(1 row(s) affected)
If you find a mistake in an existing stored procedure previously created, you can drop (delete) it and
create it again correctly. But dropping a stored procedure may affect other database objects who are
depending on this stored procedure.
So the best way to correct a mistake in an existing stored procedure is to use the "ALTER
PROCEDURE" statement as shown in the following tutorial example:
USE FyiCenterData;
GO
Very often, you need to create a stored procedure with one or more parameters. You only supply
values to those parameters at the time of executing the stored procedure.
Stored procedures with parameters can be created with the following syntax:
CREATE PROCEDURE procedure_name
@parameter_1 datatype,
@parameter_2 datatype,
...
@parameter_n datatype
AS
statement_1;
statement_2;
...
statement_n;
GO
The following tutorial exercise shows you how to create a stored procedure with one parameter called
@url:
USE FyiCenterData;
GO
If a stored procedure is created with parameters, you need pass values to those parameters when
calling the stored procedure with one of two formats listed below:
-- Passing values only
EXEC procedure_name value_1, value_2, ... value_n;
The tutorial exercise below shows 2 ways to pass values to stored procedure parameters:
DROP PROCEDURE Hello;
GO
When calling a stored procedure defined with parameters, you can pass values to those parameters
in two ways:
Passing only values in the same order as parameters defined in the stored procedure.
Passing name-value pairs in any order.
The tutorial exercise shows you some good examples of passing name-value pairs as parameters:
CREATE PROCEDURE diff_in_days
@start_date DATETIME,
@end_date DATETIME
AS BEGIN
PRINT CONVERT(VARCHAR(20),@end_date,107)
+ ' - '
+ CONVERT(VARCHAR(20),@start_date,107)
+ ' = '
+ STR(DATEDIFF(DAY, @start_date, @end_date));
END;
GO
EXEC diff_in_days
'01-Jan-2007',
'19-May-2007';
GO
May 19, 2007 - Jan 01, 2007 = 138
EXEC diff_in_days
@start_date='01-Jan-2007',
@end_date='19-May-2007';
GO
May 19, 2007 - Jan 01, 2007 = 138
Can you pass expressions to stored procedure parameters? The answer is no.
When executing stored procedures, all input values must be entered as data literals, which can be
specified within single quotes ('), or without them if they cause no confusion. The tutorial exercise
below shows you how input values should be specified:
CREATE PROCEDURE area_of_circle @radius REAL
AS BEGIN
PRINT 'Radius = ' + STR(@radius,9,3);
PRINT 'Area = ' + STR(3.14*@radius*@radius,9,3);
END;
GO
If you add a parameter when creating a stored procedure, you can provide a default value so that the
execution statement is not required to pass input value to this parameter.
To provide a default value to a parameter, you should use this format: "@parameter_name data_type
= default_value". The tutorial exercise below shows you how provide default values to stored
procedure parameters:
USE FyiCenterData;
GO
Sometime a stored procedure not only want to take input values from the calling statement batch, but
it also want to send output values back to the calling statement batch. This can be done by defining
output parameters in the CREATE PROCEDURE statement.
To define an output parameter, you should use this format: "@parameter_name data_type OUTPUT",
as shown in the following tutorial exercise:
DROP PROCEDURE diff_in_days;
GO
EXEC diff_in_days
@start_date='01-Jan-2007'
GO
Msg 201, Level 16, State 4, Procedure diff_in_days, Line 0
Procedure or Function 'diff_in_days' expects
parameter '@days', which was not supplied.
If an output parameter is defined in a stored procedure, the execution statement must provide a
variable to receive the output value in the format: "@variable_name OUTPUT" or "@parameter_name
= @variable_name OUTPUT". The following tutorial exercise gives you a good example:
-- Using @variable format
DECLARE @message VARCHAR(40);
EXECUTE diff_in_days
'01-Jan-2007',
'11-May-2007',
@message OUTPUT;
PRINT @message;
GO
May 11, 2007 - Jan 01, 2007 = 130
This tutorial exercise here creates two stored procedures, one is permanent and the other is local
temporary:
DROP PROCEDURE Hello;
DROP PROCEDURE #Hello;
GO
Can another user execute your local temporary stored procedures? The answer is no.
To test this out, continue with the exercise from the previous tutorial. Keep that user session running
and open a new client session with sqlcmd.exe. Then run the tutorial script below:
-- Executing permanent procedure
-- created by another user session
EXECUTE Hello 'fyicenter.com';
GO
Welcome to moc.retneciyf
A collection of 17 FAQs on SQL Server Transact-SQL user defined functions. Clear answers are
provided with tutorial exercises on creating and dropping user defined functions; defining and passing
parameters into functions; providing and using parameter default values; defining and using table-
valued functions.
What Are User Defined Functions?
A user defined function is a collection of Transact-SQL statements that stored in the SQL Server. A
user defined function will return data when executed.
A user defined function works in the same way as a system function. It can be used as a scalar
expression or a temporary table depending on the turning data format. A system function is provided
as part of the SQL Server. But a user defined function must be created and managed by yourself.
If you are using a group of statements to calculate the same data repeatedly in different places, you
should consider to create a user defined function for that group of statements.
What Are the Differences between User Defined Functions and Stored Procedures?
If you add a parameter when creating a stored procedure, you can provide a default value so that the
execution statement is not required to pass input value to this parameter:
To define a default value to a parameter when creating the function, you should use this format:
"@parameter_name data_type = default_value".
To use the default value of a parameter when executing the function, you should use the keyword
DEFAULT as the input value for that parameter.
The tutorial exercise below shows you how provide default values to function parameters:
USE FyiCenterData;
GO
SQL Server supports 2 categories of user defined functions based on their return modes:
1. Scalar-valued Functions - A function that returns a single value. Scalar-valued functions can be
used in scalar expressions. Below are some scalar-valued functions:
PRINT GETDATE();
GO
May 19 2007 1:26PM
2. Table-valued Functions - A function that returns data in rows and columns like a table. Table-
valued functions can be used in table expressions like the FROM clause of SELECT statements
Below are some scalar-valued functions:
SELECT * FROM fn_helpcollations() WHERE name LIKE 'French_CI%'
GO
name
-------------------
French_CI_AI
French_CI_AI_WS
French_CI_AI_KS
French_CI_AI_KS_WS
French_CI_AS
French_CI_AS_WS
French_CI_AS_KS
French_CI_AS_KS_WS
(8 row(s) affected)
1. Inline Table-valued Functions - A table-valued function created with a single SELECT statement:
CREATE FUNCTION function_name(
@parameter_1 data_type,
@parameter_2 data_type,
...
@parameter_n data_type
)
RETURNS TABLE
AS
RETURN (select_statement);
To create an inline table-valued function, you need to use the "RETURNS TABLE" clause in the
"CREATE FUNCTION" statement. There should be no function body, except for a RETURN
statement with a SELECT subquery:
An inline table-valued function can be viewed as a select statement with parameters, see the
example showing in this tutorial exercise:
USE FyiCenterData;
GO
To create a multi-statement table-valued function, you need to define a temporary table as the
returning table in the function. INSERT statements should be used to insert data into the returning
table.
The tutorial exercise below shows you a simple example of how to build a temporary table and make
it as the returning table of a function:
USE FyiCenterData;
GO
A collection of 11 FAQs on SQL Server on creating and managing schemas. Clear answers are
provided with tutorial exercises on listing all schemas and all objects in a schema; transferring tables
from one schema to another schema; changing ownership of a schema
A schema is a container of database objects with the following interesting related rules:
A schema may contain different object types, like tables, indexes, views, procedures, functions,
etc.
A database user can be assigned with a default schema.
Object names must be prefixed with schema names when referencing schemas outside your
default schema.
Every schema has a single owner (a database user). A database user may own multiple
schemas.
If you login name is mapped to the owner of a schema, you have full permissions on this schema.
To drop a schema, you need to empty the schema first.
When you login to a SQL Server and select a database to use, SQL Server will assign your login
session a default schema. The schema name can be omitted when you refer to objects in the default
schema. Here is what you should remember about default schema:
The default schema of your login session in the current database is the default schema assigned
to the current database level principal - database user.
If you are referring to an object in the default schema, you do not need to specify the schema
name.
If you are referring to an object outside the default schema, you must specify the schema name.
The tutorial exercise below shows you how to verify your default schema:
-- Login with "fyi_login"
USE FyiCenterData;
GO
Changed database context to 'FyiCenterData'.
PRINT User_Name();
GO
Fyi_User
The last query shows that the default schema for "fyi_login" in "FyiCenterData" is "dbo".
When you create a schema in a database, SQL Server will assign a owner (a database user) to this
schema. If your login name is mapped to the owner of a schema at the database level, you have the
full permission on all objects in this schema.
The following tutorial exercise shows you how to see who is the owner of a schema:
-- Login with "sa"
USE FyiCenterData;
GO
If you want to change the owner of a schema, you can use the "ALTER AUTHORIZATION" statement
using the following syntax:
ALTER AUTHORIZATION ON SCHEMA::schema_name TO user_name
The following tutorial example shows you how to change ownership of schema "fyi" to "fyi_user":
-- Login with "sa"
USE FyiCenterData;
GO
What Happens If You Are Trying to Access a Schema Not Owned by You?
In general, if you are trying to access an object in schema owned by another database user, you will
get a "permission denied" error, unless that you have been granted access permission to that object
explicitly. Here is a tutorial example showing you the permission error:
-- Login with "fyi_login"
USE FyiCenterData;
GO
PRINT User_Name();
GO
Fyi_User
If you want to delete a schema, you need to move all objects out of that schema, then use the "DROP
SCHEMA" statement to delete the schema. The tutorial exercise below shows you how to drop
schema "fyi":
-- Login with "sa"
USE FyiCenterData;
GO
-- Dropped ok
DROP SCHEMA fyi;
GO
Command(s) completed successfully.
A collection of 20 FAQs on creating and managing triggers. Clear explanations and tutorial exercises
are provided on creating DML and DDL triggers; altering, dropping, enabling and disabling triggers;
accessing inserted and deleted records; overriding DML statements.
A trigger is a special kind of stored procedure that automatically executes when an event occurs in
the database server. A trigger is really an event handler. SQL Server allows users to create triggers
(event handlers) for 3 types of events:
DML Event - Occurs when a DML (Data Manipulation Language) statement: INSERT, UPDATE
or DELETE, is executed.
DDL Event - Occurs when a DDL (Data Definition Language) statement: CREATE, ALTER, or
DROP, is executed.
Logon Event - Occurs when a user logins to the Server.
There are 3 different types of triggers (event handlers) based on the types of events they are
triggered by:
DML Trigger - Executes in response to a DML event.
DDL Trigger - Executes in response to a DDL event.
Logon Trigger - Executes in response to a logon event.
Since a SQL Server trigger is a really an event handler, it has the following basic features similar to
event handlers in other programming languages:
Event Type - It must be declared to handle a specific event, like a DELETE event.
Object Scope - It must be declared to handle events in a specific database object scope, like a
specific table.
Statement Body - It must have a statement body, a batch of statements to be executed when the
specified event occurs in specified database object scope. An event handler (trigger) with an
empty statement body is useless.
Access of Event Attributes - It must have access to some attributes of the event, so it can have
different logics for different instances of the event.
For example, you can implement a trigger to send a security alert message to each user whenever
his or her password is changed. This trigger should have the following features:
Event Type - It must be declared to handle the UPDATE event.
Object Scope - It must be declared to handle the UPDATE event on the user password table only.
Statement Body - It must have a statement body to determine if the password is really changed or
not. If it is changed, send an email to the user's email address.
Access of Event Attributes - It must have access to some attributes of the event instance, like the
old value and the new value of the password, and the user email address.
When a DML event occurs, SQL Server will prepare a temporary table called "INSERTED", which
contains the new record of the affected row, which is:
A copy of the inserted row for an INSERT statement.
A copy of the updated row for an UPDATE statement.
Empty for a DELETE statement.
The tutorial exercise below shows you how to create a trigger, update_user, to report email changes
on table, fyi_users:
USE FyiCenterData;
GO
As you can see, the INSERTED table is helpful, if you want the trigger to perform specific logics on
the affected rows.
When a DML event occurs, SQL Server will prepare a temporary table called "DELETED", which
contains the old record of the affected row, which is:
A copy of the deleted row for a DELETE statement.
A copy of the row to be updated for an UPDATE statement.
Empty for an INSERT statement.
The tutorial exercise below shows you how to improve the trigger, update_user, to report email
changes on table, fyi_users, with both old and new emails:
USE FyiCenterData;
GO
INSERTED and DELETED are working as expected. The reported message is getting better.
How To Improve the Trigger to Handle NULL Values?
When a NULL value is concatenated with a string, the result will be a null value. So if you want the
trigger to properly report NULL values, you need to enhance the trigger as shown in the following
tutorial example:
USE FyiCenterData;
GO
(1 row(s) affected)
If there is only one row affected by a DML statement, we know that the DML trigger will be executed
once. But how many times the DML trigger will be executed if the DML statement resulted multiple
affected rows? The answer is still one.
In the case of multiple affected rows, both INSERTED and DELETED tables will contain multiple
rows.
If you want your trigger to report all affected rows, you need to write a loop
USE FyiCenterData;
GO
select * from fyi_users;
(5 row(s) affected)
Sometime, you may want to implement some business logics in a DML trigger to cancel the DML
statement. For example, you may want to check the new email address format provided by the
UPDATE statement. If the email address is invalid, you to cancel the UPDATE statement.
There is no easy way to cancel the DML statement in a DML trigger. But there is easy way to override
the DML statement with an "INSTEAD OF" trigger. SQL Server supports 2 options (3 keywords) on
when the defined trigger will be fired:
AFTER - Trigger fired after the DML statement executed successfully.
INSTEAD OF - Trigger fired instead of the DML statement execution, allowing the trigger to
decide whether or not, and how, to execute the statement.
FOR - Same as AFTER.
The tutorial exercise below shows you how define an "INSTEAD OF" trigger on fyi_users to validate
email addresses:
USE FyiCenterData;
GO
-- invalid email
UPDATE fyi_users SET email='john.king'
WHERE name = 'John King';
GO
Invalid email(s) found.
-- valid email
UPDATE fyi_users SET email='john@fyicenter'
WHERE name = 'John King';
GO
Email changed from gniK nhoJ to john@fyicenter
-- change all
UPDATE fyi_users SET email='dba@fyicenter';
GO
Email changed from ramuK craM to dba@fyicenter
Email changed from hsuB yoR to dba@fyicenter
Email changed from etaG kcaJ to dba@fyicenter
Email changed from grebneerG ycnaN to dba@fyicenter
Email changed from john@fyicenter to dba@fyicenter
The "invalid email" test shows that trigger check_email did stoped the UPDATE statement. John
King's email did not get updated.
The "valid email" test shows that trigger check_email properly updated the email column, if the new
email is valid. The reported message was generated from trigger update_user.
How To Create a DDL Trigger using "CREATE TRIGGER" Statements?
A DDL trigger is defined to handle a DDL statement event, like create, alter and drop tables, views,
indexes, etc. DDL triggers can be used to generate warning messages on database object changes.
The format of creating a DDL trigger should be:
CREATE TRIGGER trigger_name ON DATABASE
AFTER ddl_event_types
AS
statements
GO
-- ddl_event_types are keywords like:
-- CREATE_TABLE, ALTER_TABLE, DROP_TABLE, ...
Can you roll back the DDL statement in a trigger? The answer is yes. Since the DDL statement that
fires the trigger and the statements defined inside the trigger are all executed as a single statement
batch, you can add a ROLLBACK statement in the trigger to rollback the entire batch.
USE FyiCenterData; GO CREATE TRIGGER drop_rollback ON DATABASE AFTER DROP_TABLE AS
PRINT 'Drop table is not allowed!'; ROLLBACK; GO DROP TABLE fyi_users; GO Drop table is not
allowed! Msg 3609, Level 16, State 2, Line 2 The transaction ended in the trigger. The batch has been
aborted.
This trigger is powerful. It will stop you from dropping any tables in FyiCenterData database.
Can You Create a Logon Trigger in SQL Server 2005 Express Edition?
Can you create a logon trigger in SQL Server 2005 Express Edition? The answer is no. LOGON is
not a supported event type in Express Edition. The script below shows you the error message when
you try to create a logon trigger:
CREATE TRIGGER welcome ON ALL SERVER
AFTER LOGON
AS
PRINT 'Welcome to FyiCenterData database!';
GO
Msg 1084, Level 15, State 1, Procedure welcome, Line 2
'LOGON' is an invalid event type.
Or may be there is a configuration setting that disables the logon event type
A collection of 9 FAQs on working with cursors. Clear explanations and tutorial exercises are
provided on declaring cursor names and cursor variables; open and close cursors; looping through
cursor result set; backward scrolling; dynamic cursors.
A cursor is a special data type that represents a result set returned by a SELECT query statement.
There are several notes about cursor you need to remember:
Cursor data type can not be used to define table columns.
Cursor data type is used on store procedures, functions, and triggers to help you loop through
result sets returned by queries.
Cursor data type can be used to define cursor variables.
There are special Transact-SQL statements dedicated to work with cursors variables: OPEN,
FETCH, CLOSE, and DEALLOCATE.
Cursor variables can be passed as procedure or function parameters.
There is a special function, CURSOR_STATUS(), for check cursor statuses.
A collection of 11 FAQs on working with NULL values. Clear explanations and tutorial exercises
are provided on assigning NULL values to columns, variables and parameters; evaluating
expressions with NULL values; testing NULL values; ISNULL() and NULLIF() functions
A NULL value is a special value that represents an unknown value. SQL Server supports NULL
values with the following features:
All data types used for table columns support NULL values. In another word, NULL values can be
stored in database tables.
Individual table columns may be defined to not allow NULL values. In this case, you can not
assign NULL values to those columns.
"NULL" is a keyword that represent a NULL value in expressions.
NULL values can be used directly in SET (assignment) statements.
If NULL values are involved in an arithmetic operation, the result will be a numeric NULL.
If NULL values are involved in a string operation, the result will be a string NULL.
If NULL values are involved in a datetime operation, the result will be a datetime NULL.
If NULL values are involved in a bitwise operation, the result will be a binary NULL.
If NULL values are involved in a comparison operation, the result will be a Boolean NULL.
If NULL values are involved in a Boolean operation, the result could be TRUE, FALSE, or NULL.
To test NULL values, you need to use two special operators, IS NULL and IS NOT NULL.
Special functions are available to handle NULL values, like ISNULL(), and NULLIF()
The rule for assigning NULL values to variables or table columns is simple: Use keyword "NULL"
directly as normal values. Specificly,
"NULL" can be used in SET statements to assign NULL values to variables.
"NULL" can be used in SET clauses in UPDATE statements.
"NULL" can be used in value lists in INSERT statements.
"NULL" can be used in parameter lists when calling stored procedures or functions.
If NULL values are involved in arithmetic operations, the result will be numeric NULL values. The
following tutorial script shows you some good examples:
SELECT 7+NULL;
GO
-----------
NULL
SELECT 10.02*NULL;
GO
-----------
NULL
SELECT 4.988E+10/NULL;
GO
-----------
NULL
If NULL values are involved in string operations, the result will be string NULL values. The following
tutorial script shows you some good examples:
SELECT 'FyiCenter'+NULL;
GO
----------
NULL
SELECT LEN(NULL);
GO
----------
NULL
SELECT REVERSE(NULL);
GO
----------
NULL
If NULL values are involved in datetime operations, the result will be datetime NULL values. The
following tutorial script shows you some good examples:
USE FyiCenterData;
GO
SELECT GETDATE()+NULL;
GO
-----------
NULL
If NULL values are involved in bitwise operations, the result will be binary NULL values. The following
tutorial script shows you some good examples:
SELECT 1 | NULL;
GO
-----------
NULL
SELECT ~NULL;
GO
-----------
NULL
If NULL values are involved in comparison operations, the result will be Boolean NULL values. This
behavior is very interesting because you would expect a comparison operation returns only one of the
two values: TRUE and FALSE. But SQL Server may return you a third value: NULL.
The tutorial script below proves that "1>NULL" is not returning TRUE or FALSE. It is returning a third
value, NULL:
IF 1>NULL PRINT '1>NULL is returning TRUE'
ELSE PRINT '1>NULL is not returning TRUE'
GO
1>NULL is not returning TRUE
Another test proves that "'FYI'=NULL" is not returning TRUE or FALSE. It is returning a third value,
NULL:
IF 'FYI'=NULL PRINT '''FYI''=NULL returns TRUE'
ELSE PRINT '''FYI''=NULL does not return TRUE'
GO
'FYI'=NULL does not return TRUE
If NULL values are involved in Boolean operations, the result will vary depending on the operator
type. For AND operator, FALSE takes precedence over NULL. The result can be summarized in a
table below:
AND TRUE FALSE NULL
TRUE true false null
FALSE false false false
NULL null false null
For OR operator, TRUE takes precedence over NULL. The result can be summarized in a table
below:
OR TRUE FALSE NULL
TRUE true true true
FALSE true false null
NULL true null null
The tutorial script below shows you that NULL AND FALSE returns FALSE:
IF 0=NULL AND 0=1 PRINT 'NULL AND FALSE returns TRUE'
ELSE PRINT 'NULL AND FALSE does not returns TRUE'
GO
NULL AND FALSE does not returns TRUE
From previous tutorials, you learned that comparing expressions with NULL will always result NULL.
So you can not use comparison operators to test if an expression represents a NULL value or not.
To test expressions for NULL values, you should use one of the following special operators:
expression IS NULL
-- Returns TRUE if the expression is a NULL value
The turorial script below shows you how to use IS NULL and IS NOT NULL:
IF 0 IS NULL PRINT 'TRUE'
ELSE PRINT 'FALSE';
GO
FALSE
As you learned from provious tutorials, NULL values presented in expressions will cause the final
results to be NULL. Sometimes, you want NULL values to be replaced with some default values, like
0, '', or 'NULL', so that expressions can be evaluated properly.
SQL Server offers a built-in function called ISNULL() to help you replacing NULL values in
expressions:
ISNULL(expression, replacement)
-- Returns "expression", if it is not NULL
-- Returns "replacement", if "expression" is NULL
The tutorial example below shows you how to replace possible NULL values in @middle_initial:
USE FyiCenterData;
GO
The first PRINT statement in the second test returns a blank line because of NULL value.
NULLIF() can be viewed as the reverse function of ISNULL(). The tutorial script below shows you a
good example of using NULLIF():
USE FyiCenterData;
GO
-- converting NULL to 0
UPDATE fyi_links SET counts=ISNULL(counts,0);
GO
SELECT id, counts FROM fyi_links;
GO
id counts
----------- -----------
101 0
102 8
1101 0
202 0
2101 0
2102 0
301 0
302 0
-- converting 0 to NULL
UPDATE fyi_links SET counts=NULLIF(counts,0);
GO
SELECT id, counts FROM fyi_links;
GO
id counts
----------- -----------
101 NULL
102 8
1101 NULL
202 NULL
2101 NULL
2102 NULL
301 NULL
302 NULL
SQL Server 2005 uses a very standard security model involves 3 concepts:
Securables - Entities representing resources that need to be secured. For example, a database
table is a securable.
Principals - Entities representing users that request accesses to resources. For example, a login
user is a principal.
Permissions - Types of accesses associated with securables. Permissions can be granted to or
revoked from principals. For example, "Update" is a permission associated a securable, table "R".
"Update" on "R" can be granted to a principal, user "U". Now user "U" will get "Update" access on
table "R".
In simple terms, a principal answers the security question of "Who are you?"; a securable answers
the security question of "What is your target object?"; a permission answers the security question of
"You are allowed to perform this action on this target object".
SQL Server 2005 supports multiple securables and multiple principals organized into hierarchical
structures as shown in this picture:
(Picture by Microsoft)
SQL Server 2005 supports several basic security principals located at different levels:
Windows-Level Principals: Windows Local Login and Windows Network Domain Login - Used to
control accesses to SQL Server instances.
SQL Server-Level Principal: SQL Server Login. - Used to control accesses to SQL Server
instances.
Database-Level Principal: Database User. - Used to control accesses to database instances.
To access a SQL Server instance, you must use a Windows login or a SQL Server login previously
created in that server instance. Once you logged in, you are represented by this login name as your
security principal at the server level.
If you select a specific database in the server to use, SQL Server will search that database for a
previously user that has been mapped to your login name. If that user is located, you are represented
by this user name as your security principal at the database level.
What Is the Security Principal at the Server Level That Represents Your Session?
Security principal identifies who you are when you interact with the SQL Server. What can do you at
the server level solely depends on the security principal that represents you. So it is very important to
know your security principal at the server level.
What is the server level security principal of your session? The answer is simple - the login name you
used to connect to the server to start the session. For example, if you connects to the server with the
login name "sa", then your security principal is "sa" at the server level.
On a Unix system, there is a nice command called "whoami" which returns your security principal on
the system. SQL Server provides a similar function called Suser_Sname(), which returns your
security principal (a login name) at the server. Try it by following this tutorial example:
-- Find out your security principal at the server level
PRINT Suser_Sname();
GO
sa
This example shows you that you used "sa" as the login name to connect to the server.
What Is the Security Principal at the Database Level That Represents Your Session?
Security principal identifies who you are when you interact with the SQL Server. What can do you at
the database solely depends on the security principal that represents you. So it is very important to
know your security principal at the database level.
What is the database level security principal of your session? The answer is simple - the user name
in the current database that has been mapped to your login name. For example, if you connects to
the server with the login name "sa", and sets "FyiCenterData" as the current database, SQL Server
will map "sa" to a user name defined in "FyiCenterData" based on some logics. That mapped user
name is your security principal for "FyiCenterData" at the database level.
On a Unix system, there is a nice command called "whoami" which returns your security principal on
the system. SQL Server provides a similar function called User_Name(), which returns your security
principal (a user name mapped to the login name) at the database level. Try it by following this tutorial
example:
PRINT Suser_Sname();
GO
sa
USE FyiCenterData;
GO
In previous tutorials, it is assumed that you use the "sa" (System Administrator) login name to connect
to your SQL Server. But that is not what a normal developer uses to connect to the server, since "sa"
has the ALL permissions granted. You need to create new login names and grant less permissions to
them, and give them to developers.
To create a new login name, you can use the "CREATE LOGIN" statement in a simple syntax like
this:
CREATE LOGIN login_name WITH PASSWORD = 'password'
To run "CREATE LOGIN" statement, you need to connect to the server with a privileged login name
like "sa". See the tutorial example below:
-- Login with 'sa'
The quickest way to verify a login name on a SQL Server is probably to use the SQLCMD tool, which
takes the server name, login name and password in a single command line. Here is how to try it
yourself:
This shows FYI_DBA is a valid login and the password is correct. Now try this command:
C:\>SQLCMD -S LOCALHOST\SQLEXPRESS -U FYI_DEV -P ABD_IYF
Msg 18456, Level 14, State 1, Server LOCALHOST\SQLEXPRESS, Line 1
Login failed for user 'FYI_DEV'.
C:\>
If a developer lost the password of his or her login name, you can reset the password with the
"ALTER LOGIN" statement as shown in this tutorial example:
-- Login with sa
You can also use the "ALTER LOGIN" to change your own password.
If you want to change a login name, you can use the "ALTER LOGIN" statement as shown in this
tutorial example:
-- Login with "sa"
If you want temporarily disable a login name, you can use the "ALTER LOGIN" statement with a
DISABLE keyword. If you want to enable it later on, you can use the ENABLE keyword. The tutorial
exercise below shows how to disable and enable login name "Dba_Login":
-- Login with "sa"
-- Disable a login
ALTER LOGIN Fyi_Login DISABLE;
-- Enable a login
ALTER LOGIN Fyi_Login ENABLE;
If you don't want to keep a login name any more, you should delete it by using the "DROP LOGIN"
statement as shown in this tutorial example:
-- Login with "sa"
User names are security principals at the database level. If you want to allow a login name to access
a specific database, you need to create a user name in that database and link it to the login name.
Creating a user name can be done by using the "CREATE USER" statement as shown in this tutorial
exercise:
-- Login with "sa"
-- Create a login
CREATE LOGIN Fyi_Login WITH PASSWORD = 'IYF'
GO
-- Select a database
USE FyiCenterData;
GO
Login name "Fyi_Login" should be able to access database "FyiCenterData" through user name
"Fyi_User".
If you want to see a list of all user names defined in a database, you can use the system view,
sys.database_principals as shown in this tutorial exercise:
-- Login with sa
-- Select a database
USE FyiCenterData;
GO
As you can see, there are 5 user names defined in "FyiCenterData". 4 are defined by SQL Server
during the database creation process. Only the last one "Fyi_User" was defined by you in the
previous tutorial.
If you know a user name in a database and you want to find out which login name is linked this user
name, you need to check the Security ID (SID) of the user name based on the following rules:
Each login name is associated a unique SID.
When a user name is linked to a login name, the login name's SID is copied to the user name.
So the login name linked to a user name must have the SID as the user name. The tutorial exercise
below shows you how to find the login name that is linked to the user name "Fyi_User":
-- Login with sa
USE FyiCenterData;
GO
The quickest way to verify a user name in a database is probably to use the SQLCMD tool. You can
connect to the server, select the database, and check which user name is linked the current login
name as shown below.
This shows user "Fyi_User" in database "FyiCenterData" is linked to login name "Fyi_Login".
If you want to change the name of an existing database user, you can use the "ALTER USER"
statement as shown in the tutorial exercise below:
-- Login with "sa"
USE FyiCenterData;
GO
If you don't want to keep a database user any more, you should delete the user by using the "DROP
USER" statement. This tutorial exercise shows how to delete "Dba_User":
-- Login with "sa"
USE FyiCenterData;
GO
SQL Server FAQs - Configuring ODBC Connection and DSN for SQL Servers
A collection of 13 FAQs on connecting SQL Server via an ODBC DSN setting. Clear explanations
and tutorial exercises are provided on creating new DSN with the SQL Server ODBC driver; starting
SQL Server Browser Service; enabling TCP/IP protocol on SQL Server; verifying TCP/IP port
numbers; testing ODBC DSN settings with MS Access.
ODBC, Open Database Communication, a standard API (application program interface) developed by
Microsoft for Windows applications to communicate with database management servers.
If you want to access a database server through an ODBC driver from an application program, you
need to meet the following requirements:
An ODBC driver specifically designed for the database server.
An ODBC DSN (Data Source Name) - an ODBC configuration representing the ODBC driver and
database server.
An ODBC API (Application Programming Interface) for your application program to interact with
database server through the ODBC driver.
For example, if you want to a SQL Server in a PHP script through an ODBC driver, you need to make
sure that:
An ODBC driver for MS SQL Server - The ODBC driver is installed as part of the Windows
system.
An ODBC DSN - You need to create one yourself using the ODBC configuration tool.
An ODBC API in PHP language - The API is installed as part of the PHP engine.
How To Add a New DSN with the ODBC Driver for SQL Server?
Assuming that the ODBC driver for SQL Server has been installed as part of the Windows system,
the next step of setting up ODBC connection to SQL Server is to create a new DSN (Data Source
Name) with the ODBC Data Source Administrator:
Go to Control Panel.
Go to Administrative Tools.
Run Data Sources (ODBC). The ODBC Data Source Administrator window shows up.
Go to System DSN tab.
Click the Add button.
You should a list of all ODBC drivers installed on your system. SQL Server ODBC driver should be on
the list. If you look at the picture below, you will see the SQL Server ODBC driver with version
2000.85.1117.00, file SQLSRV32.DLL, date 8/4/2004:
Select "SQL Server" from the ODBC driver list, and click "Finish" button. The "Create a New Data
Source to SQL Server" wizard window shows up. Continue with the next tutorial to finish up creating a
new DSN.
Continuing from the previous tutorial, on the first screen of the "Create a New Data Source to SQL
Server" wizard, you should enter 3 fields: Name, Description, and Server as suggested below:
Name: FYI_SQL_SERVER
Description: FYIcenter.com SQL Server
Server: LOCALHOST
Note that the name and description can be decided by yourself. But the server must be the network
machine name where the SQL Server is running. In this example, LOCALHOST is the machine name
for your local system.
Click Next and continue with the next tutorial to finish up creating a new DSN.
Continue from the previous tutorial. After clicking Next on the first screen of the "Create a New Data
Source to SQL Server" wizard, you should see the second screen asking you to select SQL Server
login type, login name and password.
Select the radio button on "With SQL Server authentication using a login ID and password entered by
the user. Also enter in Login ID field: "sa" and in Password field: "FYIcenter". See the picture below:
Remeber that "sa" is the system administrator login name, you probably should use a less privileged
login name here. "FYIcenter" must be the correct password defined in the SQL Server for "sa" login
name.
Click Next and continue with the next tutorial to finish up creating a new DSN
Why Are You Getting Errors When Creating a New ODBC DSN?
Continue from the previous tutorial. After clicking Next on the SQL login information screen, ODBC
manager will try to connect to the SQL Server with the login information you provided.
After a period of waiting time, you may get error message box saying that:
Connection failed:
SQLState: '01000'
SQL Server Error: 53
[Microsoft][ODBC SQL Server Driver][DBNETLIB]
ConnectionOpen(Connect()).
Connection failed:
SQLState: '08001'
SQL Server Error: 17
[Microsoft][ODBC SQL Server Driver][DBNETLIB]
SQL Server does not exist or access denied.
The first and third reasons are easy to validate and correct. The second reason requires further
investigation. Continue with the next tutorial to configure your SQL Server to take a network
connection.
By default, SQL Server 2005 Express Edition is installed only one connection protocol enabled:
Shared Memory - SQL Server connection protocol for applications that are running on the same
machine where the SQL Server is running. For example, if you are running SQLCMD tool on the
SQL Server machine, it will use the "Shared Memory" protocol.
If you want application that are running remotely to connect and access the SQL Server you need
enable the "TCP/IP" protocol.
For applications that are running on the same machine as the SQL Server, but they do not support
"Shared Memory" protocol, you also need to enable the "TCP/IP" protocol for those applications.
ODBC Manager is an application that requires the "TCP/IP" protocol to connect to the SQL Server.
In order for the SQL Server to accept network connections, you also need to run SQL Server Browser
Service on the SQL Server machine.
In summary, there are two requirements for a SQL Server to accept network connections:
Start SQL Server Browser Service on the SQL Server machine.
Enable the TCP/IP protocol support on the SQL Server.
5. Click on "SQL Server 2005 Services". You will see two services.
6. Right-mouse click on "SQL Server (SQLEXPRESS)" and select restart to finish the TCP/IP
protocol setting change.
Your SQL Server is ready to accept network connection now
How To Verify the Port Number of the SQL Server?
When applications use TCP/IP for network communication, you need to know the port number
where the server is listening for connect request from the client.
If you want to connect to the SQL Server through the TCP/IP, you must know on which port
number the SQL Server is listening for connection requests. Follow this tutorial to find and verify
the port number of your SQL Server.
1. Go to Start > All Programs > Microsoft SQL Server 2005 > Configuration Tools > SQL Server
Configuration Manager.
2. Double click on "SQL Server 2005 Network Configuration" to see the list of SQL Server
instances.
3. Click on "Protocols for SQLEXPRESS". You will see a list of protocols.
4. Right-mouse click on TCP/IP and select the "Properties" command. The properties dialog box
shows up.
Click the IP Address tab. The server IP address and port number used by the SQL Server will be
displayed. You should see something like:
IP Address: 127.0.0.1
Ports: 1269
Note that 1433 may also be used as the default port number by your SQL Server.
How To Configure ODBC DSN with Different Port Numbers?
If your SQL Server is not using the default port number, like 1269, you need to set the port
number to the correct value during the ODBC DSN creation process, as show in this tutorial:
1. Start ODBC Data Source Administrator and click System DSN tab.
2. Click Add button, select SQL Server and click Finish button.
3. Enter the following and click Next:
Name: FYI_SQL_SERVER
Description: FYIcenter.com SQL Server
Server: LOCALHOST
4. Select the radio button on "With SQL Server authentication using a login ID and password
entered by the user. Also enter in Login ID field: "sa" and in Password field: "FYIcenter".
5. Click "Client Configuration..." button. The "Edit Network Library Configuration" dialog box
shows up.
Check and uncheck "Dynamically determine port" and enter "1269" as the Port Number. See
picture bellow:
Click OK and continue with the next tutorial to finish up ODBC DSN creation.
How To Configure and Test ODBC DSN Settings?
Continue from the previous tutorial. Click Next after you have finished changing the port number.
The ODBC Data Source Administrator will try to connect to the SQL server through the specified
port number and login information.
If the connection is successful, you will see the next screen asking for selecting default database.
1. Check "Change the default database to:" check box, and select "FyiCenterData" as the default
database for this DSN setting. See picture bellow:
2. Click Next to see the last screen of the "Create a New Data Source to SQL Server" wizard.
3. Change nothing on the last screen and click Finish button. The confirmation screen shows up.
4. Click "Test Data Source..." button. You should see the test result as:
Attempting connection
Connection established
Verifying option settings
Disconnecting from server
TESTS COMPLETED SUCCESSFULLY!
Your FYI_SQL_SERVER ODBC DSN is ready to use
Once you got a DSN defined in the ODBC manager that connects to your SQL Server, you can
connect a normal MS Access document to the Oracle server, and link an Access table to a SQL
Server table. The tutorial below gives you a good example:
Start MS Access with a new database file.
Go to File menu.
Select Get External Data.
Select Import.... The Import dialog box shows up.
Select Files of type: ODBC Database(). The Select Data Source dialog box shows up.
Click the Machine Data Source tab. You should see the DSN name "FYI_SQL_SERVER" you
defined earlier.
Select "FYI_SQL_SERVER".
Enter User Name: sa.
Enter Password: FYIcenter.
Click the OK button to continue. You should see a list of tables available for you to import from the
SQL Server as shown in the picture below:
Select the table you are interested in and click OK. You should the selected table being imported from
the SQL Server to MS Access.
One way of connecting a windows application to a SQL Server is to use ODBC drivers. The
requirements to do this is summarized here:
The SQL Server must have TCP/IP protocol enabled with a specific port number.
The SQL Server Browser Service must be running on the server machine.
A ODBC DSN must be created to represent the connection to SQL Server on the specified port
number.
The local windows application must be able to support ODBC API calls.
The diagram below shows how MS Access can connect to a SQL Server through the ODBC driver:
SQL Server FAQs - PHP ODBC Functions - Connection and Query Execution
A collection of 14 FAQs on using PHP ODBC functions to connect to SQL Server databases. Clear
explanations and tutorial exercises are provided on testing ODBC DSN settings; creating connection
to a SQL Server through a DSN; executing SQL statements; looping through result set; Executing
prepared statements
If you are planning to use ODBC connections to access SQL Server databases in PHP scripts, you
need to check the following requirements:
The PHP engine must support ODBC functions. If you install PHP 5.2.2 from The PHP Group, the
ODBC functions are already included in the default installation.
The SQL Server must have TCP/IP protocol enabled for a specific port.
The SQL Server Browser Service must be running on the SQL server machine.
An ODBC DSN must be created on machine where you are running PHP scripts.
The ODBC DSN connection must be tested to make sure it is working.
You need to following other tutorials provided by FYIcenter.com to install PHP engine, install SQL
Server, configure TCP/IP protocol, start SQL Server Browser Service, create and test ODBC DSN
connections.
If you look at the PHP 5 manual, you will see a group of functions listed under the ODBC Functions
(Unified) setion. The commonly used ODBC functions are:
odbc_connect — Establish an OBDC connection.
odbc_data_source — Returns information about a current connection.
odbc_close — Close an ODBC connection.
odbc_exec — Prepare and execute a SQL statement.
odbc_fetch_row — Fetch a row - moving the pointer to the a new row in a result object.
odbc_result — Get the value of a specific field from the current row of a result object.
odbc_fetch_array — Fetch a result row as an associative array.
odbc_fetch_object — Fetch a result row as an object.
odbc_num_rows — Number of rows in a result.
odbc_field_name — Get the name of a specified field index.
odbc_field_type — Get the data type of a specified field index.
odbc_next_result — Checks if multiple results are available.
odbc_free_result — Free resources associated with a result object.
odbc_prepare — Prepares a statement for execution.
odbc_execute — Execute a prepared statement.
odbc_error — Get the last error code.
odbc_errormsg — Get the last error message.
odbc_tables — Get the list of table names stored in a specific data source.
odbc_columns — Lists the column names in specified tables.
odbc_autocommit — Toggle autocommit behaviour.
odbc_commit — Commit an ODBC transaction.
odbc_rollback — Rollback a transaction.