Ist es ratsam, eine temporäre Tabelle zu verwenden, wenn die gespeicherte Prozedur gleichzeitig von verschiedenen Benutzern ausgeführt werden kann?

8

Ich arbeite an einer gespeicherten Prozedur, die die objectGUID aus dem Active Directory abruft. Ich speichere das Ergebnis in einer temporären Tabelle und gebe dann den Wert in einem Ausgabeparameter zur Verwendung mit anderen Prozessen zurück. Der SP wird von verschiedenen gespeicherten Prozeduren sowie von Webanwendungen PHP, ASP Classic und ASP.Net aufgerufen.

Ich habe HIER gelesen, dass (in Bezug auf temporäre Tabellen):

Wenn sie innerhalb einer gespeicherten Prozedur erstellt werden, werden sie nach Abschluss der gespeicherten Prozedur zerstört. Darüber hinaus ist der Umfang einer bestimmten temporären Tabelle die Sitzung, in der sie erstellt wird. Dies bedeutet, dass es nur für den aktuellen Benutzer sichtbar ist. Mehrere Benutzer könnten eine temporäre Tabelle mit dem Namen #TableX erstellen, und alle gleichzeitig ausgeführten Abfragen würden sich nicht gegenseitig beeinflussen - sie würden autonome Transaktionen bleiben und die Tabellen würden autonome Objekte bleiben. Möglicherweise stellen Sie fest, dass der Name meiner temporären Beispieltabelle mit einem "#" - Zeichen begann.

Klingt so, als wäre ich gut zu gehen, aber ich wollte einen Rat einholen, um sicherzustellen, dass es keine Fallstricke gibt, von denen ich nichts weiß. Hier ist der SP.

Danke im Voraus.

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

Antworten:

15

Ja, jeder Benutzer erhält eine eigene Kopie der Tabelle #temp, auch wenn er genau zur gleichen Zeit ausgeführt wird.

(Verwenden Sie jedoch keine globalen ## temporären Tabellen, die mit zwei führenden Pfund- / Hash-Zeichen gekennzeichnet sind.)

Aber warum brauchst du hier überhaupt eine # temp-Tabelle? So etwas sollte funktionieren (ungetestet, da ich kein LDAP in meiner Nähe habe):

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

Sie sollten in Ordnung sein, wir haben hier unzählige SPs, die tausende Male am Tag mit temporären Tabellen ausgeführt werden, die den gleichen Namen haben und keine Probleme haben.

Hier ist ein visuelles Beispiel. Ich habe 2 Tabellen auf meiner SQL2014-Instanz erstellt. Eine wurde aus SPID 53 erstellt, die andere aus SPID 57. So sieht es im Objekt-Explorer aus:

Geben Sie hier die Bildbeschreibung ein

Wie Sie sehen können, gibt es am Ende, obwohl sie gleich benannt sind, eine schöne Reihe von Zeichen, die die Tabellen anders machen. Der einzige Unterschied ist, dass ich die CREATE-Anweisungen aus verschiedenen Abfragefenstern ausgeführt habe. Dies ist nur eine visuelle Darstellung. Wenn Sie die Tabelle #tmp abfragen, fragen Sie nur die Tabelle ab, die für Ihre Sitzung gilt.

Ich werde jedoch einen Vorschlag machen. Es ist etwas, an dem ich völlig schuld bin und an dem ich gerade arbeite. Verwenden Sie sp_executesqlanstelle von EXEC(). Aaron Bertrand schrieb dies als eine der "Bad Habits to Kick":

Grundsätzlich verringert die Verwendung von sp_executesql die Wahrscheinlichkeit einer SQL-Injection und es besteht eine höhere Wahrscheinlichkeit, dass der Ausführungsplan wiederverwendet werden kann. Aaron geht in dem Artikel viel detaillierter auf das ein, aber das ist die 1000-Fuß-Ansicht.

Kris Gruttemeyer
quelle
5
Ich möchte nur hinzufügen, dass es nützlich sein kann, lokale temporäre Tabellen pro Prozedur eindeutig zu benennen, da die Prozedur möglicherweise von einer anderen Prozedur aufgerufen wird, die bereits eine lokale temporäre Tabelle mit demselben Namen erstellt hat.
Paul White 9
2

Im weitesten Sinne werden Sie es auf diese Weise gut machen. Gespeicherte Prozeduren haben einen begrenzten Umfang. Obwohl (Beispiel) 3 Benutzer dieselbe gespeicherte Prozedur ausführen und sich die temporären Tabellen nicht vermischen, sehen sie sich nicht einmal.

Solange Sie die Ergebnisse nicht für eine andere Sitzung freigeben müssen oder ein Benutzer eine andere Prozesstemp-Tabelle ausführt, kann dies ein perfekter Weg sein.

Brad D.
quelle