¿CREATE TABLE SomeSchema. # TempTableName tiene un error?

12

Banco de pruebas 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;

Lo anterior debería crear una tabla temporal nombrada #MyTempTableen tempdb bajo el esquema nombrado SomeSchema; Sin embargo no lo hace. En cambio, la tabla se crea en el dboesquema.

¿Es este comportamiento esperado? Me doy cuenta de que este es sin duda un caso extremo en torno al uso de tablas temporales específicas del esquema; sin embargo, sería bueno si el motor proporcionara un error al intentar crear una tabla temporal vinculada al esquema, o si realmente lo vinculó al esquema especificado en el DDL.

Además, actualmente no tengo acceso a SQL Server 2014 o 2016; ¿Funciona como se espera en esas plataformas?

Max Vernon
fuente
El kit de capacitación para 70-461 establece que "las tablas temporales se crean en tempdb en el esquema dbo", sin embargo, no incluye más información que esa, por lo que no estoy seguro de si eso significa solo cuando usted no " t especificar un esquema.
Mark Sinkinson el

Respuestas:

11

Ambas referencias son válidas y se resolverán correctamente, pero la tabla #temp se crea bajo el dboesquema.

La misma respuesta (en su sistema, algún número que no podría adivinar):

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

Misma respuesta (ambos 1, que es 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');

Poder especificar un esquema no te compra nada porque no vas a tener colisiones (dos tablas #temp del mismo nombre bajo diferentes esquemas) dentro de una sesión, ¿verdad?

Este es el comportamiento esperado. Una tabla #temp está vinculada a una sesión, pero no a un esquema específico. Y funciona igual hasta 2016 CTP 3.2. El analizador probablemente sea indulgente, permitiendo el nombre de esquema sin sentido de la misma manera que permite esta coma final errante:

CREATE TABLE dbo.foo 
(
        bar INT
        ,
);
Aaron Bertrand
fuente
Probablemente en gran parte porque las tablas temporales se crean realmente en TempDB y un esquema local no funcionaría (a menos que estuvieras realmente en TempDB, por supuesto)
Kenneth Fisher
Entonces, claramente hay un código que ignora el nombre del esquema al crear una tabla temporal; y ese código es silencioso
Max Vernon