Apakah CREATE TABLE SomeSchema. # TempTableName memiliki bug?

12

Test-bed sederhana:

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;

Di atas harus membuat tabel sementara bernama #MyTempTabledi tempdb di bawah skema bernama SomeSchema; namun tidak demikian. Sebagai gantinya tabel dibuat di menudbo skema.

Apakah ini perilaku yang diharapkan? Saya menyadari ini jelas merupakan kasus tepi di sekitar penggunaan tabel temp skema khusus; namun akan lebih baik jika mesin memberikan kesalahan saat mencoba membuat tabel sementara skema-terikat, atau benar-benar mengikatnya ke skema yang ditentukan dalam DDL.

Juga, saya saat ini tidak memiliki akses ke SQL Server 2014 atau 2016; apakah itu berfungsi seperti yang diharapkan pada platform tersebut?

Max Vernon
sumber
Kit Pelatihan untuk 70-461 menyatakan bahwa 'Tabel sementara dibuat dalam tempdb dalam skema dbo.', Namun itu tidak masuk ke info lebih dari itu, jadi saya tidak yakin apakah itu hanya berarti ketika Anda tidak ' t menentukan skema.
Mark Sinkinson

Jawaban:

11

Kedua referensi tersebut valid dan akan diselesaikan dengan benar, tetapi tabel #temp dibuat di bawah dboskema.

Jawaban yang sama (pada sistem Anda, beberapa nomor saya tidak bisa menebak):

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

Jawaban yang sama (keduanya 1, yaitu 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');

Mampu menentukan skema tidak memberi Anda apa-apa karena Anda tidak akan memiliki tabrakan (dua tabel #temp dengan nama yang sama di bawah skema yang berbeda) dalam satu sesi, bukan?

Ini adalah perilaku yang diharapkan. Tabel #temp diikat ke sebuah sesi, tetapi tidak ke skema tertentu. Dan itu berfungsi sama sampai 2016 CTP 3.2. Pengurai mungkin memaafkan, memungkinkan nama skema yang tidak berarti dalam banyak cara yang sama memungkinkan pengelompokan koma sesat ini:

CREATE TABLE dbo.foo 
(
        bar INT
        ,
);
Aaron Bertrand
sumber
Mungkin sebagian besar karena tabel temp sebenarnya dibuat di TempDB dan skema lokal tidak akan berfungsi (kecuali Anda benar-benar di TempDB tentu saja)
Kenneth Fisher
Jadi jelas ada kode yang mengabaikan nama skema saat membuat tabel sementara; dan kode itu diam.
Max Vernon