В базе данных уже есть объект с именем #columntable - PullRequest
8 голосов
/ 22 ноября 2010

Я пытаюсь выполнить следующий запрос

   if exists (select 1  from emp where eid = 6)     
     begin
        if object_id('tempdb..#columntable') is not null 
          begin 
             drop table #columntable                         
          end                     
        create table #columntable (oldcolumns varchar(100))   
     end
  else
     begin
        if object_id('tempdb..#columntable') is not null 
          begin 
             drop table #columntable            
          end     


    create table #columntable (newcolumns varchar(100))   
 end

Но я получаю сообщение об ошибке

Msg 2714, Level 16, State 1, Line 8
There is already an object named '#columntable' in the database.

Кто-нибудь может подсказать почему?Тот же запрос работает нормально, если я не напишу остальную часть.

Ответы [ 7 ]

7 голосов
/ 29 августа 2014

К сожалению, это ошибка синтаксического анализатора SQL Server ( подтверждено Microsoft ).

@ DizGrizz также прав - SELECT .. INTO #SomeTable не работает, если повторяется в IF .. ELSE заявлениях.

ЕСЛИ .. ДАЛЕЕ .. СОЗДАТЬ ТАБЛИЦУ # SomeTempTable

В ответ на актуальный вопрос работает создание и изменение таблицы (вам также нужно только один раз проверить и удалить) ...

IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL
BEGIN 
     DROP TABLE #MyTempTable
END  

CREATE TABLE #MyTempTable (DummyColumn BIT)

IF EXISTS (SELECT 1 FROM EMP WHERE EID = 6)     
    BEGIN
        ALTER TABLE #MyTempTable
        ADD MyColumnType1 VARCHAR(100)

        ALTER TABLE #MyTempTable
        DROP COLUMN DummyColumn
    END
ELSE
    BEGIN
        ALTER TABLE #MyTempTable 
        ADD MyColumnType2 VARCHAR(100)

        ALTER TABLE #MyTempTable
        DROP COLUMN DummyColumn
    END

ЕСЛИ .. ДАЛЕЕ .. ВЫБРАТЬ В # SomeTempTable

Проблема, с которой я столкнулся, была такой же, как у @DizGrizz: IF .. ELSE в сочетании с SELECT .. INTO #SomeTable не удалась.В качестве обходного пути можно выбрать верхние 0 строк (т.е. ни одной), чтобы создать таблицу с правильными типами столбцов.(Это изолирует скрипт от изменений типа столбца, а также избавляет от необходимости объявлять каждый тип.) Затем можно использовать INSERT INTO при условии, что IDENTITY_INSERT установлен на ON для предотвращения ошибок:

IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL
    DROP TABLE #MyTempTable

-- This creates the table, but avoids having to declare any column types or sizes
SELECT TOP 0 KeyNm
INTO #MyTempTable
FROM dbo.MyDataTable2

-- Required to prevent IDENTITY_INSERT error
SET IDENTITY_INSERT #MyTempTable ON

IF @something = 1
    BEGIN
        -- Insert the actual rows required into the (currently empty) temp table
        INSERT INTO #MyTempTable (KeyNm)
        SELECT KeyNm
        FROM dbo.MyDataTable2
        WHERE CatNum = 2
    END
ELSE
    BEGIN
        -- Insert the actual rows required into the temp table
        INSERT INTO #MyTempTable (KeyNm)
        SELECT KeyNm
        FROM dbo.MyDataTable2
        WHERE CatNum = 8
    END

SET IDENTITY_INSERT #MyTempTable OFF
6 голосов
/ 22 ноября 2010

Временные таблицы не удаляются автоматически в конце запроса, только когда текущее соединение с БД сброшено или вы явно удалили их с помощью DROP TABLE #columntable

Либо проверить наличие таблицы в начале запроса, либо всегда удалить ее в конце (предпочтительно обе)

РЕДАКТИРОВАТЬ: Как сказал Матрин в своем комментарии, это на самом деле ошибка разбора. Вы получаете ту же ошибку, если анализируете только SQL, как при его выполнении.

Чтобы проверить это, я разделил ваш запрос и попытался:

if exists (select 1 from emp where id = 6)
  create table #columntable (newcolumns varchar(100))
GO
if not exists (select 1 from emp where id = 6)
  create table #columntable (oldcolumns varchar(100))
GO

Парсер доволен этим. Интересно, что если вы перейдете на использование не временных таблиц, исходный запрос будет в порядке (я понимаю, какие проблемы могут возникнуть, мне просто было интересно узнать, почему запрос не будет анализироваться).

2 голосов
/ 11 октября 2011

Это также происходит, если вы создаете таблицы с помощью SELECT INTO ... как в

IF OBJECT_ID('tempdb..#MyTempTable', 'U') IS NOT NULL
    DROP TABLE #MyTempTable
SELECT TOP 1 @MyVariable = ScaleValue
    FROM MyDataTable1
    WHERE ProductWeight > 1000
IF @MyVariable = 1
BEGIN
    SELECT KeyNm
        INTO #MyTempTable
        FROM dbo.MyDataTable2
        WHERE CatNum = 2
END
ELSE
BEGIN
    SELECT KeyNm
        INTO #MyTempTable
        FROM dbo.MyDataTable2
        WHERE CatNum = 8
END

. Парсер не должен даже пытаться обнаружить это, поскольку во многих случаях это будет невозможно для парсераопределить, существует ли таблица уже.Приведенный выше код является идеальным примером ... для парсера не будет возможности определить значение @MyVariable.Я надеюсь, что кто-то сообщил MS об этой ошибке (у меня нет их уха).

1 голос
/ 19 апреля 2013

Используйте глобальные временные таблицы и переносите выбор в exec.

Пример:

Fail

declare @a int = 1
if object_id('tempdb..##temp') is not null drop table ##temp
if(@a = 1) select * into ##temp from table_1
else if(@a = 2) select * into ##temp from table_2

Win

declare @a int = 1
if object_id('tempdb..##temp') is not null drop table ##temp
if(@a = 1) exec('select * into ##temp from table_1')
else if(@a = 2) exec('select * into ##temp from table_2')

Это будетобмануть паршивый парсер, который пытается быть умнее, чем есть.И Microsoft - пожалуйста, исправьте это.

1 голос
/ 22 ноября 2010

Вы можете проверить, существует ли он, выполнив:

IF OBJECT_ID('tempdb..#columntable') IS NOT NULL
BEGIN
DROP TABLE #columntable
PRINT 'Dropped table...'
END
0 голосов
/ 22 ноября 2010

Ну, я получил ответ ... Как сказал Мартин, это проблема разбора / компиляции. Поэтому я попытался изменить свой сценарий, как показано ниже

  if exists (select 1  from emp where eid = 6)     
     begin
        if object_id('tempdb..#columntable') is not null 
          begin 
             drop table #columntable                         
          end                     
        create table #columntable (oldcolumns varchar(100))   
     end
  go
 if exists (select 1  from emp where eid = 1)   
     begin
        if object_id('tempdb..#columntable') is not null 
          begin 
             drop table #columntable            
          end         
        create table #columntable (newcolumns varchar(100))   
     end

И это сработало для меня.

0 голосов
/ 22 ноября 2010

Ошибка неправильная, удалите условие if, и оно проходит нормально. Таким образом, проблема в существовании:

if object_id('tempdb..#columntable') is not null
begin
    drop table #columntable
end 

create table #columntable (oldcolumns varchar(100))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...