web-dev-qa-db-fra.com

Est-il conseillé d'utiliser une table temporaire lorsque la procédure stockée peut être exécutée simultanément par différents utilisateurs?

Je travaille sur une procédure stockée qui récupère le objectGUID d'Active Directory. Je stocke le résultat dans une table temporaire, puis je renvoie la valeur dans un paramètre de sortie pour une utilisation avec d'autres processus. Le SP sera appelé à partir de différentes procédures stockées ainsi que des applications Web PHP, ASP Classic et ASP.Net.

J'ai lu ICI cela (concernant les tables temporaires):

S'ils sont créés dans une procédure stockée, ils sont détruits à la fin de la procédure stockée. En outre, la portée d'une table temporaire particulière est la session dans laquelle elle est créée; ce qui signifie qu'il n'est visible que pour l'utilisateur actuel. Plusieurs utilisateurs pourraient créer une table temporaire nommée #TableX et toutes les requêtes exécutées simultanément ne s'influenceraient pas - elles resteraient des transactions autonomes et les tables resteraient des objets autonomes. Vous pouvez remarquer que mon exemple de nom de table temporaire a commencé par un signe "#".

On dirait que je suis prêt à partir, mais je voulais obtenir des conseils pour m'assurer qu'il n'y avait aucun problème que j'ignore. Voici le SP.

Merci d'avance.

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

Oui, chaque utilisateur obtiendra sa propre copie de la table #temp, même s'il s'exécute en même temps.

(Cependant, n'utilisez pas les tables globales ## temp, signifiées par deux signes dièse/hachage principaux.)

Mais pourquoi avez-vous besoin d'une table #temp ici? Quelque chose comme ça devrait fonctionner (non testé, car je n'ai LDAP nulle part près de moi):

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
15
Aaron Bertrand

Vous devriez être très bien, nous avons ici d'innombrables SP qui s'exécutent des milliers de fois par jour avec des tables temporaires qui sont nommées de la même manière et qui n'ont aucun problème.

Voici un exemple visuel. J'ai créé 2 tables sur mon instance SQL2014. L'un a été créé à partir de SPID 53, l'autre à partir de SPID 57. Voici à quoi il ressemble dans l'Explorateur d'objets:

enter image description here

Comme vous pouvez le voir, bien qu'ils soient "nommés" de la même manière, à la toute fin, il y a un bel ensemble de caractères qui rendent les tableaux différents. La seule différence est que j'ai exécuté les instructions CREATE à partir de différentes fenêtres de requête. C'est juste une façon visuelle de le montrer. Lorsque vous interrogez la table #tmp, vous interrogez uniquement la table qui s'applique à votre session.

Je ferai cependant une suggestion. C'est quelque chose dont je suis complètement coupable et je travaille à la transition vers. Utilisez sp_executesql Au lieu de EXEC(). Aaron Bertrand a écrit ceci comme l'une des `` mauvaises habitudes de coup de pied '':

Fondamentalement, l'utilisation de sp_executesql réduira les risques d'injection SQL et il y a plus de chances que le plan d'exécution puisse être réutilisé. Aaron va dans beaucoup plus de détails dans l'article, mais c'est la vue de 1000 pieds.

8
Kris Gruttemeyer

d'un sens large, vous serez très bien de le faire de cette façon. Les procédures stockées ont une portée limitée, donc même si (exemple) 3 utilisateurs exécutent la même procédure stockée et que les tables temporaires ne se mélangent pas, elles ne se voient même pas.

Tant que vous n'avez pas besoin de partager les résultats avec une session différente ou qu'un utilisateur exécutant un processus différent, la table Temp peut être une solution parfaitement appropriée.

2
Brad D