0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

最新版テーブル定義出力クエリ、及び一時テーブルのテーブル定義確認

Last updated at Posted at 2019-09-23

【序文】

一時テーブルのテーブル定義を確認しようとして少し嵌ったので忘備録として残す。

【環境】

SQLServer
2017
設定はデフォルト。

【テーブル定義の確認方法】

一般的なテーブル定義の確認方法は以下。
テーブルの定義の表示 - SQL Server _ Microsoft Docs

システムストアドプロシージャを利用する場合は以下。
カタログ ストアド プロシージャ (TRANSACT-SQL) - SQL Server _ Microsoft Docs
sp_help (TRANSACT-SQL) - SQL Server _ Microsoft Docs
sp_tables (TRANSACT-SQL) - SQL Server _ Microsoft Docs
sp_columns (TRANSACT-SQL) - SQL Server _ Microsoft Docs

しかし、これらの方法で一時テーブルを確認するも出てこない。???
探し方が悪い?

【一時テーブルはどこにある?】

CREATE TABLE (Transact-SQL) - SQL Server _ Microsoft Docs

tempdb の sysobjects テーブルに格納される一時テーブルのフル ネームは、CREATE TABLE ステートメントで指定されたテーブル名とシステムが生成する数値サフィックスから構成されます。

そうそう、一時テーブルは tempdb に作成される。それは知っていたけれど……。
前述システムストアドプロシージャはカレントのデータベースに対して機能する。つまり、明示的に tempdb に切り替える必要がある。

まず一時テーブル作成。

SELECT * INTO #TempTbl FROM (VALUES ('A', 1))t([Col1], [Col2]);

tempdb 直下に一時テーブルが作成される。

次に一時テーブルの確認。

USE tempdb;
GO 
EXEC sp_tables @table_name = N'%';
EXEC sp_help N'#TempTbl';
EXEC sp_columns @table_name = N'#TempTbl';
GO

【最新版テーブル定義出力クエリ】

久しぶりにテーブル定義関連のシステムビューについて調べてみると、こんな情報が。

sys.sysobjects (TRANSACT-SQL) - SQL Server _ Microsoft Docs

この SQL Server 2000 システム テーブルは、下位互換性を保つためにビューとして含まれています。 代わりに、現在の SQL Server システム ビューを使用することをお勧めします。 対応するシステム ビューを調べるには、「システム テーブルのシステム ビューへのマッピング (Transact-SQL)」をご覧ください。 この機能は、Microsoft SQL Server の将来のバージョンで削除されます。 新規の開発作業ではこの機能を使用しないようにし、現在この機能を使用しているアプリケーションは修正することを検討してください。

システム テーブルのマッピング システム ビュー (TRANSACT-SQL) - SQL Server _ Microsoft Docs

うーむ、いつの間にそんなことに。
テーブル定義を出力するクエリってのは定番ネタだと思うけど、改めてぐぐってみても、参照しているビューが古かったり、作りがイマイチだったり。
そんな訳で実装してみた。カレントデータベースが対象。

DECLARE @SchemaName     sysname = N'dbo';       -- スキーマ名
DECLARE @TableName      sysname = N'Table_1';   -- テーブル名

SELECT
      [Col].name                                            [名称]              -- 列の名前。オブジェクト内で一意。
    , [Typ].name                                            []                -- 型
    , CASE
        WHEN [Typ].user_type_id IN (106, 108)                                   THEN LTRIM(STR([Col].precision))        -- decimal, numeric
        WHEN [Typ].user_type_id IN (165, 167, 231) AND [Col].max_length = -1    THEN N'MAX'                             -- varbinary, varchar, nvarchar
        WHEN [Typ].user_type_id IN (231, 239)                                   THEN LTRIM(STR([Col].max_length / 2))   -- nvarchar, nchar
        WHEN [Typ].user_type_id IN (165, 167, 173, 175)                         THEN LTRIM(STR([Col].max_length))       -- varbinary, varchar, binary, char
        WHEN [Typ].user_type_id IN (60, 61, 122) OR [Typ].scale = 0             THEN N''                                -- money, datetime, smallmoney
        ELSE                                                                         LTRIM(STR([Col].scale))            -- time, datetime2, datetimeoffset
      END                                                   [桁数]              -- 数値ベースの場合は、列の有効桁数。
    , IIF([Typ].user_type_id IN (106, 108), LTRIM(STR([Col].scale)), N'')                                               -- decimal, numeric
                                                            [小数部]            -- 数値に基づく場合は列の小数点以下桁数
    , LEFT(N'○', [Col].is_nullable)                        [NULLを許容]        -- 1 = 列で NULL 値を使用できます
    , ISNULL(LTRIM(STR([Idx].index_column_id)), '')         [PK]                -- PK
    , ISNULL([Prp].value, N'')                              [コメント]          -- コメント
FROM sys.tables                                             [Tbl]               -- テーブル情報
INNER JOIN sys.columns                                      [Col]               -- 列情報
    ON  [Tbl].object_id         = [Col].object_id                               -- オブジェクトの ID
INNER JOIN sys.types                                        [Typ]               -- オブジェクトの ID
    ON  [Col].user_type_id      = [Typ].user_type_id                            -- 型の内部システム型の ID
LEFT OUTER JOIN sys.index_columns                           [Idx]               -- インデクス
    ON  [Tbl].object_id         = [Idx].object_id                               -- オブジェクトの ID
    AND [Col].column_id         = [Idx].column_id                               -- 列の ID
    AND [Idx].index_id          = 1                                             -- PK
LEFT OUTER JOIN sys.extended_properties                     [Prp]               -- 拡張プロパティ
    ON  [Tbl].object_id         = [Prp].major_id                                -- オブジェクトの ID
    AND [Col].column_id         = [Prp].minor_id                                -- 拡張プロパティが属するアイテムのセカンダリ ID
    AND [Prp].class             = 1                                             -- プロパティが存在するアイテムのクラスを識別します。1 = オブジェクトまたは列
    AND [Prp].class_desc        = N'OBJECT_OR_COLUMN'                           -- 拡張プロパティが存在するクラスの説明
    AND [Prp].name              = N'MS_Description'                             -- class、major_id、および minor_id で一意となるプロパティ名
WHERE   [Tbl].schema_id         = SCHEMA_ID(@SchemaName)                        -- スキーマ ID
    AND [Tbl].object_id         = OBJECT_ID(@SchemaName + N'.' + @TableName)    -- オブジェクトの ID
ORDER BY
      [Col].[column_id]         -- 列の ID
;

真面目に実装すると、桁数の判定がすげー面倒。
それと PK。公式ヘルプには記載が見当たらないようだけど、sys.index_columns.index_id が 1 のものが PK のようだったのでそう判定している。違ったらゴメンってことで。

【参照公式ヘルプ】

システムビュー/システム関数 説明
sys.columns ビューやテーブルなど、列を持つオブジェクトの列ごとに 1 行のデータを返します
sys.extended_properties 現在のデータベース内の拡張プロパティごとに 1 行のデータを返します
sys.index_columns 列の一部であるごとに 1 行が含まれています、 sys.indexesインデックスまたは順序付けられていないテーブル (ヒープ)
sys.indexes テーブル、ビュー、テーブル値関数など、テーブル オブジェクトのインデックスまたはヒープごとに 1 行のデータを格納します
sys.objects ネイティブ コンパイルのスカラー ユーザー定義関数を含む、データベース内で作成されるユーザー定義のスキーマ スコープ オブジェクトごとに行が含まれています
sys.schemas データベース スキーマごとに 1 行が含まれています
sys.tables 各ユーザー テーブルの行を返します
sys.types システム型とユーザー定義の型ごとに 1 行のデータを格納します
SCHEMA_ID スキーマ名に関連付けられているスキーマ ID を返します
OBJECT_ID スキーマ スコープ オブジェクトのデータベース オブジェクト ID 番号を返します
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?