Geçici bir tablo olup olmadığını kontrol edin ve geçici bir tablo oluşturmadan önce varsa silin


663

Geçici tablo olup olmadığını kontrol etmek için aşağıdaki kodu kullanıyorum ve yeniden oluşturmadan önce varsa tablo bırakın. Sütunları değiştirmediğim sürece iyi çalışıyor. Daha sonra bir sütun eklersem, "geçersiz sütun" diyerek bir hata verir. Lütfen neyi yanlış yaptığımı bildirin.

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

Sütunu nereye ekliyorsunuz? size hata veren kodu tam olarak gönderebilir misiniz?
Makrolar

#Results tablosuna sütun ekliyorum. Yukarıdaki kodu kopyalar ve ilk kez çalıştırırsanız herhangi bir hata almazsınız. Şimdi geçici tabloya bir sütun ekler ve select deyimine sütun eklerseniz, sütun bulunamadı (ya da bunun gibi bir şey) söyleyecektir.
Sridhar

22
Aşağıdaki desen kullanmayı düşünün: BEGIN TRANSACTION; CREATE TABLE #Results; ...; DROP TABLE #Results; COMMIT. İşlem başarılı olursa, tablo kaldırılır. Başarısız olursa, tablo da (işlem içinde oluşturulduğundan beri) gider. Her durumda: Tablonun zaten var olup olmadığını kontrol etmeye gerek yoktur.
Heinzi

1
Görünüşe göre sadece GO ifadelerine ihtiyacınız var.
sam yi

Yanıtlar:


734

Hatayı yeniden oluşturamıyorum.

Belki de sorunu anlamıyorum.

SQL Server 2005'te benim için iyi çalışıyor, ikinci seçme sonucunda fazladan "foo" sütunu görünüyor:

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') BOŞ DEĞİLSE TABLO # Results` CREATE TABLE #Results (Şirket CHAR (3), StepId INT) şirket seçin, #results'tan stepid şimdi create deyimine geri dönün ve ekleyin fieldid öğesini eklemek ve çalıştırmak için end.change select deyimindeki sütun fieldid.
Sridhar

28
'tempdb..#name'tam da ihtiyacım olan şey. 'dbo.#name'Bir aptal gibi kullanıyordum . Rolü anladım tempdb, ama çift nokta ne olacak?
Conrad.Dean

77
@ Conrad.Dean çift nokta .dbo için bir kısaltmadır.
deutschZuid

32
@deutschZuid, çift noktanın kullanıcının varsayılan şeması olduğunu söylemek daha doğrudur, bu genellikle dbo (bu harika bir fikir değildir,
dbo'yu

8
Kodunuz OP'den o kadar farklı ki 'çoğaltılamıyor' ifadeniz anlamsız. Farklı bir şekilde çalışmasını sağladığınız için mutluyum.
Gerard ONeill

85

İfade sıralı olmalı

  1. Tablo için Alter ifadesi
  2. GİT
  3. İfade seçin.

Arada 'GO' olmadan, her şey tek bir komut dosyası olarak kabul edilir ve select deyimi sütunu aradığında bulunmaz.

'GO' ile, komut dosyasının 'GO'ya kadar olan kısmını tek bir toplu iş olarak kabul eder ve' GO 'dan sonra sorguya girmeden önce yürütülür.


7
Bu doğru cevap olarak işaretlenmelidir. SELECT'in aslında oluşturma tablosundan önce çalışacağı değil, ayrıştırılmadan ve çalıştırılmadan önce bir hata atması değil, çünkü #Results adında henüz FieldId sütunu bulunmayan mevcut bir tablo var. select deyiminin ayrıştırıldığı zaman. Buraya bir GO eklemek, sorguyu her biri ayrı ayrı ayrıştırılan ve çalıştırılan toplu işlere ayırır.
Davos

2
Bu ve üst yanıt arasındaki oylardaki eşitsizliğe inanamıyorum, bu da kodu çok değiştirdi - nedenini açıklamadan - bir yanıt olarak anlamsızdı.
underscore_d

63

Bunun yerine droppinggeçici tabloyu oluşturmak ve yeniden oluşturmak truncateve yeniden kullanmak

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

Geçici tabloyu bırakmak ve yeniden oluşturmak için aşağıdaki sözdizimini kullanıyorsanız Sql Server 2016veya Azure Sql Databasedaha sonra kullanıyorsanız. Daha fazla bilgi burada MSDN

Sözdizimi

DROP TABLE [VARSA] [veritabanı_adı. [şema_adı]. | şema_adı. ] tablo_adı [, ... n]

Sorgu:

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

Öyle görünüyor truncate/reuseyöntem daha verimli olacaktır DROP TABLE IF EXISTSüzerinde Sql Server 2016ve Azure Sql Databasehem de. Durum böyle değil mi?
JDawg

@prdp DROP TABLE IF ExistsSQL 2016 veya Azure için neden öneriyorsunuz ? Sözdizimi SQL 2008'den itibaren kullanılabilir. Cevabınızdaki MSDN bağlantısına bakın? Performans faktörü?
HappyTown

4
Boşver. Şimdi fark ettim, DROP TABLESQL Server 2008'den destekleniyor, ancak IF EXISTSmadde 2016'da tanıtıldı.
HappyTown

1
Kullandığım INTO: dbo.HistoricoUser dan * INTO #HistoricoUserTable seçin
Kiquenet

54

Bence sorun, yürütmeyi toplu olarak ayırmak için arada GO ifadesi eklemeniz gerektiğidir. İkinci bırakma komut dosyası IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results, geçici tabloyu tek bir grubun parçası olarak bırakmadı. Aşağıdaki betiği deneyebilir misiniz?

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
Notun; tempdb..Yukarıdaki kodda çok önemlidir. Geçici tablo adınızdan önce gelmesi gerekir. Basitçe kontrol etmek OBJECT_ID('#Results')yeterli değildir. Geçici tablolar TempDB veritabanında depolanır. Microsoft Başına: TempDB sistem veritabanı, SQL Server örneğine veya SQL Veritabanına bağlı tüm kullanıcılar tarafından kullanılabilen global bir kaynaktır
iCode

Teşekkürler, @Code. Geçici tabloları düşürmenin anahtarı budur: yapılması gerekiyor tempdbya da gitmeyecek.
Alex

37

Bu, tek bir kod satırı ile gerçekleştirilebilir:

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

1
Ben her gün buna bakmak gerekir
Ab Bennett

28

Bu benim için çalıştı: social.msdn.microsoft.com/Forums/en/transactsql/thread/02c6da90-954d-487d-a823-e24b891ec1b0?prof=required

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
Bu, koşullu tablo düşüşü için yalnızca farklı bir sözdizimidir. Bu ilginç ama OP'nin sorusunu çözmüyor ve çoğu gereksiz. OBJECT_ID (N'tempdb .. # Results ') null olmadığını kontrol ederseniz, bu nesnenin zaten var olduğunu kanıtlamak için yeterlidir.
Davos

21

Benim OBJECT_IDiçin işe yaramıyor çünkü benim tarafımdan sadece küçük bir yorum . Her zaman geri döner

`#tempTable mevcut değil

olsa ..even yapar mevcuttur. Ben sadece böyle farklı bir adla ( _alt çizgilerle postfixed ) depolanan bulundu :

#tempTable________

Bu benim için iyi çalışıyor:

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

6
Dikkat: Bu kod, herhangi bir iş parçacığı tarafından oluşturulmuşsa bir tabloyu algılar. Saklı bir proc için iş parçacığı / arayan başına ayrı ayrı tekli geçici tablolar oluşturulur; Object_ID, SQL 2005 veya sonraki bir sürümü olduğu sürece geçerli iş parçacığı için Tamam çalışmalıdır.
Bytemaster

12

SQL Server'ın (2016+) yeni sürümlerinden birini kullanıyorsanız şimdi aşağıdaki sözdizimini kullanabilirsiniz.

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

1
SSMS 17.3 kullanıyorum ve bu verirIncorrect syntax near the keyword 'IF'.
StingyJack

7
@StingyJack Çünkü SQL Sözdizimi SSMS sürümüyle ilgili değil, SQL Server sürümüyle ilgilidir. IF [NOT] EXISTSFıkra SQL Server 2016 den kullandığınız hangi ssms versiyon fark etmez mevcuttur.
Pred

10

pmac72 , sorguyu toplu olarak parçalamak için GO'yu ve bir ALTER kullanıyor.

Aynı toplu işi çalıştırıyor, ancak değiştirdikten sonra iki kez çalıştırıyorsunuz: DROP ... CREATE ... edit ... DROP ... CREATE ..

Neler olup bittiğini görebilmemiz için tam kodunuzu yayınlayın.


7

Temp tablosunu zaten oluşturduğumda genellikle bu hatayı vurdum; SQL ifadesini hatalar için kontrol eden kod "eski" geçici tabloyu yerinde görür ve geçici tablo hiç bırakılmamış gibi sonraki ifadelerde sütun sayısı üzerinde bir yanlış sayım döndürür.

Zaten daha az sütunlu bir sürüm oluşturduktan sonra geçici tablodaki sütun sayısını değiştirdikten sonra, tabloyu bırakın ve ardından sorgunuzu çalıştırın.


6

Son zamanlarda bir DBA'nın buna benzer bir şey yaptığını gördüm:

begin try
    drop table #temp
end try

begin catch 
    print 'table does not exist'
end catch 

create table #temp(a int, b int)

2
Bu try ifadesi, tablo bırakılmaya çalışılırken oluşabilecek diğer hataları yakalar. Bu kod, denemenin başarısız olmasının tek nedeninin tablonun mevcut olmaması olduğunu varsayar. Muhtemelen çoğu zaman işe yarar, ama bunu garanti etmem. Try ifadesi başka bir nedenden dolayı başarısız olursa, tabloyu oluştururken bir hata alırsınız, çünkü bu tabloyu bırakmayla ilgili gerçek sorunu maskelemiştir.
Davos

Bu işe yarıyor ama kötü akıllı ve mükemmel bir çözüm olduğunda zor yolu teşvik etmiyorum. Ayrıca OP'nin 2005 sürümü belirtmesine rağmen, try catch block eski sürümlerde desteklenmiyor
dejjub-AIS

Bununla ilgili diğer sorun, try / catch vs logic kullanma ideolojisidir. Tartışmanın daha fazlasını burada görebilirsiniz: stackoverflow.com/questions/17335217/try-catch-or-if-statement/…
logixologist

3

SourceKodum, değişen bir Destinationtablo ve bu değişikliklerle eşleşmesi gereken bir tablo kullanır .

-- 
-- 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

Evet, "geçersiz sütun" satırından kaynaklanan bu hata "#results 'dan şirket, stepid, fieldid, NewColumn seçin".

T-sql koşmanın iki aşaması vardır,

ilk olarak, ayrıştırma, bu aşamada sql sunucusu tablo sütun dahil olmak üzere gönderilen sql dize düzeltmesini kontrol edin ve sorgunuzu en hızlı kurtarma için optimize.

ikincisi, çalışan, verileri toplayan.

#Results tablosu varsa, ayrıştırma işlemi belirttiğiniz sütunların geçerli olup olmadığını kontrol eder, aksi takdirde (tablo mevcut değildir) ayrıştırma belirttiğiniz gibi kontrol sütunlarını geçirerek yapılır.


0

Geçici tabloda bir sütunu değiştirdiğinizde, sorguyu yeniden çalıştırmadan önce tabloyu bırakmanız gerekir. (Evet, sinir bozucu. Yapmanız gerekenler.)

Ben her zaman bu "geçersiz sütun" onay ayrıştırıcı tarafından sorgu çalıştırılmadan önce yapılır, bu yüzden düştü önce tablodaki sütunlar dayanmaktadır çünkü varsaydım ..... ve bu da pnbs de söyledi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.