我正在尝试根据SQL 2005中的条件结果填充临时表。临时表将具有相同的结构,但将根据条件使用不同的查询填充。下面的简化示例脚本在ELSE
块INSERT INTO
的语法检查中失败,错误为:
已经有一个名为的对象 数据库中的“#MyTestTable”。
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
我可以在IF/ELSE
语句之前创建临时表,然后只在条件块中执行INSERT SELECT
语句,但是表中会有很多列,我试图提高效率。这是唯一的选择吗?或者有什么方法可以使这项工作?
谢谢, 马特
答案 0 :(得分:8)
您遇到的问题不是您正在填充临时表,而是您正在尝试创建表。 SQL会解析您的脚本并发现您尝试在两个不同的位置创建它,因此会引发错误。要意识到“执行路径”不可能同时触及两个创建状态,这并不够聪明。使用动态SQL将无法正常工作;我试过了
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
但临时表只持续动态会话。所以,唉,看起来你必须首先声明表然后填充它。也许是编写和支持的笨拙代码,但它会足够有效地执行。
答案 1 :(得分:5)
迟到了8年,但我没有想到会这么惊讶:
select * into #MyTempTable from...
where 1=2
IF -- CONDITION HERE
insert into #MyTempTable select...
ELSE
insert into #MyTempTable select...
简单,快捷,有效。不需要动态sql
答案 2 :(得分:3)
在您提供的方案中,您可以执行此操作
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;
但是否则您需要在if statement
之前创建表格
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
答案 3 :(得分:1)
这是一个解决方案,如果无法提前创建临时表并且不想将核心逻辑放入动态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
答案 4 :(得分:0)
这是一个老问题,但对于其他任何人来到这里:
用户Philip Kelley提供的动态SQL答案不适用于本地临时表(#Mytemp
)。您可以做的是创建动态SQL以将其插入到全局临时表(##MyTemp
)中,以后可以将其删除。
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
答案 5 :(得分:0)
此代码可以帮助您
--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
此代码适用于sql server 2014 我不知道它是否在sql 2005中工作
答案 6 :(得分:0)
我尝试过:
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
如果以后需要将列添加到#MyTestTable中,则此解决方案会更好,因为否则必须在重新运行脚本之前物理上将其删除,这是令人讨厌的测试条件。
答案 7 :(得分:0)
你可以试试这个代码。
IF (CONDITION HERE)
begin
select * into #MyTempTable from tablename ....
end
ELSE
truncate table #MyTempTable
insert into #MyTempTable
select * from tablename ....
end
谢谢!!!
答案 8 :(得分:-1)
在两种情况下,您可以在选择INTO之前删除表格,例如:
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
评论后更新:
这很烦人。
两个单独的临时表怎么样?然后在If / Else登录后,检查每个是否存在,如果存在,选择第三个临时表?这可能不会很好,但是否重要取决于你需要什么。