Apakah disarankan untuk menggunakan tabel temp ketika prosedur yang disimpan dapat dijalankan secara bersamaan oleh pengguna yang berbeda?

8

Saya sedang mengerjakan prosedur tersimpan yang mengambil objectGUID dari direktori aktif. Saya menyimpan hasilnya dalam tabel temp dan kemudian mengembalikan nilai dalam parameter output untuk digunakan dengan proses lain. SP akan dipanggil dari berbagai prosedur tersimpan serta aplikasi web PHP, ASP Classic dan ASP.Net.

Saya membaca DI SINI bahwa (mengenai tabel temp):

Jika dibuat di dalam prosedur tersimpan mereka dihancurkan setelah menyelesaikan prosedur tersimpan. Selain itu, ruang lingkup dari tabel sementara tertentu adalah sesi di mana ia dibuat; artinya hanya dapat dilihat oleh pengguna saat ini. Beberapa pengguna dapat membuat tabel temporer bernama #TableX dan setiap kueri yang dijalankan secara bersamaan tidak akan memengaruhi satu sama lain - mereka akan tetap menjadi transaksi otonom dan tabel akan tetap menjadi objek otonom. Anda mungkin memperhatikan bahwa nama tabel sementara sampel saya dimulai dengan tanda "#".

Kedengarannya saya baik untuk pergi tetapi saya ingin mendapatkan beberapa saran untuk memastikan tidak ada gotcha yang saya tidak sadari. Inilah SP.

Terima kasih sebelumnya.

CREATE PROCEDURE stp_adlookup
@user varchar(100),
@objectGUID varbinary(256) OUTPUT
AS
SET NOCOUNT ON;
DECLARE @qry char(1000)
CREATE TABLE #tmp(
objectGUID nvarchar(256)
)

SET @qry = 'SELECT *
FROM openquery(ADSI, ''
SELECT  objectGUID              
FROM    ''''LDAP://mydomaincontroller.com''''
WHERE sAMAccountName = ''''' + @user + '''''
'')'
INSERT INTO #tmp
EXEC(@qry)
SELECT @objectGUID=CAST(objectGUID as varbinary(256))  FROM #tmp;
DROP TABLE #tmp
SET NOCOUNT OFF;
GO
pengguna1633947
sumber

Jawaban:

15

Ya, setiap pengguna akan mendapatkan salinan tabel #temp mereka sendiri, bahkan jika mereka berjalan pada waktu yang sama.

(Namun, jangan gunakan tabel temp ## global, yang ditandai dengan dua tanda pound / hash terkemuka.)

Tapi mengapa Anda perlu tabel #temp di sini? Sesuatu seperti ini seharusnya bekerja (belum diuji, karena saya tidak memiliki LDAP di dekat saya):

CREATE PROCEDURE dbo.stp_adlookup -- ALWAYS use schema prefix
  @user varchar(100),
  @objectGUID varbinary(256) OUTPUT
AS
BEGIN -- use body wrappers
  SET NOCOUNT ON;

  DECLARE @qry nvarchar(max); -- don't use CHAR for dynamic SQL

  SET @qry = N'SELECT @o = objectGUID
    FROM openquery(ADSI, ''SELECT  objectGUID              
      FROM    ''''LDAP://mydomaincontroller.com''''
      WHERE sAMAccountName = ''''' + @user + ''''''')';

  -- can probably parameterize the above, but those single
  -- quotes are a nightmare. Not sure if they're necessary
  -- but I do not feel like trying to untangle them.

  EXEC sys.sp_executesql @qry, N'@o UNIQUEIDENTIFIER', @o = @objectGUID OUTPUT;

  -- SET NOCOUNT OFF; -- don't do this.
END
GO
Aaron Bertrand
sumber
8

Anda seharusnya baik-baik saja, kami memiliki SPs yang tak terhitung jumlahnya di sini yang dijalankan 1000 kali sehari dengan tabel temp yang dinamai sama dan tidak memiliki masalah.

Ini contoh visualnya. Saya telah membuat 2 tabel pada contoh SQL2014 saya. Satu dibuat dari SPID 53, yang lain dari SPID 57. Begini tampilannya di Object Explorer:

masukkan deskripsi gambar di sini

Seperti yang Anda lihat, meskipun mereka 'diberi nama' yang sama, pada akhirnya, ada serangkaian karakter indah yang membuat tabel berbeda. Satu-satunya perbedaan adalah saya menjalankan pernyataan CREATE dari jendela permintaan yang berbeda. Ini hanya cara visual untuk menunjukkannya. Saat Anda kueri tabel #tmp, Anda hanya kueri tabel yang berlaku untuk sesi Anda.

Saya akan memberikan satu saran. Ini adalah sesuatu yang saya sepenuhnya bersalah dan saya sedang berusaha untuk beralih ke. Gunakan sp_executesqlsebagai ganti EXEC(). Aaron Bertrand menulis ini sebagai salah satu 'Kebiasaan Buruk untuk Tendangan':

Pada dasarnya, menggunakan sp_executesql akan mengurangi kemungkinan injeksi SQL dan ada peluang yang lebih tinggi bahwa rencana eksekusi dapat digunakan kembali. Aaron masuk ke jauh lebih detail dalam artikel, tapi itulah pandangan 1000-kaki.

Kris Gruttemeyer
sumber
5
Saya hanya akan menambahkan bahwa akan berguna untuk memberi nama tabel sementara lokal secara unik per prosedur, karena prosedur dapat dipanggil dari prosedur lain yang telah membuat tabel sementara lokal dengan nama yang sama.
Paul White 9
2

dari pengertian luas Anda akan baik-baik saja melakukannya dengan cara ini. Prosedur tersimpan memiliki ruang lingkup terbatas, jadi meskipun (contoh) 3 pengguna menjalankan prosedur tersimpan yang sama dan tabel temp tidak akan saling berbaur, mereka bahkan tidak akan melihat satu sama lain.

Selama Anda tidak perlu berbagi hasil dengan sesi yang berbeda atau pengguna yang menjalankan proses Temp table yang berbeda bisa menjadi cara yang sangat masuk akal.

Brad D
sumber