CREATE TABLE SomeSchema. # TempTableName a-t-il un bogue?

12

Banc d'essai simple:

USE tempdb;
GO

/*
    This DROP TABLE should not be necessary, since the DROP SCHEMA
    should drop the table if it is contained within the schema, as
    I'd expect it to be.
*/
IF COALESCE(OBJECT_ID('tempdb..#MyTempTable'), 0) <> 0 
    DROP TABLE #MyTempTable;

IF EXISTS (SELECT 1 FROM sys.schemas s WHERE s.name = 'SomeSchema') 
    DROP SCHEMA SomeSchema;
GO

CREATE SCHEMA SomeSchema AUTHORIZATION [dbo]
CREATE TABLE SomeSchema.#MyTempTable /* specifying the schema
                                        should not be necesssary since
                                        this statement is executed inside
                                        the context of the CREATE SCHEMA
                                        statement
                                     */
(
    TempTableID INT NOT NULL IDENTITY(1,1)
    , SomeData VARCHAR(50) NOT NULL
);
GO

INSERT INTO tempdb.SomeSchema.#MyTempTable (SomeData) VALUES ('This is a test');

SELECT *
FROM tempdb.SomeSchema.#MyTempTable;
GO

SELECT *
FROM sys.objects o
    INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE s.name = 'SomeSchema';

SELECT s.name
    , o.name
FROM sys.objects o
    INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE s.name = 'dbo'
    AND o.name LIKE '%MyTempTable%';

DROP SCHEMA SomeSchema;
DROP TABLE #MyTempTable;

Ce qui précède doit créer une table temporaire nommée #MyTempTabledans la tempdb sous le schéma nommé SomeSchema; mais ce n'est pas le cas. Au lieu de cela, la table est créée dans le dboschéma.

Est-ce un comportement attendu? Je me rends compte que c'est certainement un cas limite autour de l'utilisation de tables temporaires spécifiques au schéma; cependant, ce serait bien si le moteur fournissait une erreur lors de la tentative de création d'une table temporaire liée au schéma, ou s'il le liait réellement au schéma spécifié dans la DDL.

De plus, je n'ai actuellement pas accès à SQL Server 2014 ou 2016; ça marche comme prévu sur ces plateformes?

Max Vernon
la source
Le kit de formation pour 70-461 indique que «les tables temporaires sont créées dans tempdb dans le schéma dbo. t spécifier un schéma.
Mark Sinkinson

Réponses:

11

Les deux références sont valides et se résoudront correctement, mais la table #temp est créée sous le dboschéma.

Même réponse (sur votre système, un nombre que je ne pouvais pas deviner):

SELECT OBJECT_ID('dbo.#MyTempTable');
SELECT OBJECT_ID('SomeSchema.#MyTempTable');

Même réponse (les deux 1, qui est dbo):

SELECT schema_id FROM sys.tables WHERE [object_id] = OBJECT_ID('dbo.#MyTempTable');
SELECT schema_id FROM sys.tables WHERE [object_id] = OBJECT_ID('SomeSchema.#MyTempTable');

Pouvoir spécifier un schéma ne vous rapporte rien parce que vous n'allez pas avoir de collisions (deux tables #temp du même nom sous des schémas différents) au cours d'une session, non?

Il s'agit d'un comportement attendu. Une table #temp est liée à une session, mais pas à un schéma spécifique. Et cela fonctionne de la même manière jusqu'à 2016 CTP 3.2. L'analyseur pardonne probablement, autorisant le nom de schéma vide de sens de la même manière qu'il autorise cette virgule de fin errante:

CREATE TABLE dbo.foo 
(
        bar INT
        ,
);
Aaron Bertrand
la source
Probablement en grande partie parce que les tables temporaires sont en fait créées dans TempDB et qu'un schéma local ne fonctionnerait pas (sauf si vous étiez en fait dans TempDB bien sûr)
Kenneth Fisher
Il existe donc clairement du code qui ignore le nom du schéma lors de la création d'une table temporaire; et ce code est silencieux.
Max Vernon