SQLServer テーブル定義の取得

不具合修正版

テーブル定義情報を取得してExcelに出力する (テーブル別)

テーブル定義 取得用 SQL

lesson014.sql


select
C.NAME SCHEMA_NAME
, K.VALUE TABLE_COMMENT
, B.NAME TABLE_NAME
, A.COLUMN_ID
, A.NAME COLUMN_NAME
, L.VALUE COLUMN_COMMENT
, D.DATA_TYPE
, D.CHARACTER_MAXIMUM_LENGTH
, D.NUMERIC_PRECISION
, D.NUMERIC_SCALE
, case D.IS_NULLABLE when 'YES' then '' else 'NO' end IS_NULLABLE
, isnull(D.COLUMN_DEFAULT, '') COLUMN_DEFAULT
--
, isnull(G1.CONSTRAINT_NAME, '') PRIMARY_KEY
, isnull(G2.CONSTRAINT_NAME, '') FOREIGN_KEY
, isnull(G3.CONSTRAINT_NAME, '') UNIQUE_KEY
--
, isnull(J1.NAME, '') INDEX1_NAME
, isnull(J1.TYPE_DESC, '') INDEX1_TYPE
, isnull(J1.INDEX_COLUMN_ID, '') INDEX1_COLUMN_ID
, isnull(M1.VALUE, '') INDEX1_COMMENT
--
, isnull(J2.NAME, '') INDEX2_NAME
, isnull(J2.TYPE_DESC, '') INDEX2_TYPE
, isnull(J2.INDEX_COLUMN_ID, '') INDEX2_COLUMN_ID
, isnull(M2.VALUE, '') INDEX2_COMMENT
--
, isnull(J3.NAME, '') INDEX3_NAME
, isnull(J3.TYPE_DESC, '') INDEX3_TYPE
, isnull(J3.INDEX_COLUMN_ID, '') INDEX3_COLUMN_ID
, isnull(M3.VALUE, '') INDEX3_COMMENT
--
, isnull(J4.NAME, '') INDEX4_NAME
, isnull(J4.TYPE_DESC, '') INDEX4_TYPE
, isnull(J4.INDEX_COLUMN_ID, '') INDEX4_COLUMN_ID
, isnull(M4.VALUE, '') INDEX4_COMMENT
--
, isnull(J5.NAME, '') INDEX5_NAME
, isnull(J5.TYPE_DESC, '') INDEX5_TYPE
, isnull(J5.INDEX_COLUMN_ID, '') INDEX5_COLUMN_ID
, isnull(M5.VALUE, '') INDEX5_COMMENT
--
from
sys.columns A
--
inner join
sys.tables B
on
B.object_id = A.object_id
inner join
sys.schemas C
on
C.SCHEMA_ID = B.SCHEMA_ID
--
inner join
information_schema.columns D
on
D.TABLE_SCHEMA = C.NAME
and D.TABLE_NAME = B.NAME
and D.COLUMN_NAME = A.NAME
--
left join
(
select
F1.TABLE_CATALOG
, F1.TABLE_SCHEMA
, F1.TABLE_NAME
, F1.COLUMN_NAME
, E1.CONSTRAINT_NAME
, E1.CONSTRAINT_TYPE
from
information_schema.table_constraints E1
inner join
information_schema.key_column_usage F1
on
F1.CONSTRAINT_NAME = E1.CONSTRAINT_NAME
where
E1.CONSTRAINT_TYPE = 'PRIMARY KEY'
)
G1
on
( G1.TABLE_CATALOG = D.TABLE_CATALOG )
and ( G1.TABLE_SCHEMA = D.TABLE_SCHEMA )
and ( G1.TABLE_NAME = D.TABLE_NAME )
and ( G1.COLUMN_NAME = D.COLUMN_NAME )
--
left join
(
select
F2.TABLE_CATALOG
, F2.TABLE_SCHEMA
, F2.TABLE_NAME
, F2.COLUMN_NAME
, E2.CONSTRAINT_NAME
, E2.CONSTRAINT_TYPE
from
information_schema.table_constraints E2
inner join
information_schema.key_column_usage F2
on
F2.CONSTRAINT_NAME = E2.CONSTRAINT_NAME
where
E2.CONSTRAINT_TYPE = 'FOREIGN KEY'
)
G2
on
( G2.TABLE_CATALOG = D.TABLE_CATALOG )
and ( G2.TABLE_SCHEMA = D.TABLE_SCHEMA )
and ( G2.TABLE_NAME = D.TABLE_NAME )
and ( G2.COLUMN_NAME = D.COLUMN_NAME )
--
left join
(
select
F3.TABLE_CATALOG
, F3.TABLE_SCHEMA
, F3.TABLE_NAME
, F3.COLUMN_NAME
, E3.CONSTRAINT_NAME
, E3.CONSTRAINT_TYPE
from
information_schema.table_constraints E3
inner join
information_schema.key_column_usage F3
on
F3.CONSTRAINT_NAME = E3.CONSTRAINT_NAME
where
E3.CONSTRAINT_TYPE = 'UNIQUE'
)
G3
on
( G3.TABLE_CATALOG = D.TABLE_CATALOG )
and ( G3.TABLE_SCHEMA = D.TABLE_SCHEMA )
and ( G3.TABLE_NAME = D.TABLE_NAME )
and ( G3.COLUMN_NAME = D.COLUMN_NAME )
--
left join
(
select
H1.object_id
, H1.INDEX_ID
, H1.NAME
, H1.TYPE_DESC
, I1.COLUMN_ID
, I1.INDEX_COLUMN_ID
from
sys.indexes H1
inner join
sys.index_columns I1
on
( I1.object_id = H1.object_id )
and ( I1.INDEX_ID = H1.INDEX_ID )
where
( H1.INDEX_ID = 1 )
)
J1
on
J1.object_id = A.object_id
and J1.COLUMN_ID = A.COLUMN_ID
--
left join
(
select
H2.object_id
, H2.INDEX_ID
, H2.NAME
, H2.TYPE_DESC
, I2.COLUMN_ID
, I2.INDEX_COLUMN_ID
from
sys.indexes H2
inner join
sys.index_columns I2
on
( I2.object_id = H2.object_id )
and ( I2.INDEX_ID = H2.INDEX_ID )
where
( H2.INDEX_ID = 2 )
)
J2
on
J2.object_id = A.object_id
and J2.COLUMN_ID = A.COLUMN_ID
--
left join
(
select
H3.object_id
, H3.INDEX_ID
, H3.NAME
, H3.TYPE_DESC
, I3.COLUMN_ID
, I3.INDEX_COLUMN_ID
from
sys.indexes H3
inner join
sys.index_columns I3
on
( I3.object_id = H3.object_id )
and ( I3.INDEX_ID = H3.INDEX_ID )
where
( H3.INDEX_ID = 3 )
)
J3
on
J3.object_id = A.object_id
and J3.COLUMN_ID = A.COLUMN_ID
--
left join
(
select
H4.object_id
, H4.INDEX_ID
, H4.NAME
, H4.TYPE_DESC
, I4.COLUMN_ID
, I4.INDEX_COLUMN_ID
from
sys.indexes H4
inner join
sys.index_columns I4
on
( I4.object_id = H4.object_id )
and ( I4.INDEX_ID = H4.INDEX_ID )
where
( H4.INDEX_ID = 4 )
)
J4
on
J4.object_id = A.object_id
and J4.COLUMN_ID = A.COLUMN_ID
--
left join
(
select
H5.object_id
, H5.INDEX_ID
, H5.NAME
, H5.TYPE_DESC
, I5.COLUMN_ID
, I5.INDEX_COLUMN_ID
from
sys.indexes H5
inner join
sys.index_columns I5
on
( I5.object_id = H5.object_id )
and ( I5.INDEX_ID = H5.INDEX_ID )
where
( H5.INDEX_ID = 5 )
)
J5
on
J5.object_id = A.object_id
and J5.COLUMN_ID = A.COLUMN_ID
--
left join
sys.extended_properties K
on
( K.CLASS = 1 )
and ( K.MAJOR_ID = B.object_id )
and ( K.MINOR_ID = 0 )
--
left join
sys.extended_properties L
on
( L.CLASS = 1 )
and ( L.MAJOR_ID = B.object_id )
and ( L.MINOR_ID = A.COLUMN_ID )
--
left join
sys.extended_properties M1
on
( M1.CLASS = 7 )
and ( M1.MAJOR_ID = B.object_id )
and ( M1.MINOR_ID = J1.INDEX_ID )
--
left join
sys.extended_properties M2
on
( M2.CLASS = 7 )
and ( M2.MAJOR_ID = B.object_id )
and ( M2.MINOR_ID = J2.INDEX_ID )
--
left join
sys.extended_properties M3
on
( M3.CLASS = 7 )
and ( M3.MAJOR_ID = B.object_id )
and ( M3.MINOR_ID = J3.INDEX_ID )
--
left join
sys.extended_properties M4
on
( M4.CLASS = 7 )
and ( M4.MAJOR_ID = B.object_id )
and ( M4.MINOR_ID = J4.INDEX_ID )
--
left join
sys.extended_properties M5
on
( M5.CLASS = 7 )
and ( M5.MAJOR_ID = B.object_id )
and ( M5.MINOR_ID = J5.INDEX_ID )
--
where
( B.TYPE_DESC = 'USER_TABLE' )
order by
B.NAME
, A.COLUMN_ID

接続文字列

lesson004.con


DRIVER={SQL Server};SERVER=xxxxxx;DataBase=adventureworksdw;UID=yyyyyy;PWD=zzzzzz;

Excel出力用スクリプト

lesson015.vbs

Option Explicit

Private fs
Set fs = CreateObject("Scripting.FileSystemObject")

'接続文字列 読み込み
Private tsCon
Set tsCon = fs.OpenTextFile(WScript.Arguments(0))

Private sCon
sCon = ""
If Not tsCon.AtEndOfStream Then
    sCon = tsCon.ReadLine
End If
tsCon.Close
Set tsCon = Nothing

'接続
Private con
Set con = CreateObject("ADODB.Connection")
With con
    .Provider         = "SQLOLEDB"
    .ConnectionString = sCon
    .Open
End With

'SQL 読み込み
Private tsSql
Set tsSql = fs.OpenTextFile(WScript.Arguments(1))

Private sSql
sSql = ""
Do Until tsSql.AtEndOfStream
    sSql = sSql & tsSql.ReadLine & vbNewLine
Loop
tsSql.Close
Set tsSql = Nothing
Set fs    = Nothing

Dim rs
Set rs = CreateObject("ADODB.Recordset")
With rs
    .ActiveConnection = con
    .CursorType       = 0 'adOpenForwardOnly
    .LockType         = 1 'adLockReadOnly
    .Source           = sSql
    .Open
End With


If Not rs.EOF Then
    '結果を Excel に保存
    Dim excelApp
    Set excelApp = CreateObject("Excel.Application")
    excelApp.Visible       = True
    excelApp.DisplayAlerts = False '警告メッセージをOFF

    'ブックを書き込み用で開く
    Dim excelBook
    Set excelBook = excelApp.Workbooks.Add

    'シートを1枚だけにする
    Dim iSheet
    For iSheet = excelBook.WorkSheets.Count To 2 Step -1
        excelBook.WorkSheets(iSheet).Delete
    Next

    Dim tableNameList()
    Dim tableCount: tableCount = -1
    Dim tableName:  tableName  = ""

    Dim iRow:       iRow       = 0
    Dim iCol:       iCol       = 0
    Dim excelSheet

    Do Until rs.EOF
        If tableName <> rs("table_name") & "" Then
            tableName = rs("table_name") & ""

            tableCount = tableCount + 1
            ReDim Preserve tableNameList(tableCount)
            tableNameList(tableCount) = tableName

            excelBook.Sheets.Add , excelBook.WorkSheets(tableCount + 1)

            Set excelSheet  = excelBook.WorkSheets(tableCount + 2)
            excelSheet.Name = tableName

            excelSheet.Cells(1,  1).Value = "No."
            excelSheet.Cells(1,  2).Value = "項目名"
            excelSheet.Cells(1,  3).Value = ""
            excelSheet.Cells(1,  4).Value = "型"
            excelSheet.Cells(1,  5).Value = "長さ"
            excelSheet.Cells(1,  6).Value = "小数部"
            excelSheet.Cells(1,  7).Value = "初期値"
            excelSheet.Cells(1,  8).Value = "必須"
            excelSheet.Cells(1,  9).Value = "PRIMARY KEY (CLUSTERED)"
            excelSheet.Cells(1, 10).Value = "PRIMARY KEY (NONCLUSTERED)"
            excelSheet.Cells(1, 11).Value = "UNIQUE KEY"
            excelSheet.Cells(1, 12).Value = "INDEX 1"
            excelSheet.Cells(1, 13).Value = "INDEX 2"
            excelSheet.Cells(1, 14).Value = "INDEX 3"
            excelSheet.Cells(1, 15).Value = "INDEX 4"
            excelSheet.Cells(1, 16).Value = "INDEX 5"
            excelSheet.Cells(1, 17).Value = "FOREIGN KEY"

            iRow = 1
        End If
        iRow = iRow + 1
        iCol = 0

        'No.
        iCol = iCol + 1
        excelSheet.Cells(iRow, iCol).Value = rs("COLUMN_ID") & ""

        '項目名
        iCol = iCol + 1
        excelSheet.Cells(iRow, iCol).Value =  rs("column_name") & ""

        '項目説明
        iCol = iCol + 1
        excelSheet.Cells(iRow, iCol).Value =  rs("COLUMN_COMMENT") & ""

        '型
        iCol = iCol + 1
        excelSheet.Cells(iRow, iCol).Value =  rs("data_type") & ""

        '長さ
        iCol = iCol + 1
        Select Case LCase(rs("data_type") & "")
            Case "nvarchar", "nchar", "varchar", "char"
                excelSheet.Cells(iRow, iCol).Value =  rs("character_maximum_length") & ""
            Case "decimal"
                excelSheet.Cells(iRow, iCol).Value =  rs("numeric_precision")        & ""
        End Select

        '小数部
        iCol = iCol + 1
        Select Case LCase(rs("data_type") & "")
            Case "decimal"
                excelSheet.Cells(iRow, iCol).Value = rs("numeric_scale") & ""
        End Select

        '初期値
        iCol = iCol + 1
        excelSheet.Cells(iRow, iCol).Value = rs("column_default") & ""

        '必須
        iCol = iCol + 1
        Dim s: s = rs("is_nullable") & ""
        If UCase(s) = "NO" Then
            excelSheet.Cells(iRow, iCol).Value = "○"
        End If

        'INDEX
        Dim indexType: ReDim indexType(5)
        Dim idx
        For idx = 1 To 5
            If rs("INDEX" & idx & "_NAME") & "" <> "" Then
                If rs("INDEX" & idx & "_NAME") & "" = rs("PRIMARY_KEY") & "" Then
                        indexType(idx) = rs("INDEX" & idx & "_TYPE") & " PRIMARY KEY"
                ElseIf rs("INDEX" & idx & "_NAME") & "" = rs("UNIQUE_KEY")  & "" Then
                        indexType(idx) = "UNIQUE KEY"
                Else
                        indexType(idx) = ""
                End If
            End If
        Next

        'PRIMARY KEY (CLUSTERED)
        iCol = iCol + 1
        For idx = 1 To 5
            If rs("INDEX" & idx & "_COLUMN_ID") & "" <> "0" Then
                If indexType(idx) = "CLUSTERED PRIMARY KEY" Then
                    excelSheet.Cells(iRow, iCol).Value = rs("INDEX" & idx & "_COLUMN_ID") & ""
                    Exit For
                End If
            End If
        Next

        'PRIMARY KEY (NONCLUSTERED)
        iCol = iCol + 1
        For idx = 1 To 5
            If rs("INDEX" & idx & "_COLUMN_ID") & "" <> "0" Then
                If indexType(idx) = "NONCLUSTERED PRIMARY KEY" Then
                    excelSheet.Cells(iRow, iCol).Value = rs("INDEX" & idx & "_COLUMN_ID") & ""
                    Exit For
                End If
            End If
        Next

        'UNIQUE KEY
        iCol = iCol + 1
        For idx = 1 To 5
            If rs("INDEX" & idx & "_COLUMN_ID") & "" <> "0" Then
                If indexType(idx) = "UNIQUE KEY" Then
                    excelSheet.Cells(iRow, iCol).Value = rs("INDEX" & idx & "_COLUMN_ID") & ""
                    Exit For
                End If
            End If
        Next

        'OTHER INDEX
        For idx = 1 To 5
            iCol = iCol + 1
            If rs("INDEX" & idx & "_COLUMN_ID") & "" <> "0" Then
                If indexType(idx) = "" Then
                    excelSheet.Cells(iRow, iCol).Value = rs("INDEX" & idx & "_COLUMN_ID") & ""
                End If
            End If
        Next

        'FOREIGN KEY
        iCol = iCol + 1
        If rs("FOREIGN_KEY") & "" <> "" Then
            excelSheet.Cells(iRow, iCol).Value = "○"
        End If

        rs.MoveNext
    Loop

    Set excelSheet  = excelBook.WorkSheets(1)
    excelSheet.Name = "テーブル一覧"

    For iRow = 1 To tableCount + 1
        excelSheet.Cells(iRow, 1).Value = tableNameList(iRow - 1)
        excelSheet.Hyperlinks.Add excelSheet.Cells(iRow, 1), "", tableNameList(iRow - 1) & "!A1"
    Next

    'ブックを保存する
    excelBook.SaveAs(WScript.Arguments(2))
    excelApp.Quit 
    Set excelApp = Nothing
End If
rs.Close

'切断
con.Close
Set con = Nothing
実行形式


C:\>cscript c:\study\vbscript\chapter006\lesson015.vbs c:\study\vbscript\chapte
r006\lesson004.con c:\study\vbscript\chapter006\lesson014.sql c:\study\vbscript\
chapter006\lesson15.xls //nologo

出力イメージ

Sheet : "AdventureWorksDWBuildVersion"

No. 項目名 長さ 小数部 初期値 必須 PRIMARY KEY
(CLUSTERED)
PRIMARY KEY
(NONCLUSTERED)
UNIQUE
KEY
INDEX
1
INDEX
2
INDEX
3
INDEX
4
INDEX
5
FOREIGN
KEY
1 DBVersion nvarchar 50                        
2 VersionDate datetime                          

Sheet : "DatabaseLog"

No. 項目名 長さ 小数部 初期値 必須 PRIMARY KEY
(CLUSTERED)
PRIMARY KEY
(NONCLUSTERED)
UNIQUE
KEY
INDEX
1
INDEX
2
INDEX
3
INDEX
4
INDEX
5
FOREIGN
KEY
1 DatabaseLogID int                        
2 PostTime datetime                        
3 DatabaseUser nvarchar 128                      
4 Event nvarchar 128                      
5 Schema nvarchar 128                        
6 Object nvarchar 128                        
7 TSQL nvarchar -1                      
8 XmlEvent xml                        

Sheet : "DimAccount"

No. 項目名 長さ 小数部 初期値 必須 PRIMARY KEY
(CLUSTERED)
PRIMARY KEY
(NONCLUSTERED)
UNIQUE
KEY
INDEX
1
INDEX
2
INDEX
3
INDEX
4
INDEX
5
FOREIGN
KEY
1 AccountKey int       1                
2 ParentAccountKey int                        
3 AccountCodeAlternateKey int                 1        
4 ParentAccountCodeAlternateKey int                          
5 AccountDescription nvarchar 50                        
6 AccountType nvarchar 50                        
7 Operator nvarchar 50                        
8 CustomMembers nvarchar 300                        
9 ValueType nvarchar 50                        
10 CustomMemberOptions nvarchar 200                        

Sheet : "DimCurrency"

No. 項目名 長さ 小数部 初期値 必須 PRIMARY KEY
(CLUSTERED)
PRIMARY KEY
(NONCLUSTERED)
UNIQUE
KEY
INDEX
1
INDEX
2
INDEX
3
INDEX
4
INDEX
5
FOREIGN
KEY
1 CurrencyKey int       1                
2 CurrencyAlternateKey nchar 3         1            
3 CurrencyName nvarchar 50                      

Sheet : "FactInternetSalesReason"

No. 項目名 長さ 小数部 初期値 必須 PRIMARY KEY
(CLUSTERED)
PRIMARY KEY
(NONCLUSTERED)
UNIQUE
KEY
INDEX
1
INDEX
2
INDEX
3
INDEX
4
INDEX
5
FOREIGN
KEY
1 SalesOrderNumber nvarchar 20         1          
2 SalesOrderLineNumber tinyint           2          
3 SalesReasonKey int           3