임시 테이블을 작성하기 전에 임시 테이블이 있는지 확인하고 존재하는 경우 삭제하십시오.


662

다음 코드를 사용하여 임시 테이블이 있는지 확인하고 테이블을 다시 만들기 전에 테이블을 삭제하십시오. 열을 변경하지 않는 한 제대로 작동합니다. 나중에 열을 추가하면 "잘못된 열"이라는 오류가 발생합니다. 내가 뭘 잘못하고 있는지 알려주세요.

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

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
)

select company, stepid, fieldid from #Results

--Works fine to this point

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

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
    NewColumn            NVARCHAR(50)
)

select company, stepid, fieldid, NewColumn from #Results

--Does not work

열을 어디에 추가합니까? 오류가 발생하는 정확한 코드를 게시 할 수 있습니까?
Macros

#Results 테이블에 열을 추가하고 있습니다. 위의 코드를 복사하여 처음 실행하면 오류가 발생하지 않습니다. 이제 임시 테이블에 열을 추가하고 select 문에 열을 추가하면 열을 찾을 수 없습니다 (또는 이와 유사한 것)가 표시됩니다.
Sridhar

22
다음 패턴 사용을 고려하십시오 BEGIN TRANSACTION; CREATE TABLE #Results; ...; DROP TABLE #Results; COMMIT.. 트랜잭션이 성공하면 테이블이 제거됩니다. 실패하면 테이블이 트랜잭션 내에서 작성되었으므로 사라집니다. 어쨌든 : 테이블이 이미 존재하는지 확인할 필요가 없습니다.
Heinzi

1
GO 문만 필요한 것 같습니다.
sam yi

답변:


733

오류를 재현 할 수 없습니다.

아마도 문제를 이해하지 못했을 것입니다.

다음은 SQL Server 2005에서 두 번째 선택 결과에 추가 "foo"열이 표시되어 제대로 작동하는 것입니다.

IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results
GO
CREATE TABLE #Results ( Company CHAR(3), StepId TINYINT, FieldId TINYINT )
GO
select company, stepid, fieldid from #Results
GO
ALTER TABLE #Results ADD foo VARCHAR(50) NULL
GO
select company, stepid, fieldid, foo from #Results
GO
IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results
GO

1
OBJECT_ID ( 'tempdb .. # Results')가 NULL이 아닌 경우 DROP TABLE # Results` CREATE TABLE #Results (회사 CHAR (3), StepId INT) 회사 선택, #results의 stepid는 이제 create 문으로 돌아가서 fieldid를 포함하고 실행하려면 end.change select 문에 fieldfieldid를 입력하십시오.
Sridhar

28
'tempdb..#name'정확히 내가 필요한 것입니다. 'dbo.#name'바보처럼 을 사용 하고 있었습니다 . 나는 tempdb부분을 얻지 만 이중 점은 무엇입니까?
Conrad.Dean

77
@ Conrad.Dean 이중 점은 .dbo의 약어입니다.
deutschZuid 2016 년

32
@deutschZuid 더블 도트는 일반적으로 dbo 인 사용자의 기본 스키마라고 말하는 것이 더 정확합니다 (dbo는 좋은 아이디어는 아니지만 dbo를 사용자의 기본 스키마로 설정하지만 일반적으로 진행되는 방식 임)
jcollum

8
코드가 OP와 매우 다르기 때문에 '재생할 수 없습니다'라는 문구는 의미가 없습니다. 다른 방식으로 작동하게되어 기쁩니다.
Gerard ONeill

85

진술서는 순서대로 이루어져야한다

  1. 테이블 변경 문
  2. 가다
  3. 문장을 선택하십시오.

사이에 'GO'가 없으면 전체가 하나의 단일 스크립트로 간주되며 select 문이 열을 찾을 때 찾을 수 없습니다.

'GO'를 사용하면 스크립트의 일부를 'GO'까지 단일 배치로 간주하여 'GO'이후 쿼리에 들어가기 전에 실행됩니다.


7
정답으로 표시해야합니다. SELECT 테이블이 실제로 create 테이블보다 먼저 실행되는 것은 아닙니다. 아직 필드 ID 열이없는 #Results라는 기존 테이블이 있기 때문에 구문 분석 및 실행 전에 오류가 발생하는 것입니다. select 문이 구문 분석되는 시간. 거기에 GO를 추가하면 쿼리가 일괄 처리로 구분되며 각 쿼리는 개별적으로 구문 분석 및 실행됩니다.
Davos

2
나는이 답변과 최고 답변 사이의 투표 차이가 있다고 생각할 수 없다.
underscore_d

63

dropping임시 테이블을 재생성 하는 대신 truncate재사용 할 수 있습니다.

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    Truncate TABLE #Results
else
    CREATE TABLE #Results
    (
        Company             CHAR(3),
        StepId              TINYINT,
        FieldId             TINYINT,
    )

사용 Sql Server 2016하거나 Azure Sql Database다음 구문을 사용하여 임시 테이블을 삭제하고 다시 작성하십시오. 자세한 내용은 여기 MSDN

통사론

DROP TABLE [존재하는 경우] [database_name. [schema_name]. | schema_name ] table_name [, ... n]

질문:

DROP TABLE IF EXISTS tempdb.dbo.#Results
CREATE TABLE #Results
  (
   Company             CHAR(3),
   StepId              TINYINT,
   FieldId             TINYINT,
  )

보이는 truncate/reuse방법은보다 더 효율적인 것 DROP TABLE IF EXISTSSql Server 2016Azure Sql Database뿐만 아니라. 그렇지 않습니까?
JDawg

@prdp DROP TABLE IF ExistsSQL 2016 또는 Azure 를 제안 하는 이유는 무엇 입니까? 이 구문은 SQL 2008부터 사용할 수 있습니다. 답변에서 MSDN 링크를 참조하십시오. 성능 계수?
HappyTown 2012

4
신경 쓰지 마. 이제 DROP TABLESQL Server 2008에서 지원되지만이 IF EXISTS조항은 2016 년에 도입되었습니다.
HappyTown

1
나는 사용 INTO: select * INTO # dbo.HistoricoUser에서 #HistoricoUserTable
Kiquenet

54

문제는 실행을 배치로 분리하기 위해 사이에 GO 문을 추가해야한다고 생각합니다. 두 번째 삭제 스크립트로 즉 IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results, 임시 테이블을 단일 배치의 일부로 삭제하지 않았습니다. 아래 스크립트를 사용해보십시오.

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

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
)

GO

select company, stepid, fieldid from #Results

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

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
    NewColumn            NVARCHAR(50)
)

GO

select company, stepid, fieldid, NewColumn from #Results

1
참고로; tempdb..위의 코드에서 매우 중요합니다. 임시 테이블 이름 앞에 와야합니다. 단순히 확인하는 것만으로 OBJECT_ID('#Results')는 충분하지 않습니다. 임시 테이블은 TempDB 데이터베이스에 저장됩니다. 마이크로 소프트 당 : 임시 데이터베이스 시스템 데이터베이스는 SQL Server 인스턴스에 연결 또는 SQL 데이터베이스에 연결된 모든 사용자가 사용할 수있는 글로벌 자원이다
ICODE

감사합니다, @iCode. 그것이 임시 테이블을 삭제하는 열쇠입니다. 수행해야 tempdb하거나 사라지지 않을 것입니다.
Alex

37

이는 한 줄의 코드로 수행 할 수 있습니다.

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

1
나는 이것을 매일 봐야한다
Ab Bennett

28

이것은 나를 위해 일했다 : social.msdn.microsoft.com/Forums/en/transactsql/thread/02c6da90-954d-487d-a823-e24b891ec1b0?prof= 필수

if exists (
    select  * from tempdb.dbo.sysobjects o
    where o.xtype in ('U') 

   and o.id = object_id(N'tempdb..#tempTable')
)
DROP TABLE #tempTable;

1
이것은 조건부 테이블 삭제에 대한 다른 구문입니다. 흥미롭지 만 OP의 문제를 해결하지 못하며 대부분 중복됩니다. OBJECT_ID (N'tempdb .. # Results ')가 null이 아닌지 확인하면 객체가 이미 존재한다는 것을 증명하기에 충분합니다.
Davos

21

OBJECT_ID나를 위해 작동하지 않기 때문에 내 측면에서 약간의 의견 . 항상

`#tempTable이 존재하지 않습니다

그것이 비록 ..even 않습니다 존재합니다. 방금 다른 이름 ( _밑줄로 접두사)이 저장되어 있음을 알았습니다 .

#tempTable________

이것은 나를 위해 잘 작동합니다 :

IF EXISTS(SELECT [name] FROM tempdb.sys.tables WHERE [name] like '#tempTable%') BEGIN
   DROP TABLE #tempTable;
END;

6
주의 : 해당 코드는 스레드에 의해 작성된 테이블을 감지합니다. 단일 # 임시 테이블은 저장된 proc에 대한 스레드 / 호출자마다 개별적으로 작성되므로 스레드 / 프로세스마다 다른 사본이 존재하도록 이름에 밑줄이 표시됩니다. Object_ID는 SQL 2005 이상에있는 한 현재 스레드에서 정상적으로 작동합니다.
Bytemaster

12

이제 새 버전의 SQL Server (2016+) 중 하나를 사용하는 경우 아래 구문을 사용할 수 있습니다.

DROP TABLE IF EXISTS schema.yourtable(even temporary tables #...)

1
SSMS 17.3을 사용하고 있습니다.Incorrect syntax near the keyword 'IF'.
StingyJack

7
@StingyJack SQL 구문은 SSMS 버전과 관련이 없지만 SQL Server 버전과 관련이 있기 때문입니다. 이 IF [NOT] EXISTS절은 SQL Server 2016에서 사용할 수 있습니다. 사용중인 SSMS 버전은 중요하지 않습니다.
Pred

10

pmac72 는 GO를 사용하여 쿼리를 배치로 나누고 ALTER를 사용합니다.

동일한 배치를 실행하고 있지만 변경 후 두 번 실행하는 것 같습니다 : DROP ... CREATE ... 편집 ... DROP ... CREATE ..

정확한 코드를 게시하여 진행 상황을 확인할 수 있습니다.


7

임시 테이블을 이미 만들었을 때 일반적으로이 오류가 발생했습니다. SQL 문에서 오류를 점검하는 코드는 "오래된"임시 테이블을 제자리에두고 임시 테이블이 삭제되지 않은 것처럼 이후 명령문의 열 수에 대해 잘못된 수를 리턴합니다.

열 수가 적은 버전을 이미 만든 후 임시 테이블의 열 수를 변경 한 후 테이블을 삭제하면 쿼리가 실행됩니다.


6

나는 최근 DBA가 이와 비슷한 것을 보았습니다.

begin try
    drop table #temp
end try

begin catch 
    print 'table does not exist'
end catch 

create table #temp(a int, b int)

2
이 try 문은 테이블을 삭제하려고 할 때 발생할 수있는 다른 오류를 포착합니다. 이 코드는 시도가 실패하는 유일한 이유는 테이블이 존재하지 않기 때문이라고 가정합니다. 아마 대부분의 시간 동안 작동하지만 보장하지는 않습니다. 다른 이유로 try 문이 실패하면 테이블을 삭제할 때 실제 문제를 숨 겼기 때문에 테이블을 만들 때 오류가 발생합니다.
Davos

이것은 효과가 있지만 나쁘고 똑똑하고 완벽한 솔루션이있을 때 어려운 방법을 권장하지 않습니다. 또한 OP에서 2005 버전을 지정했지만 try catch 블록은 이전 버전에서 지원되지 않습니다.
dejjub-AIS

이것에 대한 다른 문제는 try / catch vs logic을 사용하는 이념입니다. 여기에서 더 많은 토론을 볼 수 있습니다. stackoverflow.com/questions/17335217/try-catch-or-if-statement/…
logixologist

3

내 코드는 Source변경되는 Destination테이블과 해당 변경 사항과 일치해야하는 테이블을 사용합니다.

-- 
-- Sample SQL to update only rows in a "Destination" Table
--  based on only rows that have changed in a "Source" table
--


--
-- Drop and Create a Temp Table to use as the "Source" Table
--
IF OBJECT_ID('tempdb..#tSource') IS NOT NULL drop table #tSource
create table #tSource (Col1 int, Col2 int, Col3 int, Col4 int)

--
-- Insert some values into the source
--
Insert #tSource (Col1, Col2, Col3, Col4) Values(1,1,1,1)
Insert #tSource (Col1, Col2, Col3, Col4) Values(2,1,1,2)
Insert #tSource (Col1, Col2, Col3, Col4) Values(3,1,1,3)
Insert #tSource (Col1, Col2, Col3, Col4) Values(4,1,1,4)
Insert #tSource (Col1, Col2, Col3, Col4) Values(5,1,1,5)
Insert #tSource (Col1, Col2, Col3, Col4) Values(6,1,1,6)

--
-- Drop and Create a Temp Table to use as the "Destination" Table
--
IF OBJECT_ID('tempdb..#tDest') IS NOT NULL drop Table #tDest
create table #tDest (Col1 int, Col2 int, Col3 int, Col4 int)

--
-- Add all Rows from the Source to the Destination
--
Insert #tDest
Select Col1, Col2, Col3, Col4 from #tSource


--
-- Look at both tables to see that they are the same
--
select *
from #tSource
Select *
from #tDest

--
-- Make some changes to the Source
--
update #tSource
    Set Col3=19
    Where Col1=1
update #tSource
    Set Col3=29
    Where Col1=2
update #tSource
    Set Col2=38
    Where Col1=3
update #tSource
    Set Col2=48
    Where Col1=4

--
-- Look at the Differences
-- Note: Only 4 rows are different. 2 Rows have remained the same.
--
Select Col1, Col2, Col3, Col4
from #tSource
except
Select Col1, Col2, Col3, Col4
from #tDest

--
-- Update only the rows that have changed
-- Note: I am using Col1 like an ID column
--
Update #tDest
    Set Col2=S.Col2,
        Col3=S.Col3,
        Col4=S.Col4
From    (   Select Col1, Col2, Col3, Col4
            from #tSource
            except
            Select Col1, Col2, Col3, Col4
            from #tDest
        ) S
Where #tDest.Col1=S.Col1 

--
-- Look at the tables again to see that
--  the destination table has changed to match
--  the source table.

select *
from #tSource
Select *
from #tDest

--
-- Clean Up
--
drop table #tSource
drop table #tDest

1

예, "잘못된 열"이 오류는 "Select companies, stepid, fieldid, #Results의 NewColumn"줄에서 발생합니다.

t-sql 실행에는 두 단계가 있습니다.

먼저,이 단계에서 SQL Server는 구문 분석하여 테이블 열을 포함하여 제출 한 SQL 문자열의 정정을 확인하고 가장 빠른 검색을 위해 쿼리를 최적화합니다.

둘째, 실행 중이며 데이터를 검색하는 중입니다.

테이블 #Results가 있으면 구문 분석 프로세스에서 지정한 열이 유효한지 확인하고, 그렇지 않은 경우 (테이블이 존재하지 않음) 구문 분석은 지정한대로 확인 열을 전달합니다.


0

임시 테이블에서 열을 변경하면 쿼리를 다시 실행하기 전에 테이블을 삭제해야합니다. (예, 성가신 일입니다.해야 할 일입니다.)

필자는 이것이 항상 쿼리가 실행되기 전에 파서가 "잘못된 열"검사를 수행하기 때문에 테이블이 삭제되기 전에 테이블의 열을 기반으로하기 때문이라고 가정했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.