Apakah “CUKUP” untuk MENCIPTAKAN dan MENGHENTIKAN #SomeTable lebih dari sekali?

8

Saya mendapatkan kode yang dipisahkan sebagai "blok koheren" yang dapat saya masukkan ke dalam "skrip konfigurasi" yang lebih lama, dan salah satu pola yang saya gunakan adalah ini:

CREATE TABLE #WidgetSetting 
(
    WidgetID bigint not null,
    Name nvarchar(100) not null,
    Value nvarchar(max) not null,
    CreateDate datetime not null
)

INSERT VALUES

MERGE TABLES

DROP TABLE #WidgetSetting

Tapi sekarang SSMS mengeluh bahwa objek sudah ada pada saat CREATE TABLEkebakaran berikutnya . Apa yang menyebabkannya?

Saya pikir sudah jelas saya harus mendeklarasikan tabel sekali di awal skrip, memotong bukan drop, tapi tentu saja frustasi, tidak bisa hanya menjatuhkan meja dan menggunakan nama yang sama lagi.

jcolebrand
sumber
Seperti yang dikomentari Aaron di bawah ini, jika ini adalah rute yang telah Anda ambil, perbaikan yang paling mudah adalah dengan menjatuhkan #TABLE di bagian paling akhir skrip dan cukup TRUNCATE pada langkah-langkah di antaranya. Itu dengan asumsi itu tidak mungkin untuk hanya mendesain ulang skrip agar bekerja secara berbeda sejak awal. :)
Kahn
1
Sebenarnya itulah yang saya lakukan untuk menyelesaikannya. Saya hanya bingung dengan perilaku itu. Dia menjelaskan mengapa yang saya inginkan lebih daripada cara memperbaikinya.
jcolebrand

Jawaban:

11

Tidak, pengurai tidak akan membiarkan Anda membuat tabel #temp yang sama dua kali dalam batch yang sama (dan ini tidak ada hubungannya dengan SSMS). Bahkan tidak masalah jika hanya satu salinan tabel #temp yang dapat dibuat; misalnya, dalam logika kondisional berikut, yang bagi manusia jelas hanya dapat menjalankan satu cabang, SQL Server tidak dapat melihat bahwa:

IF 1 = 1
BEGIN
  CREATE TABLE #x(i INT);
  DROP TABLE #x;
END
ELSE
BEGIN
  CREATE TABLE #x(j INT);
  DROP TABLE #x;
END

Msg 2714, Level 16, Negara 1, Baris 8
Sudah ada objek bernama '#x' dalam database.

Dan untuk membuktikan itu bukan SSMS mengeluh pada waktu kompilasi (kesalahpahaman umum):

DECLARE @sql NVARCHAR(MAX) = N'IF 1 = 1
BEGIN
  CREATE TABLE #x(i INT);
  DROP TABLE #x;
END
ELSE
BEGIN
  CREATE TABLE #x(j INT);
  DROP TABLE #x;
END';

EXEC sp_executesql @sql;

Menghasilkan kesalahan yang sama persis, meskipun SSMS tidak mencoba menguraikan atau memvalidasi SQL dinamis sebelum mengirimnya ke server melalui sp_executesql.

Cara mengatasinya, tentu saja, adalah menggunakan kembali tabel #temp yang sama dan bukannya menjatuhkan, menggunakan tabel #temp yang berbeda setiap kali, atau tidak menggunakan tabel #temp di tempat pertama.

Ini bukan sesuatu yang seharusnya Anda harapkan SQL Server untuk menangani lebih baik. Dengan kata lain, biasakan diri untuk penyelesaian apa pun yang Anda putuskan.

Lihat juga jawaban terkait ini di Stack Overflow yang memberikan penjelasan alternatif:

Aaron Bertrand
sumber