Hat CREATE TABLE SomeSchema. # TempTableName einen Fehler?

12

Einfacher Prüfstand:

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;

Das Obige sollte eine temporäre Tabelle erstellen, die #MyTempTablein der Tempdb unter dem angegebenen Schema benannt ist SomeSchema. dies ist jedoch nicht der Fall. Stattdessen wird die Tabelle im dboSchema erstellt.

Ist das erwartetes Verhalten? Mir ist klar, dass dies sicherlich ein Randfall bei der Verwendung schemaspezifischer temporärer Tabellen ist. Es wäre jedoch schön, wenn die Engine beim Versuch, eine schemagebundene temporäre Tabelle zu erstellen, entweder einen Fehler liefern würde oder sie tatsächlich an das in der DDL angegebene Schema binden würde.

Außerdem habe ich derzeit keinen Zugriff auf SQL Server 2014 oder 2016. Funktioniert es auf diesen Plattformen wie erwartet?

Max Vernon
quelle
Das Training Kit für 70-461 besagt, dass temporäre Tabellen in tempdb im Dbo-Schema erstellt werden. Es enthält jedoch keine weiteren Informationen. t Geben Sie ein Schema an.
Mark Sinkinson

Antworten:

11

Beide Verweise sind gültig und werden korrekt aufgelöst, aber die # temporäre Tabelle wird unter dem dboSchema erstellt.

Dieselbe Antwort (auf Ihrem System eine Nummer, die ich unmöglich erraten konnte):

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

Gleiche Antwort (beide 1 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');

Die Angabe eines Schemas bringt Ihnen nichts, weil Sie in einer Sitzung keine Kollisionen haben werden (zwei gleichnamige # temporäre Tabellen unter verschiedenen Schemas), oder?

Dies ist das erwartete Verhalten. Eine # temporäre Tabelle ist an eine Sitzung gebunden, jedoch nicht an ein bestimmtes Schema. Und es funktioniert bis 2016 CTP 3.2 genauso. Der Parser verzeiht wahrscheinlich und lässt den bedeutungslosen Schemanamen auf die gleiche Weise zu, wie dies bei diesem fehlerhaften nachgestellten Komma der Fall ist:

CREATE TABLE dbo.foo 
(
        bar INT
        ,
);
Aaron Bertrand
quelle
Wahrscheinlich zu einem großen Teil, weil temporäre Tabellen tatsächlich in TempDB erstellt werden und ein lokales Schema nicht funktionieren würde (es sei denn, Sie wären tatsächlich in TempDB)
Kenneth Fisher
Es gibt also eindeutig Code, der den Schemanamen beim Erstellen einer temporären Tabelle ignoriert. und dieser Code ist still.
Max Vernon