Есть ли в CREATE TABLE SomeSchema. # TempTableName ошибка?

12

Простой испытательный стенд:

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;

Выше следует создать временную таблицу с именем #MyTempTableв базе данных tempdb под именем схемы SomeSchema; однако это не так. Вместо этого таблица создается в dboсхеме.

Это ожидаемое поведение? Я понимаю, что это, безусловно, крайний случай использования временных таблиц для конкретной схемы; однако было бы неплохо, если бы движок либо выдавал ошибку при попытке создать привязанную к схеме временную таблицу, либо фактически связывал ее со схемой, указанной в DDL.

Кроме того, в настоящее время у меня нет доступа к SQL Server 2014 или 2016; это работает, как ожидалось, на этих платформах?

Макс Вернон
источник
Обучающий комплект для 70-461 гласит, что «Временные таблицы создаются в базе данных tempdb в схеме dbo», однако в нем больше нет информации, поэтому я не уверен, что это означает, только когда вы этого не сделаете » Не указывайте схему.
Марк Синкинсон

Ответы:

11

Обе ссылки действительны и разрешатся правильно, но таблица #temp создается в dboсхеме.

Тот же ответ (в вашей системе какое-то число, которое я не мог догадаться):

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

Тот же ответ (оба 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');

Возможность указать схему ничего не дает, потому что у вас не будет коллизий (двух таблиц #temp с одинаковыми именами в разных схемах) внутри сессии, верно?

Это ожидаемое поведение. Таблица #temp привязана к сеансу, но не к конкретной схеме. И он работает одинаково вплоть до 2016 года ОСАГО 3.2. Синтаксический анализатор, вероятно, прощает, разрешая бессмысленное имя схемы во многом так же, как допускает эту ошибочную запятую:

CREATE TABLE dbo.foo 
(
        bar INT
        ,
);
Аарон Бертран
источник
Вероятно, во многом потому, что временные таблицы фактически создаются в TempDB, а локальная схема не будет работать (если, конечно, вы не были в TempDB, конечно)
Кеннет Фишер
Таким образом, очевидно, что есть код, который игнорирует имя схемы при создании временной таблицы; и этот код молчит.
Макс Вернон