338

I have the following code in one of my Sql (2008) Stored Procs which executes perfectly fine:

    CREATE PROCEDURE [dbo].[Item_AddItem]
        @CustomerId uniqueidentifier,
        @Description nvarchar(100),
        @Type int,
        @Username nvarchar(100),
    AS
    BEGIN

        DECLARE @TopRelatedItemId uniqueidentifier;
        SET @TopRelatedItemId = 
        (
           SELECT top(1) RelatedItemId 
           FROM RelatedItems 
           WHERE CustomerId = @CustomerId
        ) 

        DECLARE @TempItem TABLE
        (
            ItemId uniqueidentifier,
            CustomerId uniqueidentifier,
            Description nvarchar(100),
            Type int,
            Username nvarchar(100),
            TimeStamp datetime
        );

        INSERT INTO Item
        OUTPUT INSERTED.* INTO @TempItem
        SELECT NEWID(), @CustomerId, @Description, @Type, @Username, GETDATE()

        SELECT
            ItemId,
            CustomerId,
            @TopRelatedItemId,
            Description,
            Type,
            Username,
            TimeStamp
        FROM
            @TempItem
END
GO

So the question for you guys is is there a possibility to do something along the lines of:

DECLARE @TempCustomer TABLE
(
   CustomerId uniqueidentifier,
   FirstName nvarchar(100),
   LastName nvarchar(100),
   Email nvarchar(100)
);
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
INTO 
    @TempCustomer 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId

So that I could reuse this data from memory in other following statements? SQL Server throws a fit with the above statement, however i don't want to have to create separate variables and initialize each one of them via a separate SELECT statement against the same table.... UGH!!!

Any suggestions on how to achieve something along the lines without multiple queries against the same table?

2
  • 1
    "to create separate variables and initialize each one of them via a separate SELECT statement" - why would you need to do that? declare @t table once, and if you need to reuse it, fire a DELETE @TempCustomer before inserting into it again Commented Jan 28, 2011 at 1:40
  • You can use the Table Variable - mssqltips.com/sqlservertip/6039/…
    – AquaAlex
    Commented Feb 25, 2022 at 8:30

7 Answers 7

652

If you wanted to simply assign some variables for later use, you can do them in one shot with something along these lines:

declare @var1 int,@var2 int,@var3 int;

select 
    @var1 = field1,
    @var2 = field2,
    @var3 = field3
from
    table
where
    condition

If that's the type of thing you're after

6
  • 2
    Best answer imho, but what happens if the results are more than one? Commented Feb 17, 2016 at 10:25
  • If the results are more than one, you will get one of the available values. That could make for an interesting puzzle! See mssqltips.com/sqlservertip/1888/…
    – Smandoli
    Commented Feb 24, 2016 at 18:01
  • 18
    To force the query to return a single row use SELECT TOP 1
    – Adrian
    Commented Aug 11, 2016 at 21:43
  • 1
    @Adrian Yes, the above query assumes you've selected a single row. You could also use ordering and aggregate functions if you want more fancy logic. Commented Mar 21, 2017 at 8:16
  • 1
    In case if you aren't using the database type that the OP is using, not all support TOP 1 as Adrian mentioned. SQL Server / MS Access use TOP, MySQL uses LIMIT, and Oracle uses ROWNUM. See w3schools.com/sql/sql_top.asp for more information.
    – Tyler
    Commented Jul 7, 2017 at 12:08
246

You cannot SELECT .. INTO .. a TABLE VARIABLE. The best you can do is create it first, then insert into it. Your 2nd snippet has to be

DECLARE @TempCustomer TABLE
(
   CustomerId uniqueidentifier,
   FirstName nvarchar(100),
   LastName nvarchar(100),
   Email nvarchar(100)
);
INSERT INTO 
    @TempCustomer 
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId
3
  • 5
    Should note that this works just fine in a CTE context as well. Bazinga! Commented Dec 20, 2011 at 22:23
  • 5
    Anyone have an answer as to why one cannot select into a table variable like you can with an actual temporary table?
    – KSwift87
    Commented Jun 30, 2016 at 17:15
  • Why it's not possible? Probably to prevent the possibility of blowing up your database server with out of memory exception. The DB server needs to be a very stable process... Commented Feb 7, 2022 at 10:30
45

You can do this:

SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email
INTO #tempCustomer 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId

then later

SELECT CustomerId FROM #tempCustomer

you don't need to declare the structure of #tempCustomer

3
  • 3
    @webturner Neither of those points are true. Temp tables aren't scoped outside of the proc and table variables aren't any more "memory only" than temp tables. Commented Apr 14, 2014 at 23:45
  • 9
    Don't forget to add a DROP TABLE #tempCustomer when #tempCustomer is not needed anymore otherwise the next select will cause a #tempCustomer already exists error Commented May 19, 2016 at 11:46
  • @ViRuSTriNiTy It is only visible to the current session. Once the session ends or the connection is terminated, this table is automatically dropped. Commented Sep 18, 2023 at 8:21
21

It looks like your syntax is slightly out. This has some good examples

DECLARE @TempCustomer TABLE
(
   CustomerId uniqueidentifier,
   FirstName nvarchar(100),
   LastName nvarchar(100),
   Email nvarchar(100)
);
INSERT @TempCustomer 
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId

Then later

SELECT CustomerId FROM @TempCustomer
1
  • 2
    Due to a redirect from dbforums, that "good examples" link has transformed into an ad. Is there a better link for what you intended?
    – r2evans
    Commented Jul 2, 2020 at 16:54
4

Sounds like you want temp tables. http://www.sqlteam.com/article/temporary-tables

Note that #TempTable is available throughout your SP.

Note the ##TempTable is available to all.

4
  • 2
    ##temptable - until the owner(creator) deletes it or gets disconnected Commented Jan 28, 2011 at 1:38
  • 4
    I don't want temp tables. Temp tables are expensive and slow. I just want to keep a bit of data for a specific record for a small amount of time and make it available to multiple sql statements, without subsequent lookups. Since Table Variables have scope within the stored proc they were defined in, they are the perfect solution for storing tuppled data for that one stored proc call...
    – bleepzter
    Commented Jan 28, 2011 at 1:48
  • 3
    I also forgot to mention that the DB resides in Azure.... I don't want to introduce a mess out of managing temp tables.
    – bleepzter
    Commented Jan 28, 2011 at 1:49
  • Variable table is the way to go. declare @varTable Table (....) Commented Apr 15, 2020 at 19:53
3

I found your question looking for a solution to the same problem; and what other answers fail to point is a way to use a variable to change the name of the table for every execution of your procedure in a permanent form, not temporary.

So far what I do is concatenate the entire SQL code with the variables to use. Like this:

declare @table_name as varchar(30)
select @table_name = CONVERT(varchar(30), getdate(), 112)
set @table_name = 'DAILY_SNAPSHOT_' + @table_name

EXEC('
        SELECT var1, var2, var3
        INTO '+@table_name+'
        FROM my_view
        WHERE string = ''Strings must use double apostrophe''
    ');

I hope it helps, but it could be cumbersome if the code is too large, so if you've found a better way, please share!

0
-2
"SELECT *
  INTO 
    @TempCustomer 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId"

Which means creating a new @tempCustomer tablevariable and inserting data FROM Customer. You had already declared it above so no need of again declaring. Better to go with

INSERT INTO @tempCustomer SELECT * FROM Customer
1
  • 4
    It doesn't work. You still need to declare the table variable beforehand. Commented Dec 8, 2016 at 8:23

Not the answer you're looking for? Browse other questions tagged or ask your own question.