J'ai une question concernant un document sur les tables temporaires que j'ai récemment lu sur TechNet . Le quatrième paragraphe de la section Tables temporaires de cette page se lit comme suit:
Si une table temporaire est créée avec une contrainte nommée et que la table temporaire est créée dans le cadre d'une transaction définie par l'utilisateur, un seul utilisateur à la fois peut exécuter l'instruction qui crée la table temporaire. Par exemple, si une procédure stockée crée une table temporaire avec une contrainte de clé primaire nommée, la procédure stockée ne peut pas être exécutée simultanément par plusieurs utilisateurs.
Je travaille dans un environnement où nous utilisons de manière significative une poignée de procédures stockées qui utilisent des tables temporaires indexées, et nous n'avons jamais rencontré de problème où les utilisateurs doivent attendre la fin d'une exécution avant le début de la suivante. J'espère que cela continuera d'être le cas, mais je crains que cela ne devienne un problème si cette mise en garde n'est pas bien comprise.
Plus précisément, je ne suis pas clair sur les points suivants:
- Cela s'applique-t-il uniquement aux tables temporaires globales ou aux tables locales? Il semble étrange qu'une table qui n'est pas visible en dehors de la session (comme dans ce dernier cas) empêche une autre session de s'exécuter simultanément.
- Qu'est-ce qui constitue une "contrainte nommée"? Toutes les contraintes n'ont-elles pas de noms (même si elles sont générées par le système)? S'agit-il de contraintes avec un alias défini par l'utilisateur? Cela me semble une mauvaise formulation.
- Est-ce que "plusieurs utilisateurs" signifie en réalité plusieurs sessions? Ces procédures sont appelées via notre application à l'aide d'un seul compte de service, donc 99,9% des appels à nos scripts sont effectués vers la base de données par ce compte unique (et je ne suis pas préoccupé par l'appel occasionnel qu'un administrateur peut faire sur le backend). Si le compte de service peut exécuter le sproc dans plusieurs sessions simultanément, ce problème est sans objet pour mes besoins.
la source
Réponses:
Je pense à cela car vous ne pouvez pas avoir de noms en double
tempdb.sys.key_constraints
. Voici le contenu de cette vue de métadonnées sur l'un de mes serveurs:Tous les noms impairs qui se terminent par
_6E...
étaient des noms générés automatiquement par SQL Server. Ce ne sont pas des contraintes nommées car je ne leur ai pas explicitement donné de nom lors de leur création. SQL Server génère un nom de contrainte dans les coulisses qui évite en théorie les collisions de noms.Si j'essaie de créer le tableau suivant en deux sessions différentes:
Celui qui s'exécute en deuxième lance une erreur:
Retrouver la vue:
Si j'essaie de créer le tableau suivant en deux sessions, il n'y a pas de problème:
Voici la vue des métadonnées:
Juste pour répondre directement à vos questions: la partie que vous avez citée s'applique aux tables temporaires locales et globales, une contrainte nommée est une contrainte dans laquelle vous lui donnez délibérément un nom, et plusieurs utilisateurs signifient plusieurs sessions.
la source
Cela s'applique aux tables temporaires locales.
La différence entre les contraintes nommées et non nommées est la suivante:
Laisser les contraintes de nom du système rend extrêmement improbable une collision. Dans cet exemple, si vous ouvrez deux fenêtres dans SSMS, vous pourrez créer les
#t1
deux, mais pas#t2
.Les tables temporaires globales sont partagées par tous les utilisateurs, vous devez donc gérer les choses différemment. Ils ne sont «détruits» que lorsque la dernière session est terminée en les utilisant, vous devez donc vous assurer que lorsque les utilisateurs y accèdent, ils ne peuvent accéder qu'à leurs données. Cela est parfois effectué par SPID, d'autres fois par une valeur de hachage. Cela dépend de la façon dont la table temporaire globale est utilisée.
En règle générale pour les tables temporaires globales, les procédures stockées vérifieront si elles existent, et seulement les créer si l'
OBJECT_ID()
estNULL
.Plusieurs utilisateurs signifient plusieurs sessions. Le nom de connexion n'a rien à voir avec cela. Si George s'exécute
sp_something @i = 1
et Gina s'exécutesp_something @i = 2
, peu importe s'ils sont tous deux connectés en tant queUser1
, ils auront des SPID différents.la source