CREATE TABLE SomeSchema. # TempTableName tem um erro?

12

Cama de teste simples:

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;

O acima deve criar uma tabela temporária nomeada #MyTempTableno tempdb sob o esquema nomeado SomeSchema; no entanto não. Em vez disso, a tabela é criada no dboesquema.

Esse comportamento é esperado? Sei que esse é certamente um caso de vantagem em torno do uso de tabelas temporárias específicas do esquema; no entanto, seria bom se o mecanismo fornecesse um erro ao tentar criar uma tabela temporária vinculada ao esquema ou realmente o vinculasse ao esquema especificado na DDL.

Além disso, atualmente não tenho acesso ao SQL Server 2014 ou 2016; funciona como esperado nessas plataformas?

Max Vernon
fonte
O Kit de treinamento para 70-461 afirma que 'Tabelas temporárias são criadas em tempdb no esquema dbo.' t especifique um esquema.
Mark Sinkinson

Respostas:

11

Ambas as referências são válidas e serão resolvidas corretamente, mas a tabela #temp é criada no dboesquema.

Mesma resposta (no seu sistema, algum número que eu não poderia adivinhar):

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

Mesma resposta (ambos 1, que é 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');

Ser capaz de especificar um esquema não comprará nada para você, porque você não terá colisões (duas tabelas #temp com o mesmo nome em esquemas diferentes) em uma sessão, certo?

Este é o comportamento esperado. Uma tabela #temp está vinculada a uma sessão, mas não a um esquema específico. E funciona da mesma maneira até o CTP 3.2 de 2016. O analisador provavelmente está perdoando, permitindo o nome do esquema sem sentido da mesma maneira que permite essa vírgula à direita:

CREATE TABLE dbo.foo 
(
        bar INT
        ,
);
Aaron Bertrand
fonte
Provavelmente, em grande parte porque tabelas temporárias são realmente criadas no TempDB e um esquema local não iria funcionar (a menos que você estava realmente em TempDB é claro)
Kenneth Fisher
Portanto, existe claramente um código que ignora o nome do esquema ao criar uma tabela temporária; e esse código é silencioso.
Max Janon