È consigliabile utilizzare una tabella temporanea quando la procedura memorizzata può essere eseguita contemporaneamente da utenti diversi?


8

Sto lavorando su una procedura memorizzata che recupera objectGUID dalla directory attiva. Sto memorizzando il risultato in una tabella temporanea e quindi restituendo il valore in un parametro di output per l'uso con altri processi. L'SP verrà chiamato da diverse stored procedure, nonché dalle applicazioni Web PHP, ASP Classic e ASP.Net.

Ho letto QUI che (per quanto riguarda le tabelle temporanee):

Se creati all'interno di una procedura memorizzata, vengono distrutti al completamento della procedura memorizzata. Inoltre, l'ambito di ogni particolare tabella temporanea è la sessione in cui viene creata; nel senso che è visibile solo all'utente corrente. Più utenti potrebbero creare una tabella temporanea denominata #TableX e qualsiasi query eseguita simultaneamente non si influenzerebbe a vicenda: rimarrebbero transazioni autonome e le tabelle rimarrebbero oggetti autonomi. Potresti notare che il nome della mia tabella temporanea di esempio è iniziato con un segno "#".

Sembra che io sia bravo ad andare, ma volevo avere qualche consiglio per assicurarmi che non ci siano gotcha di cui non sono a conoscenza. Ecco la SP.

Grazie in anticipo.

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

Risposte:


15

Sì, ogni utente otterrà la propria copia della tabella #temp, anche se vengono eseguiti contemporaneamente.

(Tuttavia, non utilizzare le tabelle globali ## temp, indicate con due principali segni cancelletto / cancelletto.)

Ma perché hai bisogno di una tabella #temp qui? Qualcosa del genere dovrebbe funzionare (non testato, poiché non ho LDAP vicino a me):

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

8

Dovresti andare bene, qui abbiamo innumerevoli SP che vengono eseguiti migliaia di volte al giorno con tabelle temporanee che hanno lo stesso nome e non hanno problemi.

Ecco un esempio visivo. Ho creato 2 tabelle sulla mia istanza SQL2014. Uno è stato creato da SPID 53, l'altro da SPID 57. Ecco come appare in Esplora oggetti:

inserisci qui la descrizione dell'immagine

Come puoi vedere, sebbene siano "nominati" allo stesso modo, alla fine, c'è un bel set di personaggi che rende i tavoli diversi. L'unica differenza è che ho eseguito le istruzioni CREATE da diverse finestre di query. Questo è solo un modo visivo per mostrarlo. Quando si esegue una query sulla tabella #tmp, si esegue solo una query sulla tabella che si applica alla sessione.

Farò comunque un suggerimento. È qualcosa di cui sono completamente colpevole e sto lavorando alla transizione verso. Usa sp_executesqlinvece di EXEC(). Aaron Bertrand ha scritto questo come una delle 'Bad Habits to Kick':

Fondamentalmente, l'utilizzo di sp_executesql ridurrà la possibilità di iniezione SQL e vi è una maggiore possibilità che il piano di esecuzione possa essere riutilizzato. Aaron approfondisce molto di più l'articolo, ma questa è la vista da 1000 piedi.


5
Vorrei solo aggiungere che può essere utile nominare le tabelle temporanee locali in modo univoco per procedura, poiché la procedura può essere chiamata da un'altra procedura che ha già creato una tabella temporanea locale con lo stesso nome.
Paul White 9

2

in senso lato, starai bene così. Le procedure memorizzate hanno un ambito limitato, quindi anche se (esempio) 3 utenti eseguono la stessa procedura memorizzata e le tabelle temporanee non si confondono, non si vedranno nemmeno.

Finché non è necessario condividere i risultati con una sessione diversa o un utente che esegue un processo diverso, la tabella Temp potrebbe essere una strada perfettamente valida.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.