web-dev-qa-db-fra.com

Table temporaire du serveur SQL utilisant # - est-elle uniquement accessible par la requête conteneur pour plusieurs connexions avec la même connexion?

Supposons que nous ayons 2 requêtes complètement différentes, qui font référence à une table temporaire avec le même nom:

requête un .... opère sur: #tempTableName

requête deux .... opère sur: #tempTableName

J'ai fait des recherches et découvert que "#temp est une table temporaire locale, et donc pas visible pour les autres connexions", mais je ne sais pas vraiment ce qu'est une connexion vraiment signifie en profondeur dans le contexte des requêtes SQL. SQL considère-t-il qu'il existe une "connexion" distincte pour chaque requête distincte exécutée, ou une connexion est-elle partagée d'une manière ou d'une autre?

Plus précisément, ma question est "que se passe-t-il si les deux requêtes de mon scénario sont accessibles par la même connexion", par exemple plusieurs applications .NET utilisent la même chaîne de connexion .NET et accèdent simultanément à la base de données. Vont-ils alors potentiellement accéder à la même table temporaire si les deux requêtes de mon scénario sont exécutées simultanément? Et les serrures? Dois-je faire quelque chose pour empêcher tout accès indésirable pendant les opérations sur la table?

J'ai regardé cette réponse, https://stackoverflow.com/questions/466947/are-temporary-tables-thread-safe , mais j'ai vraiment besoin de quelque chose comme un 'faire semblant d'avoir 6 ans ans pour que je sois parfaitement clair sur ce qui se passe dans mon scénario hypothétique en termes d'exactement comment les requêtes SQL utilisent les connexions et déterminent l'accès exclusif, etc. Tous les diagrammes ou pointeurs vers des ressources qui peuvent me donner une commande complète de ce serait génial!

7
Chris Halcrow

Les objets temporaires locaux sont séparés par session. Si vous avez deux requêtes exécutées simultanément, il s'agit clairement de deux sessions complètement distinctes et vous n'avez rien à craindre. La connexion n'a pas d'importance. Et si vous utilisez le pool de connexions, cela n'a pas d'importance non plus. Les objets temporaires locaux (les tables le plus souvent, mais aussi les procédures stockées) sont à l'abri des autres sessions.

Bien que votre code ait un seul nom commun pour les objets temporaires locaux, SQL Server ajoute une chaîne unique à chaque nom d'objet pour chaque session (et si nécessaire, pour chaque sous-processus) pour les garder séparés. Vous pouvez le voir en exécutant les requêtes suivantes dans SSMS:

CREATE TABLE #T (Col1 INT)

SELECT * FROM tempdb.sys.tables WHERE [name] LIKE N'#T%';

Vous verrez quelque chose comme ce qui suit pour le nom (j'ai supprimé la plupart des soulignements du milieu du nom pour éviter d'avoir à faire défiler ici):

#T_______________00000000001F

Ensuite, sans fermer cet onglet de requête, ouvrez un nouvel onglet de requête et collez-les dans ces 2 mêmes requêtes et exécutez-les. Vous devriez maintenant voir quelque chose comme ceci:

#T_______________00000000001F
#T_______________000000000020

Ainsi, chaque fois que votre code référence #T, SQL Server le traduira au nom correct en fonction de la session. Tout est géré automatiquement comme par magie :-).

Pour illustrer ce point. J'ai travaillé sur des systèmes hautement transactionnels (des milliers de transactions par seconde) et étaient des applications Web SaaS (Software as a Service)) fonctionnant 24h/24 et 7j/7. Tout le code T-SQL était dans les procédures stockées (ce qui signifie: le même nom de table temporaire locale pour chaque exécution de ce code) et nous avons fait un bon usage des tables temporaires locales. Étant une application Web, la connexion était la même pour presque toutes les connexions et nous avons certainement utilisé le pool de connexions. Nous n'avons jamais eu tout problème indiquant tout accès intersessions d'objets temporaires locaux du même nom. Et franchement, nous aurions été choqués et utiliser notre contrat de support avec Microsoft pour le réparer si jamais cela se produisait .

Points supplémentaires à garder à l'esprit concernant les tables temporaires locales:

  1. Alors que leurs noms sont uniques, leurs objets dépendants ne le sont pas. Vous ne pouvez pas créer de déclencheurs ou de clés étrangères sur des tables temporaires, il s'agit donc vraiment des clés primaires, des contraintes de vérification et des contraintes par défaut. Cela signifie que nommer une clé primaire #PK_#T n'en fait pas un nom unique avec un identifiant unique en arrière-plan ajouté au nom. Si vous essayez cela, vous obtiendrez "Impossible de créer un objet. L'objet existe déjà." erreurs (enfin, en supposant plusieurs exécutions simultanées de ce même code). Donc, si vous avez besoin de l'un de ces 3 types d'objet pour une table temporaire locale, créez les objets dépendants en ligne afin qu'ils obtiennent des noms générés par le système qui seront uniques et n'entreront pas en conflit entre les sessions.

    Vous n'avez pas à vous soucier des noms d'index car ceux-ci sont déjà séparés par [object_id].

  2. Étant donné que vous obtenez "Impossible de créer un objet. L'objet existe déjà." des erreurs lors de la création d'objets dépendants nommés, ce qui soulève un bon point qui est le plus souvent ignoré en ce qui concerne "les objets temporaires locaux sont-ils complètement isolés par session": si des tables temporaires locales peuvent être vues par d'autres sessions, alors le CREATE TABLE l'instruction obtiendrait une erreur, non?
  3. Une nuance des tables temporaires locales (qui est également un contrepoint lâche au n ° 2 ci-dessus) est que si vous référencez une table temporaire locale dans un sous-processus (c'est-à-dire EXEC) qui a été créé avant ce sous-processus -démarrage du processus, il pourra voir (et même modifier) ​​cette table temporaire locale. CEPENDANT, si ce sous-processus crée une autre table temporaire portant le même nom, alors il y aura deux objets, avec des ID uniques séparés ajoutés à la fin, qui sont accessibles via le nom court. Je me souviens avoir lu quelque part qu'il n'y a pas garantie qui référençant #name dans le sous-processus se résoudra toujours par la version de cet objet qui a été créée dans le sous-processus. Par conséquent, il est préférable d'avoir une certaine unicité des noms de tables temporaires locales entre les procédures stockées qui ont la possibilité d'être exécutées dans une chaîne d'appels de procédures stockées imbriquées.
11
Solomon Rutzky