CREATE TABLE SomeSchema. # TempTableName ha un bug?


12

Banco di prova semplice:

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;

Quanto sopra dovrebbe creare una tabella temporanea denominata #MyTempTablenel tempdb sotto lo schema denominato SomeSchema; tuttavia non lo fa. Invece la tabella viene creata nello dboschema.

Questo comportamento è previsto? Mi rendo conto che questo è certamente un caso limite attorno all'uso di tabelle temporanee specifiche dello schema; tuttavia sarebbe utile se il motore fornisse un errore durante il tentativo di creare una tabella temporanea associata allo schema o effettivamente lo associasse allo schema specificato nel DDL.

Inoltre, al momento non ho accesso a SQL Server 2014 o 2016; funziona come previsto su quelle piattaforme?


Il Training Kit per 70-461 afferma che "Le tabelle temporanee vengono create in tempdb nello schema dbo", tuttavia non contiene ulteriori informazioni, quindi non sono sicuro che ciò significhi solo quando non lo fai " t specificare uno schema.
— Mark Sinkinson,

Risposte:


11

Entrambi i riferimenti sono validi e verranno risolti correttamente, ma la tabella #temp viene creata nello dboschema.

Stessa risposta (sul tuo sistema, un numero che non riuscivo a indovinare):

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

Stessa risposta (sia 1, che è 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');

Essere in grado di specificare uno schema non ti compra nulla perché non avrai collisioni (due tabelle #temp con lo stesso nome in schemi diversi) all'interno di una sessione, giusto?

Questo è un comportamento previsto. Una tabella #temp è legata a una sessione, ma non a uno schema specifico. E funziona allo stesso modo fino al 2016 CTP 3.2. Il parser probabilmente perdona, consentendo il nome dello schema insignificante più o meno allo stesso modo in cui consente questa virgola finale errata:

CREATE TABLE dbo.foo 
(
        bar INT
        ,
);

Probabilmente in gran parte perché le tabelle temporanee sono effettivamente create in TempDB e uno schema locale non funzionerebbe (a meno che tu non fossi effettivamente in TempDB ovviamente)
— Kenneth Fisher,

Quindi esiste chiaramente un codice che ignora il nome dello schema durante la creazione di una tabella temporanea; e quel codice è silenzioso.
— Max Vernon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.