Вставка SQL в временную таблицу в блоках If и Else - PullRequest
12 голосов
/ 11 ноября 2010

Я пытаюсь заполнить временную таблицу на основе результата условия в 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 в условных блоках, но в таблице будет много столбцов, и я пытался с этим справиться. Это единственный вариант? Или есть какой-нибудь способ заставить это работать?

Спасибо, Matt

Ответы [ 8 ]

9 голосов
/ 11 ноября 2010

Проблема в том, что вы заполняете временную таблицу, а пытаетесь создать таблицу.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

, но временная таблица длится столько времени, сколько динамический сеанс.Так что, увы, похоже, что вам нужно сначала объявить таблицу, а затем заполнить ее.Возможно, неудобный код для написания и поддержки, но он будет работать достаточно эффективно.

5 голосов
/ 15 февраля 2018

Отвечая на 8 лет позже, но я удивлен, что никто не подумал:

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

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

Просто, быстро, и это работает.Динамический sql не требуется

3 голосов
/ 11 ноября 2010

В предоставленном вами сценарии вы можете сделать это

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
1 голос
/ 28 декабря 2018

Вот решение, которое я использую, если временная таблица не может быть создана заранее и не хочет помещать основную логику в динамический 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
0 голосов
/ 26 апреля 2019

Я попробовал это:

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, потому что в противном случае вы должны физически отбросить его, прежде чем перезапустить сценарий, что раздражает iinусловия испытаний.

0 голосов
/ 08 января 2018

этот код может вам помочь

--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 или нет

0 голосов
/ 26 июля 2017

Это старая проблема, но для всех, кто сюда заходит:

Динамический ответ 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
0 голосов
/ 11 ноября 2010

Вы можете сбросить таблицу, прежде чем ВЫБРАТЬ В нее в обоих случаях. Например ::100100

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 проверьте наличие каждого из них и, если оно существует, выберите в третью временную таблицу? Это может не очень хорошо работать, но имеет значение, зависит это от того, для чего вам это нужно.

...