Question Portée des tables temporaires dans SQL Server


J'ai écrit une procédure stockée pour importer et transformer des données d'une base de données à une autre. Chaque importation prendrait un seul identifiant d'entreprise et importerait toutes les données relatives à cette société.

Pour faciliter l'étape de transformation, j'utilise des tables temporaires. Dans le cadre de la révision du script, on m'a dit d'utiliser des variables de table plutôt que des tables temporaires. Le réviseur affirme que si nous exécutons deux importations différentes en même temps, la table temporaire serait partagée et corromprait l'importation.


Des questions:

  • Est-il vrai que la table temporaire serait partagée si nous exécutions deux importations différentes en même temps?
  • Est-ce que chaque appel à EXEC créer une nouvelle portée?

Voici un exemple inventé du script.

CREATE PROC [dbo].[ImportCompany]
(
    @CompanyId AS INTEGER
)
AS
EXEC [dbo].[ImportAddress] @CompanyId = @CompanyId 
--Import other data

CREATE PROC [dbo].[ImportAddress]
(
    @CompanyId AS INTEGER
)
AS
    CREATE TABLE #Companies (OldAddress NVARCHAR(128), NewAddress NVARCHAR(128))
    INSERT INTO #Companies(OldAddress, NewAddress)
    SELECT
        Address as OldAddress,
        'Transformed ' + Address as NewAddress
    FROM
        [OldDb].[dbo].[Addresses]
    WHERE
        CompanyId = @CompanyId

    --Do stuff with the transformed data

    DROP TABLE #Companies

EXEC [dbo].[ImportCompany] @CompanyId = 12345

32
2017-09-04 12:51


origine


Réponses:


De CREATE TABLE:

Les tables temporaires locales ne sont visibles que dans la session en cours

et plus important):

Si une table temporaire locale est créée dans une procédure stockée ou une application pouvant être exécutée simultanément par plusieurs utilisateurs, le moteur de base de données doit pouvoir distinguer les tables créées par les différents utilisateurs. Pour ce faire, le moteur de base de données ajoute en interne un suffixe numérique à chaque nom de table temporaire locale.

Ce qui réfute exactement le point de vue de celui qui a dit qu'ils seraient partagés.


En outre, il n'est pas nécessaire de DROP TABLE à la fin de votre procédure (à partir du même lien à nouveau):

Une table temporaire locale créée dans une procédure stockée est automatiquement supprimée lorsque la procédure stockée est terminée


45
2017-09-04 12:56



## est utilisé pour les tables temporaires globales - sera disponible pour les différentes importations.

# est utilisé pour les tables temporaires locales et uniquement disponible dans la portée actuelle / interne.


22
2017-09-04 12:53



Une session ne peut pas voir les tables temporaires d'une autre session. Ainsi, différentes importations ne s’affecteront pas, que vous utilisiez des tables temporaires ou des variables de table.

L’exception concerne les tables temporaires globales, qui commencent par ##. Ceux-ci sont visibles pour toutes les connexions.


17
2017-09-04 12:52



Je viens de passer quelques heures à me demander pourquoi une table temporaire utilisée dans une détente se comportait étrangement. Ensuite, j'ai réalisé que la table temporaire avait le même nom qu'une table temporaire dans la procédure stockée utilisée pour insérer les données ayant déclenché le déclencheur. Je suis maintenant conscient que cela aurait dû être évident pour moi tout de suite, mais c'était un cas typique de négliger la cause la plus évidente en essayant de découvrir pourquoi quelque chose n'avait pas de sens.

Il est donc important de se rappeler que lorsqu'un processus stocké appelle un autre processus stocké ou déclenche un déclencheur, les noms des tables temporaires doivent être uniques pour éviter des effets secondaires indésirables.

En outre, même lorsqu’il exécute le code suivant dans la procédure stockée interne, il ne fonctionnera pas comme prévu. Étant donné que le processus externe stocké semble verrouiller le nom de la table temporaire.

IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
    DROP TABLE #TempTable

-1
2018-05-25 07:42