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のトレーニングキットには、「一時テーブルはdboスキーマのtempdbに作成されます」と記載されていますが、それ以上の情報は含まれていません。 tスキーマを指定します。
マークシンキンソン16年

回答:


11

両方の参照は有効であり、正しく解決されますが、dboスキーマの下に#tempテーブルが作成されます。

同じ答え(あなたのシステムでは、私がおそらく推測できなかった数):

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
        ,
);

おそらく大部分は、一時テーブルが実際にTempDBで作成され、ローカルスキーマが機能しないためです(もちろん実際にTempDBを使用している場合を除きます)
ケネスフィッシャー

そのため、一時テーブルを作成するときにスキーマ名を無視するコードが明らかにあります。そのコードはサイレントです。
マックスヴァーノン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.