问题
I'm trying to populate a temp table based on the result of a condition in SQL 2005. The temp table will have the same structure either way, but will be populated using a different query depending on the condition. The simplified example script below fails in syntax checking of the ELSE
block INSERT INTO
with the error of:
There is already an object named '#MyTestTable' in the database.
DECLARE @Id int
SET @Id = 1
IF OBJECT_ID('tempdb..#MyTestTable') IS NOT NULL DROP TABLE #MyTestTable
IF (@Id = 2) BEGIN
SELECT 'ABC' AS Letters
INTO #MyTestTable;
END ELSE BEGIN
SELECT 'XYZ' AS Letters
INTO #MyTestTable;
END
I could create the temp table before the IF/ELSE
statement and then just do INSERT SELECT
statements in the conditional blocks, but the table will have lots of columns and I was trying to be efficient about it. Is that the only option? Or is there some way to make this work?
Thanks, Matt
回答1:
The problem you’re having is not that you are populating the temp table, but that you’re trying to create the table. SQL parses your script and finds that you are attempting to create it in two different places, and so raises an error. It is not clever enough to realize that the “execution path” cannot possibly hit both of the create statemements. Using dynamic SQL will not work; I tried
DECLARE @Command varchar(500)
DECLARE @Id int
SET @Id = 2
IF OBJECT_ID('tempdb..#MyTestTable') IS NOT NULL DROP TABLE #MyTestTable
IF (@Id = 2) BEGIN
SET @Command = 'SELECT ''ABC'' AS Letters INTO #MyTestTable'
END ELSE BEGIN
SET @Command = 'SELECT ''XYZ'' AS Letters INTO #MyTestTable'
END
EXECUTE (@Command)
select * from #MyTestTable
but the temp table only lasts as long as the dynamic session. So, alas, it looks like you’ll have to first declare the table and then populate it. Awkward code to write and support, perhaps, but it will perform efficiently enough.
回答2:
Answering 8 years late, but I'm surprised nobody thought of:
select * into #MyTempTable from...
where 1=2
IF -- CONDITION HERE
insert into #MyTempTable select...
ELSE
insert into #MyTempTable select...
Simple, quick, and it works. No dynamic sql needed
回答3:
In the scenario you provide you could do this
DECLARE @Id int
SET @Id = 1
IF OBJECT_ID('tempdb..#MyTestTable') IS NOT NULL DROP TABLE #MyTestTable
SELECT
CASE WHEN (@Id = 2)
THEN 'ABC'
ELSE 'XYZ'
END AS Letters
INTO #MyTestTable;
But otherwise you will need to create the table before the if statement
like this
Create Table #MyTestTable (
MyValue varchar(3)
)
IF (@Id = 2) BEGIN
Insert Into (MyValue)
SELECT 'ABC' AS Letters;
END ELSE BEGIN
Insert Into (MyValue)
SELECT 'XYZ' AS Letters;
END
回答4:
Here is a solution which I use if temp table can't be created upfront and don't want to put core logic in dynamic SQL.
IF 1 = 1 -- Replace with actual condition
BEGIN
SELECT * INTO #tmp1 FROM dbo.Table1
END
ELSE
BEGIN
SELECT * INTO #tmp2 FROM dbo.Table2
END
-- Inserting data into global temp table so sql server can't complain on not recognizing in a context
DECLARE @Command VARCHAR(MAX)
IF OBJECT_ID('tempdb..#tmp1') IS NOT NULL
BEGIN
SET @Command = 'SELECT * INTO ##tmp FROM #tmp1'
END
ELSE
BEGIN
SET @Command = 'SELECT * INTO ##tmp FROM #tmp2'
END
EXECUTE(@Command)
SELECT * INTO #tmpFinal FROM ##tmp -- Again passing data back to local temp table from global temp table to avoid seeing red mark
IF OBJECT_ID('tempdb..##tmp') IS NOT NULL DROP TABLE ##tmp
IF OBJECT_ID('tempdb..#tmp1') IS NOT NULL DROP TABLE #tmp1
IF OBJECT_ID('tempdb..#tmp2') IS NOT NULL DROP TABLE #tmp2
SELECT * FROM #tmpFinal
IF OBJECT_ID('tempdb..#tmpFinal') IS NOT NULL DROP TABLE #tmpFinal
回答5:
This is an old issue, but for anyone else coming here:
The dynamic SQL answer given by user Philip Kelley does not work for local temp tables (#Mytemp
). What you can do is create dynamic SQL to insert it into a global temp table (##MyTemp
) which can later be dropped.
DECLARE @Command varchar(500)
DECLARE @Id int
SET @Id = 2
IF OBJECT_ID('tempdb..#MyTestTable') IS NOT NULL DROP TABLE ##MyTestTable
IF (@Id = 2) BEGIN
SET @Command = 'SELECT ''ABC'' AS Letters INTO ##MyTestTable'
END ELSE BEGIN
SET @Command = 'SELECT ''XYZ'' AS Letters INTO ##MyTestTable'
END
EXECUTE (@Command)
select * from ##MyTestTable
DROP ##MyTestTable
回答6:
this code may help you
--creating temptable using columns of two existing tables
--you can create your temp table Using other methods
select top 0 VI.*,VU.FullName
into #mytemptable
from dbo.Items VI inner join
dbo.Users as VU
on VU.Id=VI.Id
--insert your data base on your condition
if(i<2) --First Condition
begin
INSERT INTO #mytemptable
SELECT VI.*,VU.FullName
from dbo.Items VI inner join
dbo.Users as VU
on VU.Id=VI.Id
end
Else if(2<i) --Second Condition
begin
INSERT INTO #mytemptable
SELECT VI.*,VU.FullName
from dbo.Items VI inner join
dbo.Users as VU
on VU.Id=VI.Id
end
select * from #mytemptable --show result
drop table #mytemptable --drop table if its needed
this code works in sql server 2014 i don't know if it works in sql 2005 or not
回答7:
I tried this:
SELECT S1.* INTO #MytestTable
FROM
( SELECT 'ABC' AS Letters WHERE 1 = CASE @Id=2 THEN 1 ELSE 2 END
UNION
SELECT 'XYZ' AS Letters WHERE 1 = CASE @Id=1 THEN 1 ELSE 2 END
) AS S1
This solution is better if later you need to add columns to #MyTestTable, because otherwise you must physically drop it before you re-run your script, which is annoying iin test conditions.
回答8:
You could drop the table before SELECTing INTO it in both cases., e.g.:
DECLARE @Id int
SET @Id = 1
IF (@Id = 2) BEGIN
IF OBJECT_ID('tempdb..#MyTestTable') IS NOT NULL DROP TABLE #MyTestTable
SELECT 'ABC' AS Letters
INTO #MyTestTable;
END ELSE BEGIN
IF OBJECT_ID('tempdb..#MyTestTable') IS NOT NULL DROP TABLE #MyTestTable
SELECT 'XYZ' AS Letters
INTO #MyTestTable;
END
Update After Comment:
That's annoying.
How about two separate temp tables? Then after the If/Else login, check for the existence of each one and if it exists, select into a third temp table? That may not perform great, but whether that matters or not depends on what you need this for.
来源:https://stackoverflow.com/questions/4155996/sql-insert-into-temp-table-in-both-if-and-else-blocks