This article explores the SQL Table variables and their usage using different examples.
Introduction
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:
1 2 3 4 5 6 7 |
CREATE TABLE #temp(DBname VARCHAR(20)); INSERT INTO #temp SELECT name FROM sys.sysdatabases; SELECT * FROM #temp; DROP TABLE #temp; |
A SQL temporary table uses following process.
- 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.
Overview of SQL table variables
The table variable is a special data type that can be used to store temporary data similar to a temporary table. The syntax for the table variable looks similar to defining a new table using the CREATE TABLE statement:
1 2 3 4 |
DECLARE @Products TABLE (ProductID INT, ProductName VARCHAR(30) ); |
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.
Scope of SQL table variable
The table variable scope is within the batch. We can define a table variable inside a stored procedure and function as well. In this case, the table variable scope is within the stored procedure and function. We cannot use it outside the scope of the batch, stored procedure or function.
Insert data into a table variable
We can insert data into a table variable similar to a regular table:
1 2 3 4 5 6 7 8 9 |
DECLARE @Products TABLE (ProductID INT, ProductName VARCHAR(30) ); INSERT INTO @Products VALUES (1, 'Carpet' ); |
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.
The storage location of SQL table variable
Let’s think of a few questions:
- What is the storage location of a table variable?
- Is it created in the source database in which we execute the script?
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:
- Check the existing tables in tempdb
- Declare a table variable
- Check the tables in tempdb again
1 2 3 4 5 6 7 8 9 10 11 |
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:
1 2 3 4 5 6 7 8 9 10 |
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.
In the following query, we execute the query in four steps:
- Declare a table variable
- Starts a transaction using the BEGIN TRAN statement
- Insert record into the table variable
- Rollback transaction using ROLLBACK TRAN
- Verify whether the record exists in the table variable or not. It should not exist because we performed rollback in step 4
1 2 3 4 5 6 7 8 |
DECLARE @TableVariableA TABLE(Name VARCHAR(30)); BEGIN TRAN; INSERT INTO @TableVariableA VALUES('SQL Server'); ROLLBACK TRAN; SELECT * FROM @TableVariableA; 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.
User-defined functions (UDF) and table variable
We can define and use table variables in the user-defined functions as well. Execute the following query:
- Define a user-defined function using CREATE FUNCTION Statement
- Define a table variable and define columns for it
- Define UDF activity in the BEGIN…END statement
- Return the variable value
1 2 3 4 5 6 7 8 9 10 |
CREATE FUNCTION TableVariableWithinAFunction() RETURNS @TableVariable TABLE(Name VARCHAR(50)) AS BEGIN INSERT INTO @TableVariable SELECT FirstName FROM [DemoSQL].[dbo].[Employee]; RETURN; END; GO |
Later, we can use a UDF function to retrieve the records:
1 |
Select * from TableVariableWithinAFunction() |
It retrieves the records from UDF:
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: Is it possible to add indexes on the table variables?
A: No, we cannot define indexes on the table variables.
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:
1 2 3 4 5 |
DECLARE @Customer TABLE (CustomerId INT PRIMARY KEY NONCLUSTERED, CustomerName NVARCHAR(30) UNIQUE CLUSTERED(CustomerName) ); |
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.
Can we modify a SQL table variable structure after declaration?
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:
Temporary table |
SQL table variable |
|||
Syntax |
We use the following format for defining a temporary table:
|
In Table variable, we use the following format:
We cannot drop a table variable using an explicit drop statement. |
||
Storage |
It is stored in the tempdb system database. |
The storage for the table variable is also in the tempdb database. |
||
Transactions |
We can use temporary tables in explicit transactions as well. |
Table variables cannot be used in explicit transactions. |
||
User-defined function |
We cannot use it in the user-defined functions. |
We can use table variables in the UDF. |
||
Indexes |
We can define explicit indexes on the temporary tables. |
We cannot define explicit indexes on table variables. We can use primary and unique key constraints. |
||
Scope |
Scope of a temporary table is local and global as defined while creating it. |
Scope of the table variable is within the batch. We cannot use it outside the batch. |
- Understanding PostgreSQL SUBSTRING function - September 21, 2024
- How to install PostgreSQL on Ubuntu - July 13, 2023
- How to use the CROSSTAB function in PostgreSQL - February 17, 2023