web-dev-qa-db-ja.com

CREATE TABLE SomeSchema。#TempTableNameにはバグがありますか?

簡単なテストベッド:

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;

上記すべきSomeSchemaというスキーマの下のtempdbに#MyTempTableという一時テーブルを作成します。ただし、そうではありません。代わりに、テーブルはdboスキーマに作成されます。

これは予想される動作ですか?これは確かにスキーマ固有の一時テーブルの使用に関するエッジケースであることに気づきました。ただし、スキーマにバインドされた一時テーブルを作成しようとしたときにエンジンがエラーを提供したか、実際にそれをDDLで指定されたスキーマにバインドした場合、それは良いことです。

また、現在SQL Server 2014または2016にアクセスできません。それらのプラットフォームで期待どおりに動作しますか?

12
Max Vernon

どちらの参照も有効であり、正しく解決されますが、#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');

セッション内で衝突(異なるスキーマの下にある2つの同じ名前の#tempテーブル)が発生しないので、スキーマを指定できても何も購入しません。

これは予想される動作です。 #tempテーブルはセッションに関連付けられていますが、特定のスキーマには関連付けられていません。また、2016 CTP 3.2までは同じように機能します。パーサーはおそらく寛容であり、この誤った末尾のコンマを許可するのとほぼ同じ方法で無意味なスキーマ名を許可します。

CREATE TABLE dbo.foo 
(
        bar INT
        ,
);
11
Aaron Bertrand