Declare (@local - Variable Data - Type ( Value) ) : @testvariable 100 @testvariable
Declare (@local - Variable Data - Type ( Value) ) : @testvariable 100 @testvariable
In SQL Server, local variables are used to store data during the batch execution period. The local
variables can be created for different data types and can also be assigned values. Additionally,
variable assigned values can be changed during the execution period. The life cycle of the variable
starts from the point where it is declared and has to end at the end of the batch. On the other hand,
If a variable is being used in a stored procedure, the scope of the variable is limited to the current
stored procedure.
Firstly, if we want to use a variable in SQL Server, we have to declare it. The DECLARE statement is
used to declare a variable in SQL Server. In the second step, we have to specify the name of the
variable. Local variable names have to start with an at (@) sign because this rule is a syntax necessity.
Finally, we defined the data type of the variable. The value argument which is indicated in the syntax
is an optional parameter that helps to assign an initial value to a variable during the declaration. On
the other hand, we can assign or replace the value of the variable on the next steps of the batch. If
we don’t make any initial value assigned to a variable, it is initialized as NULL.
The following example will declare a variable whose name will be @VarValue and the data type will
be varchar. At the same time, we will assign an initial value which is ‘Save Our Planet’:
DECLARE @TestVariable AS VARCHAR(100) = 'Save Our Planet'
PRINT @TestVariable
SQL Server offers two different methods to assign values into variables except for initial value
assignment. The first option is to use the SET statement and the second one is to use the SELECT
statement. In the following example, we will declare a variable and then assign a value with the help
of the SET statement:
In the following example, we will use the SELECT statement in order to assign a value to a variable:
USE [AdventureWorks2019]
GO
DECLARE @PurchaseName Varchar(100)
SELECT @PurchaseName = Name
FROM [Purchasing].[Vendor]
WHERE BusinessEntityID=1492
PRINT @PurchaseName
As can be seen, the @PurchaseName value has been assigned from the Vendor table.
USE [AdventureWorks2019]
GO
DECLARE @StockValue int
SELECT @StockValue=[dbo].[ufnGetStock](1)
SELECT @StockValue as VaribaleValue
--PRINT @StockValue
For different cases, we may need to declare more than one variable. In fact, we can do this by
declaring each variable individually and assigned a value for every parameter:
This way is tedious and inconvenient. However, we have a more efficient way to declare multiple
variables in one statement. We can use the DECLARE statement in the following form so that we can
assign values to these variables in one SELECT statement:
USE [AdventureWorks2019]
GO
DECLARE @Variable1 AS VARCHAR(100), @Variable2 AS UNIQUEIDENTIFIER
SELECT @Variable1='Save Water Save Life', @Variable2='6D8446DE-68DA-4169-A2C5-
4C0995C00CC1'
PRINT @Variable1 + CONVERT(NVARCHAR(100),@Variable2)
PRINT @Variable1
PRINT @Variable2
Also, we can use a SELECT statement in order to assign values from tables to multiple variables:
USE [AdventureWorks2019]
GO
DECLARE @VarAccountNumber AS NVARCHAR(15), @VariableName AS NVARCHAR(50)
SELECT @VarAccountNumber=AccountNumber , @VariableName=Name
FROM [Purchasing].[Vendor]
WHERE BusinessEntityID=1492
PRINT @VarAccountNumber
PRINT @VariableName
The above script generated an error because of the GO statement. GO statement determines the end
of the batch in SQL Server thus @TestVariable lifecycle ends with GO statement line. The variable
which is declared above the GO statement line can not be accessed under the GO statement.
However, we can overcome this issue by carrying the variable value with the help of the temporary
tables:
USE [AdventureWorks2019]
GO
IF OBJECT_ID('tempdb..#TempTbl') IS NOT NULL DROP TABLE #TempTbl
DECLARE @TestVariable AS VARCHAR(100)
SET @TestVariable='Hello World'
SELECT @TestVariable as VarVal INTO #TempTbl
GO
DECLARE @TestVariable AS VARCHAR(100)
SELECT @TestVariable = Varval FROM #TempTbl
PRINT @TestVariable
Tip 2: Assume that, we assigned a value from table to a variable and the result set of the SELECT
statement returns more than one row. The main issue at this point will be which row value is
assigned to the variable. In this circumstance, the assigned value to the variable will be the last row
of the result set. In the following example, the last row of the result set will be assigned to the
variable:
USE [AdventureWorks2019]
GO
SELECT AccountNumber
FROM [Purchasing].[Vendor]
ORDER BY BusinessEntityID
What to choose when assigning values to SQL Server variables: SET vs SELECT T-
SQL statements
SQL Server provides us with two methods in T-SQL to assign a value to a previously created local
SQL variable. The first method is the SET statement, the ANSI standard statement that is commonly
used for variable value assignment. The second statement is the SELECT statement. In addition to its
main usage to form the logic that is used to retrieve data from a database table or multiple tables in
SQL Server, the SELECT statement can be used also to assign a value to a previously created local
variable directly or from a variable, view or table.
Although both T-SQL statements fulfill the SQL variable value assignment task, there is a number of
differences between the SET and SELECT statements that may lead you to choose one of them in
specific circumstances, over the other. In this article, we will describe, in detail, when and why to
choose between the SET and SELECT T-SQL statements while assigning a value to a variable.
We will start with creating a new table and fill it with few records for our demo. This can be achieved
using the below script:
The inserted data can be checked using the following SELECT statement:
If we manage to assign a scalar value for the SQL variable that is previously defined using the DECLARE
statement, both the SET and SELECT statements will achieve the target in the same way. The below SET
statement is used to assign the @EmpName1 variable with the scalar “Ali” value:
DECLARE @EmpName1 NVARCHAR(50)
SET @EmpName1 = 'Ali'
PRINT @EmpName1
GO
In the same way, the below SELECT statement can be used to assign the @EmpName2 variable with
the scalar “Ali” value:
The SELECT statement can be also used to perform the same assignment task in a different way as
shown below:
DECLARE @EmpName NVARCHAR(50)
SELECT @EmpName = [Name] FROM SetVsSelectDemo WHERE GroupNumber = 3
PRINT @EmpName
GO
Until this point, you can see that both the SET and SELECT statements can perform the variable value
assignment task in the same way and differ from the code side only.
Assume that we need to assign values to multiple variables at one shot. The SET statement can
assign value to one variable at a time; this means that, if we need to assign values for two variables,
we need to write two SET statements. In the below example, each variable requires a separate SET
statement to assign it scalar value, before printing it:
On the other hand, the SELECT statement can be used to assign values to the previously defined multiple
SQL variables using one SELECT statement. The below SELECT statement can be easily used to assign
scalar values to the two variables using one SELECT statement before printing it:
DECLARE @EmpName1 NVARCHAR(50) , @EmpName2 NVARCHAR(50)
SELECT @EmpName1 = 'Ali', @EmpName2 = 'Fadi'
PRINT @EmpName1
PRINT @EmpName2
GO
You can see from the printed result below, that both statements achieve the same task, with the
SELECT statement better than the SET statement when trying to assign values to multiple variables
due to code simplicity:
Again, if we try to assign values from database table to multiple variables, it requires us SET
statements equal to the number of variables. In our example, we need two SET statements to assign
values from the SetVsSelectDemo table to the @EmpName and @EmpGrade variables as shown in
the script below:
DECLARE @EmpName NVARCHAR(50), @EmpGrade INT
SET @EmpName = (SELECT [Name] FROM SetVsSelectDemo WHERE GroupNumber = 3)
SET @EmpGrade = (SELECT [Grade] FROM SetVsSelectDemo WHERE GroupNumber = 3)
PRINT @EmpName
PRINT @EmpGrade
GO
On the other hand, only one SELECT statement can be used to assign values from the
SetVsSelectDemo table to the @EmpName and @EmpGrade SQL variables, using simpler query as
shown clearly below:
DECLARE @EmpName NVARCHAR(50), @EmpGrade INT
SELECT @EmpName=[Name] , @EmpGrade =[Grade] FROM SetVsSelectDemo WHERE GroupNumber = 3
PRINT @EmpName
PRINT @EmpGrade
GO
Multiple values
The second point, in which the difference between assigning values to the SQL variables using the
SELECT or SET statements appears, is when the result set of the subquery query that is used to assign
a value to the variable returns more than one value. In this case, the SET statement will return an
error as it accepts only one scalar value from the subquery to assign it to the variable, while the
SELECT statement accepts that situation, in which the subquery will return multiple values, without
raising any error. You will not, though, have any control on which value will be assigned to the
variable, where the last value returned from the subquery will be assigned to the variable.
Assume that we need to assign the Name value of the second group from the previously created
SetVsSelectDemo table to the @EmpName SQL variable. Recall that the second group on that table
contains two records in the result set as shown below:
The script that is used to assign the @EmpName variable value from the SetVsSelectDemo table
using the SET and SELECT statements will be like:
DECLARE @EmpName NVARCHAR(50)
SET @EmpName = (SELECT [Name] FROM SetVsSelectDemo WHERE GroupNumber = 2)
PRINT @EmpName
GO
Due to the fact that, the subquery statement returned two records, assigning value to the
@EmpName SQL variable using the SET statement will fail, as the SET statement can assign only
single value to the variables. This is not the case when assigning value to the @EmpName variable
using the SELECT statement that will succeed with no error, assigning the name from the second
returned record, which is “Zaid”, to the variable as shown in the result messages below:
We can learn from the previous result that, when you expect that the subquery will return more than
one value, it is better to use the SET statement to assign value to the variable by implementing a
proper error handling mechanism, rather than using the SELECT statement that will assign the last
returned value to the SQL variable, with no error returned to warn us that the subquery returned
multiple values.
Assign no value
Another difference between assigning values to the SQL variables using the SET and SELECT
statements, is when the subquery that is used to assign a value to the variable return no value. If the
previously declared variable has no initial value, both the SET and SELECT statement will act in the
same way, assigning NULL value to that variable.
Assume that we need to assign the @EmpName variable, with no initial value, the Name of the fifth
group from the SetVsSelectDemo table. Recall that this table has no records that belong to the fifth
group as shown below:
The script that is used to assign the value to the @EmpName variable from the SetVsSelectDemo
table will be like:
DECLARE @EmpName NVARCHAR(50)
SET @EmpName = (SELECT [Name] FROM SetVsSelectDemo WHERE GroupNumber = 5)
SELECT @EmpName AS SET_Name
GO
Having no initial value for the @EmpName variable, and no value returned from the subquery, a
NULL value will be assigned to that variable in both cases as shown clearly in the result message
below:
If the previously declared SQL variable has an initial value, and the subquery that is used to assign a
value to the variable returns no value, the SET and SELECT statement will behave in different ways. In
this case, the SET statement will override the initial value of the variable and return the NULL value.
On the contrary, the SELECT statement will not override the initial value of the variable and will return
it, if no value is returned from the assigning subquery.
If we arrange again to assign the @EmpName variable, the Name of the fifth group from the
SetVsSelectDemo table, recalling that this table has no records that belong to the fifth group, but
this time, after setting an initial value for the @EmpName SQL variable during the variable
declaration, using the SET and SELECT statements, as shown in the script below:
Taking into consideration that the assigning subquery retuned no value, the query that used the SET
statement to assign value to the SQL variable will override the initial value of the variable, returning
NULL value, while the query that used the SELECT statement to assign value to the variable will keep
the initial value with no change as no value is returned from the subquery, as shown clearly in the
results below:
Conclusion
SQL Server provides us with two main methods that are used to assign values to the SQL variables. In
most cases, both the SET and SELECT statements fulfill the variable value assignment task with no
issue. In some situations, you may prefer using one over the other, such as:
If you manage to assign values to multiple variables directly or from a database table, it is
better to use the SELECT statement, that requires one statement only, over the SET statement
due to coding simplicity
If you are following the ANSI standard for code migration purposes, use the SET statement
for SQL variables values assignment, as the SELECT statement does not follow the ANSI
standard
If the assigning subquery returns multiple values, using the SET statement to assign value to
a variable will raise an error as it only accepts a single value, where the SELECT statement will
assign the last returned value from the subquery to the variable, with no control from your
side
If the assigning subquery returns no value, the SET statement will override the variable initial
value to NULL, while the SELECT statement will not override its initial value
The table variable is a special type of the local variable that helps to store data temporarily, similar to
the temp table in SQL Server. In fact, the table variable provides all the properties of the local
variable, but the local variables have some limitations, unlike temp or regular tables.
Syntax
If we want to declare a table variable, we have to start the DECLARE statement which is similar to
local variables. The name of the local variable must start with at(@) sign. The TABLE keyword
specifies that this variable is a table variable. After the TABLE keyword, we have to define column
names and datatypes of the table variable in SQL Server.
In the following example, we will declare a table variable and insert the days of the week and their
abbreviations to the table variable:
The answer to this question is – table variables are stored in the tempdb database. Why we underline
this is because sometimes the answer to this question is that the table variable is stored in the
memory, but this is totally wrong. Before proving the answer to this question, we should clarify one
issue about the table variables. The lifecycle of the table variables starts in the declaration point and
ends at the end of the batch. As a result, the table variable in SQL Server is automatically dropped at
the end of the batch:
As you can see, the previous query returns two result sets. The ResultSet-1 contains column names
and data types of the declared table variable and the ResultSet-2 does not contain any data. The
reason for this case is, the first INFORMATION_SCHEMA.COLUMNS view, and table variable executed
in the same batch so we can get the information of the @ExperiementTable table variable from the
tempdb database. The second query could not return any data about the @ExperiementTable
because the GO statement ends the batch so the life-cycle of the @ExperiementTable table variable
is terminated. In this section, we proved the storage location of the table variable in SQL Server.
Constraints are database objects that ensure data integrity. Table variables allow us to create the
following constraints:
Primary Key
Unique
Null
Check
In the following example, we will successfully use all types of constraints on the table variable
seamlessly:
DECLARE @TestTable TABLE
(ID INT PRIMARY KEY,
Col1 VARCHAR(40) UNIQUE,
Col2 VARCHAR(40) NOT NULL,
Col3 int CHECK (Col3>=18))
On the other hand, Foreign Key constraints cannot use for the table variables. The other restriction is,
we have to define the constraints when we are declaring the table variable otherwise, we experience
an error. For example, the following query will return an error because of this restriction. We cannot
alter the table structure after the declaration of the table variable:
Transactions are the smallest logical unit that helps to manage the CRUD (insert, select, update and
delete) operations in the SQL Server. Explicit transactions are started with BEGIN TRAN statement
and they can be completed with COMMIT or ROLLBACK statements. Now we will execute the
following query and then analyze the result:
ROLLBACK TRAN
Table variable CRUD operations do not manage by explicit transactions. As a result, ROLLBACK TRAN
cannot erase the modified data for the table variables.
The TRUNCATE statement helps to delete all rows in the tables very quickly. However, this statement
cannot be used for table variables. For example, the following query will return an error:
According to this tip interpretation, the following query has to return an error:
The table variable in SQL Server should use an alias with the join statements
If we want to join two or more table variables with each other or regular tables, we have to use an
alias for the table names. The usage of this looks like this:
on Dep.DepartmentID = Emp.DepartmentID
ON @TestTable(Col1)
However, we can overcome this issue with the help of the implicit index definitions because the
PRIMARY KEY constraint or UNIQUE constraints definitions automatically create an index and we can
use these INDEX statements in order to create single or composite non-clustered indexes. When we
execute the following query, we can figure out the created index which belongs to @TestTable:
SELECT
ind.name,type_desc
FROM
tempdb.sys.indexes ind
where ind.object_id=(
SELECT OBJECT_ID FROM tempdb.sys.objects obj WHERE obj.name IN (
SELECT TABLE_NAME FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE (COLUMN_NAME = 'Col1' OR COLUMN_NAME='Col2' OR COLUMN_NAME='Col3')
))
We use many intermediate tables to perform data manipulation, computation, and data sorting from
multiple sources. It is beneficial to use temporary tables instead of a regular table and drop them
later. Usually, we define SQL temporary tables using the # symbol:
Define
Use (Insert, update, delete, select)
Drop
In this article, we will look at an alternative way of storing temporary data, i.e. SQL table variables.
Let’s take an overview of it along with multiple examples.
);
In the above query, we specified a table variable using the DECLARE and TABLE keyword. The table
variable name must start with the @ symbol. We also define table columns, data types, constraint
similar to a regular table.
);
You can retrieve a record from a table variable using the Select statement:
We cannot drop the table variable using the DROP Table statement. If you try to drop it, you get
incorrect syntax message:
We do not require dropping the table variable. As mentioned earlier, the scope of the table variable
is within the batch. The scope of it lasts at the end of the batch or procedure.
Most people are confused about the table variable location and think that it is stored in memory.
Let’s check it out.
We can use sys.tables for listing tables in the tempdb database. Let’s execute the following query
and do the following:
SELECT *
FROM TEMPDB.sys.tables;
GO
DECLARE @Products TABLE
(ProductID INT,
ProductName VARCHAR(30)
);
Go
SELECT *
FROM TEMPDB.sys.tables;
GO
In the output, we did not get any existing table before and after declaring a table variable:
Does it mean that the table variable is not stored in the tempdb database? No, it is not valid. You can
note that we use Go statement after each step to finish the batch before starting the subsequent
batch. Table variable scope finishes at the end of the batch, and SQL Server automatically drops it.
Let’s run the following query. In the modified query, we removed the Go statement after declaring a
table variable and checking the existence of it in the tempdb:
SELECT *
FROM TEMPDB.sys.tables;
GO
DECLARE @Products TABLE
(ProductID INT,
ProductName VARCHAR(30)
);
SELECT *
FROM TEMPDB.sys.tables;
GO
Now, in the output, it shows the table variable in the tempdb database:
Table variable and explicit transaction
We cannot use the table variable in the explicit transaction, it does not return any error message, but
it skips the transaction.
GO
In the output, we can verify that ROLLBACK TRAN did not perform a rollback of data from the table
variable:
If we require explicit transactions, we can use the temporary tables. The explicit transaction works on
temporary tables.
GO
This example showed that we could use table variables in a user-defined function as well. We
cannot use temporary tables inside a user-defined function.
Indexes and table variable
Table variables are a particular type of data types. We can use these table variables similar to the
user table to hold temporary data.
Q: If we cannot define indexes on table variables, do we have any alternatives for it?
A: Yes, indeed, we cannot define index in the table variables, but we can define primary and unique
key constraints on the table variables:
);
We cannot define an explicit clustered and non-clustered index on the table variable. Primary key
and unique key constraints automatically create the internal indexes on it. You can use these
constraints to unique define rows in an index as well.
A: No, we cannot alter a table variable definition after the declaration. Suppose you define a table
variable for holding the Varchar data type of length 50. Later, our requirement changes, and we want
to modify it for length 100.
We cannot alter a table variable structure. We can define another table variable. We can also modify
the definition of an existing table variable.
Conclusion
In this article, we explored the SQL table variables and their usage for storing temporary data. We
also compared it with the temporary tables. Let’s have a quick summary of what we have learned:
Syntax We use the following format for defining a In Table variable, we use the following format:
temporary table:
Define
Define
Use
Drop
User-defined
function We cannot use it in the user-defined functions. We can use table variables in the UDF.
We can define explicit indexes on the We cannot define explicit indexes on table variables. We
Indexes temporary tables. can use primary and unique key constraints.
Scope of a temporary table is local and global Scope of the table variable is within the batch. We cannot
Scope as defined while creating it. use it outside the batch.