17

我正在尝试根据 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在条件块中执行语句,但是该表将有很多列,我试图提高效率。那是唯一的选择吗?或者有什么方法可以使这项工作?

谢谢,马特

4

9 回答 9

18

回答晚了 8 年,但我很惊讶没有人想到:

select * into #MyTempTable from...
where 1=2

IF -- CONDITION HERE
insert into #MyTempTable select...
ELSE
insert into #MyTempTable select...

简单,快速,并且有效。不需要动态sql

于 2018-02-15T17:46:04.560 回答
14

您遇到的问题不是您正在填充临时表,而是您正在尝试创建该表。SQL 解析您的脚本并发现您正试图在两个不同的位置创建它,因此会引发错误。意识到“执行路径”不可能同时命中两个 create 语句是不够聪明的。使用动态 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

但临时表只持续与动态会话一样长。因此,唉,看来您必须先声明该表,然后再填充它。编写和支持的代码可能很尴尬,但它会足够高效地执行。

于 2010-11-11T19:06:40.777 回答
4

在您提供的场景中,您可以这样做

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
于 2010-11-11T15:27:34.440 回答
2

如果无法预先创建临时表并且不想将核心逻辑放在动态 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
于 2018-12-28T17:01:05.230 回答
1

这是一个老问题,但对于其他来到这里的人来说:

用户 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
于 2017-07-26T09:49:50.913 回答
0

你可以试试这段代码。

IF (CONDITION HERE)
       begin
           select * into #MyTempTable from tablename ....
       end
       ELSE
           truncate table #MyTempTable 
           insert into #MyTempTable 
           select * from tablename ....
       end

谢谢!!!

于 2021-03-18T04:42:10.157 回答
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 添加列,则此解决方案会更好,因为否则您必须在重新运行脚本之前物理删除它,这在测试条件下很烦人。

于 2019-04-26T13:03:13.543 回答
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

于 2018-01-08T11:58:18.473 回答
-1

在这两种情况下,您都可以在 SELECTing 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 登录后,检查每个是否存在,如果存在,则选择第三个临时表?这可能表现不佳,但这是否重要取决于您需要它的目的。

于 2010-11-11T15:29:18.373 回答