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.