データベースをどのように文書化しますか?


227

私のクライアントのほとんどはデータベースをまったく文書化していないことがわかり、かなり怖いです。いくつかのより良いプラクティスを紹介するために、人々が使用しているツール/プロセスを知りたいと思います。

  • データベースをどのように文書化しますか?(SQLサーバー)
  • どのツールを使用していますか?
  • データベーススキーマ/メタデータのドキュメントストレージ形式?
    • Word文書
    • エクセルスプレッドシート
    • プレーンテキスト
  • 文書化プロセスまたはポリシー?

既存のデータベースのリバースエンジニアリング/文書化についてではなく、主にシステム/データベースを開発する際の文書化のベストプラクティスについてです。

回答:


78

拡張プロパティは非常に柔軟であるため、私は拡張プロパティを使用しています。ほとんどの標準的なドキュメントツールはオフMS_Descriptionにすることができ、独自のツールを使用して独自のツールを使用できます。

このプレゼンテーションを参照してください:#41-レバーを取得し、カメを選ぶ:メタデータでリフティング

このコード:http : //code.google.com/p/caderoux/wiki/LeversAndTurtles


3
何かを変更し、それに応じて拡張プロパティを変更するのを忘れて、それらを不正確にすることができます。そのような不一致を自動的に検出できますか?
AK

2
少なくとも、データベーススキーマ(sys.tables / sys.columns)を照会し、その拡張プロパティ(sys.extended_properties)への結合を残して、ドキュメント化されていないフィールドを特定し、そのスクリプトをデプロイ時に実行するテストに変えることができます。
ミカ

59

MicrosoftのVisio Pro(Visio 2010まで)は、CAのERwinと同様にデータベースをリバースエンジニアリングできます。Visioは安価なオプションですが、ERwinはより詳細で完全なオプションです。人々がそれらを見て気になるなら、拡張プロパティは素晴らしいです。Red GateのSQL Docなどを使用して、HTML形式でドキュメントを出力することもできます。

命名規則と適切に外部キーを設定すると、ほとんど自己文書化されたデータベースになります。目的の理解を深めるために、まだ外部ドキュメントが必要です。


よく知られた名前の外部キーデータベースであっても、単純なスキーマに欠けていることが多いのは、フィールドの説明です。私の経験では、すべてのフィールドが列名に収まるほど単純であるのは珍しいことです。
StockB


26

SQL Serverでは、拡張プロパティを使用しています。

次のPowerShellスクリプトを使用すると、dboスキーマ内の単一のテーブルまたはすべてのテーブルに対してテーブル作成スクリプトを生成できます。

このスクリプトには、Create tableコマンド、主キー、およびインデックスが含まれています。外部キーはコメントとして追加されます。テーブルおよびテーブル列の拡張プロパティがコメントとして追加されます。はい、複数行のプロパティがサポートされています。

スクリプトは、私の個人的なコーディングスタイルに合わせて調整されています。

  • 単一の列に個別の照合はありません。

  • 現在、SQL Server認証が必要です。

以下に、拡張プロパティを適切な古いASCIIドキュメントに変換する完全なコードを示します(ただし、テーブルを再作成するのに有効なSQLです)。

function Get-ScriptForTable
{
    param (
        $server, 
        $dbname,
        $user,
        $password,
        $filter
    )

[System.reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo")  | out-null

$conn = new-object "Microsoft.SqlServer.Management.Common.ServerConnection" 
$conn.ServerInstance = $server
$conn.LoginSecure = $false
$conn.Login = $user
$conn.Password = $password
$conn.ConnectAsUser = $false
$srv = New-Object "Microsoft.SqlServer.Management.Smo.Server" $conn

$Scripter = new-object ("Microsoft.SqlServer.Management.Smo.Scripter")
#$Scripter.Options.DriAll = $false
$Scripter.Options.NoCollation = $True
$Scripter.Options.NoFileGroup = $true
$scripter.Options.DriAll = $True
$Scripter.Options.IncludeIfNotExists = $False
$Scripter.Options.ExtendedProperties = $false
$Scripter.Server = $srv

$database = $srv.databases[$dbname]
$obj = $database.tables

$cnt = 1
$obj | % {

    if (! $filter -or  $_.Name -match $filter)
    {
        $lines = @()
        $header = "---------- {0, 3} {1, -30} ----------"  -f $cnt, $_.Name
        Write-Host $header 

        "/* ----------------- {0, 3} {1, -30} -----------------"  -f $cnt, $_.Name
        foreach( $i in $_.ExtendedProperties)
        {
            "{0}: {1}" -f $i.Name, $i.value
        }
        ""
        $colinfo = @{}
        foreach( $i in $_.columns)
        {
            $info = ""
            foreach ($ep in $i.ExtendedProperties)
            {
                if ($ep.value -match "`n")
                {
                    "----- Column: {0}  {1} -----" -f $i.name, $ep.name
                    $ep.value
                }
                else
                {
                    $info += "{0}:{1}  " -f $ep.name, $ep.value
                }
            }
            if ($info)
            {
                $colinfo[$i.name] =  $info
            }
        }
        ""
        "SELECT COUNT(*) FROM {0}" -f $_.Name
        "SELECT * FROM {0} ORDER BY 1" -f $_.Name
        "--------------------- {0, 3} {1, -30} ----------------- */" -f $cnt, $_.Name
        ""
        $raw = $Scripter.Script($_)
        #Write-host $raw
        $cont = 0
        $skip = $false 
        foreach ($line in $raw -split "\r\n")
        {
            if ($cont -gt 0)
            {
                if ($line -match "^\)WITH ")
                {
                    $line = ")"
                }
                $linebuf += ' ' + $line -replace " ASC", ""
                $cont--
                if ($cont -gt 0) { continue }
            }
            elseif ($line -match "^ CONSTRAINT ")
            {
                $cont = 3
                $linebuf = $line
                continue
            }
            elseif ($line -match "^UNIQUE ")
            {
                $cont = 3
                $linebuf = $line
                $skip = $true
                continue
            }
            elseif ($line -match "^ALTER TABLE.*WITH CHECK ")
            {
                $cont = 1
                $linebuf = "-- " + $line
                continue
            }
            elseif ($line -match "^ALTER TABLE.* CHECK ")
            {
                continue
            }
            else
            {
                $linebuf = $line
            }
            if ($linebuf -notmatch "^SET ")
            {
                if ($linebuf -match "^\)WITH ")
                {
                    $lines += ")"
                }
                elseif ($skip)
                {
                    $skip = $false
                }
                elseif ($linebuf -notmatch "^\s*$")
                {
                    $linebuf = $linebuf -replace "\]|\[", ""
                    $comment = $colinfo[($linebuf.Trim() -split " ")[0]]
                    if ($comment) { $comment = ' -- ' + $comment }
                    $lines += $linebuf + $comment
                }
            }
        }
        $lines += "go"
        $lines += ""
        $block = $lines -join "`r`n"
        $block
        $cnt++
        $used = $false
        foreach( $i in $_.Indexes)
        {
            $out = ''
            $raw = $Scripter.Script($i)
            #Write-host $raw
            foreach ($line in $raw -split "\r\n")
            {
                if ($line -match "^\)WITH ")
                {
                    $out += ")"
                }
                elseif ($line -match "^ALTER TABLE.* PRIMARY KEY")
                {
                    break
                }
                elseif ($line -match "^ALTER TABLE.* ADD UNIQUE")
                {
                    $out += $line -replace "\]|\[", "" -replace " NONCLUSTERED", "" 
                }
                elseif ($line -notmatch "^\s*$")
                {
                    $out += $line -replace "\]|\[", "" -replace "^\s*", "" `
                    -replace " ASC,", ", " -replace " ASC$", "" `
                    <#-replace "\bdbo\.\b", "" #> `
                    -replace " NONCLUSTERED", "" 
                }
                $used = $true
            }
            $block = "$out;`r`ngo`r`n"
            $out
        }
        if ($used)
        {
            "go"
        }
    }
} 
}

特定のデータベースの完全なdboスキーマをスクリプト化できます。

Get-ScriptForTable 'localhost'  'MyDB' 'sa' 'toipsecret'  |  Out-File  "C:\temp\Create_commented_tables.sql"

または、単一のテーブルのフィルター

Get-ScriptForTable 'localhost'  'MyDB' 'sa' 'toipsecret' 'OnlyThisTable'

21

SchemaCrawlerを見てください。これは、あなたが探していることを行うために設計した無料のコマンドラインツールです。SchemaCrawlerは、すべてのデータベーススキーマオブジェクトを含むテキストファイルを生成します。このテキスト出力は、人間が判読できるように設計されているだけでなく、別のサーバーからの類似の出力に対しても比較可能です。

実際には、ビルドの一部として行うと、データベーススキーマのテキストファイルを出力すると便利です。このようにして、テキストファイルをソースコード管理システムにチェックインし、スキーマが時間とともにどのように進化したかについてのバージョン履歴を取得できます。SchemaCrawlerは、コマンドラインからこれも自動化するように設計されています。


20

書かれている場合、文書はワード文書で構成されています。関係図がいくつか含まれます。テーブルのリストと、各テーブルが保持する内容と他のテーブルとの関係の簡単な説明。ドキュメントの1つの章には、セキュリティ設定が含まれています。アプリケーションに必要な「ユーザー」にはどのような権限がありますか?

一般的に、私が働いた会社では、データベース文書は、顧客が監査を行う者である場合にのみ記述されます。

免責事項:コードはドキュメントであるという態度をとる開発者が非常に多く、私もそれを犯しています。


10
コードに密接に結び付けられていないドキュメント(たとえば、自動生成されたスキーマダイアグラム+適切な名前のデータベースオブジェクトではなく、別のWordドキュメント)で見つけた大きな問題は、このドキュメントが間違っていることを保証することです時を経て。その理由は簡単です。別個のドキュメントが情報を効果的に複製します。ソースとの同期を維持する自動化された方法がなければ、非常に早く廃止されます。これを、データベースからライブでスキーマ図を生成し、コード内から適切なコメントを引き出すツールと比較してください。
ニックチャマス

16

拡張プロパティとRed Gates SQL Docを使用します。とてもうまくいきます!


14

おかしい、私は他の人もこれをどのようにやっているのだろうと思っていました。

私の最初の大きなデータベースプロジェクトの開発中に、Microsoft SQL Server Management Studio 10.0.1600.22はデータベースダイアグラムをサポートしており、必要に応じてドキュメントの詳細を追加できるワードドキュメントまたはその他のドキュメントソフトウェアにエクスポートできます。SQL Management Studioで接続したデータベースを展開し、オブジェクトエクスプローラーで[データベースダイアグラム]を右クリックし、[新しいデータベースダイアグラム]を選択して、異なるテーブル間のすべての関係を示す対話型ダイアグラムを生成します。ダイアグラムに含めるテーブルを指定することもできるため、1つずつドキュメント化しようとしている場合にイメージが不自然にならないようにできます。画像を他の編集ソフトウェアにエクスポートし、必要なだけコメントします。

また、データベースを生成するスクリプトには、多くの/ コメント /をお勧めします。

一般に、それが何であるかを書き留める多くの作業ですが、数年後にあなたや他の貧しい魂があなたの創造物を更新するために戻ってくるときなど、長期的には良いアイデアです!:)


3
外部キー制約はER-diagramsで行われるように、テーブルのどこかに接続されているだけなので、SQL Serverダイアグラムは使用しません。主キーフィールドと外部キーフィールドを接続するコネクタが必要です。
R.シュルーズ


12

データモデリングツールを使用するのは、データベースに「適合する」以外のデータベースに関する重要な情報を文書化できるためです。プライバシー/セキュリティ/機密性の懸念、スチュワードシップ、ガバナンスなどのメタデータ

これは、データベースの文書化に必要なものを超える場合がありますが、それらはビジネスにとって重要であり、データの管理に役立ちます。

正式なツールは、複数のデータベース/インスタンス/サーバーに保存されているデータの管理にも役立ちます。これは、パッケージ化されたアプリケーションの世界よりも真実ではありませんでした。


10

SQL Serverのドキュメント化については、最近リリースされたばかりのものを強くお勧めします。

Kendal Van Dykeが作成したWindows PowerShellを使用したSQL ServerとWindowsのドキュメント

リンクからの簡単な説明:

SQL Power Docは、SQL Serverインスタンスとその基盤となるWindows OSおよびマシン構成を検出、文書化、および診断するWindows PowerShellスクリプトとモジュールのコレクションです。SQL Power Docは、SQL Server 2000から2012までのすべてのバージョンのSQL Server、Windows 2000およびWindows XPからWindows Server 2012およびWindows 8までのすべてのバージョンのWindows ServerおよびコンシューマWindowsオペレーティングシステムで動作します。 Windows Azure SQLデータベース。


10

DB Dictionary Creator

まともなGUIとエクスポート/インポートオプションを備えたオープンソースのデータベースドキュメントツールです。拡張プロパティを使用してドキュメントを保存します。また、主キー列と外部キー列の自動説明も生成します。


1
.NET Framework 4.0を必要とし、SQL ServerおよびSQL Expressでのみ動作します
ケビンスキー

8

実際、拡張プロパティ(MS_Description)がその方法です。これらの説明をメタデータの一部としてすぐに利用できるようにすることは、ドキュメントジェネレーターだけでなく、(できればいつか)優れたSofttreeのSQL Assistant http://www.softtreetech.com/などの「インテリセンス」を提供するツールでも利用できますisql.htm(前回チェックしなかった)またはSQL Sever Management StudioのIntellisenseで構築(sql2008以降)

また、開発者とDBAがこれらのメモを追加するのは簡単だと思います。なぜなら、TangurenaとNick Chammasが正しく指摘したように-開発者はドキュメントを更新し続けて重複作業を嫌うのは非常に消極的です-これは特に教えられた人にとっては十分に公平です職業生活全体を通じて物事を最適化する。そのため、ソースコードに近い1か所でドキュメントを更新するのが本当に簡単でない限り、これは機能しません。ある時点でWebを検索し、これに対する解決策が見つからなかったので、簡単にするためにLiveDoco(無料ではなく、申し訳ありません)を書きました。興味がある場合はこちらの詳細情報:http : //www.livedoco.com/why-livedoco


7

wsSqlSrvDocご覧ください。これは、SQL Serverの拡張プロパティで動作し、MS Word文書を作成する素敵な小さなツールです。

すべての列プロパティ(外部キーリレーションを含む)の印刷は、そのまま使用できます。各フィールドの詳細については、SQL Server Management Studioでこれらの列の拡張プロパティを設定する必要があります。

無料ではありませんが、手頃な価格です。「進行中の作業ではない」DBのドキュメントを作成する必要がある場合は、無料試用版を使用するのに十分であるよりも多かれ少なかれ完成します。

ツールのウェブサイト


5

Dataedoを使用して、データディクショナリ、ドキュメントストアドプロシージャ、および関数を作成します。Visioで作成されたERDを貼り付けます。すべてのドキュメントはDataedoメタデータリポジトリ(フォーマットされたテキスト)に保存され、内部で使用するためにHTMLにエクスポートするか、印刷ドキュメント用にPDFにエクスポートします。

各オブジェクトをモジュールに割り当て、各モジュールを人に割り当てます。Dataedoにはドキュメントステータスレポートが付属しているため、ドキュメント化する必要がある新しい列またはテーブルがあるかどうかを確認できます。


1

ファイル--では、通常の接頭辞付きコメントを使用でき.sqlます。

利点には、ドキュメントにデータベーススキーマのコードが含まれており、Gitなどのバージョン管理システムに簡単にコミットできることが含まれます

例:

-- Table to store details about people.
-- See also: The customer table.
-- Note: Keep this data safe!
-- Todo: Add a email column.
CREATE TABLE Persons ( -- People in the registry
    PersonID int,
    LastName varchar(255), -- The person's last name
    FirstName varchar(255), -- The person's first name
    Address varchar(255), -- Address of residence
    City varchar(255) -- City of residence
);

たぶん、あなたもXMLを使用できます。

-- <summary>
-- Table to store details about people.
-- </summary>
-- <column name="PersonID">The id column.</column>
-- <column name="LastName">The person's last name.</column>
-- <column name="FirstName">The person's first name.</column>
-- <column name="Address">Address of residence.</column>
-- <column name="City">City of residence.</column>
CREATE TABLE Persons (
    PersonID int,
    LastName varchar(255),
    FirstName varchar(255),
    Address varchar(255),
    City varchar(255)
);

jsDoc / phpDocのような構文を使用することもできます。

-- Table to store details about people.
-- @column {int} PersonID - The id column.
-- @column {varchar} LastName - The person's last name.
-- @column {varchar} FirstName - The person's first name.
-- @column {varchar} Address - Address of residence.
-- @column {varchar} City - City of residence.
-- @see {@link https://example.com/|Example}
-- @author Jane Smith <jsmith@example.com>
-- @copyright Acme 2018
-- @license BSD-2-Clause
-- @todo Add a column for email address.
-- @since 1.0.1
-- @version 1.2.3
CREATE TABLE Persons (
    PersonID int,
    LastName varchar(255),
    FirstName varchar(255),
    Address varchar(255),
    City varchar(255)
);

または、MarkDown構文を使用できます。

-- # Persons
-- Table to store details about **people**.
-- * `PersonID` - The id column.
-- * `LastName` - The person's _last_ name.
-- * `FirstName` - The person's _first_ name.
-- * `Address` - Address of residence.
-- * `City` - City of residence.
--
-- [I'm an inline-style link](https://www.example.com/)
--
-- | PersonID | LastName | FirstName | Address | City |
-- | ---------| -------- | --------- | ------- | ---- |
-- | 1        | Smith    | Jane      | N/A     | N/A  |
CREATE TABLE Persons (
    PersonID int,
    LastName varchar(255),
    FirstName varchar(255),
    Address varchar(255),
    City varchar(255)
);

1

ERDダイアグラム(データベースダイアグラム)は常に私のチームにとって最も有用なものでした

ただし、作成する各テーブルと列のプロパティに「説明」を記述するルールがあります。

次に、Enterprise Architectというソフトウェア名を使用して、TablesすべてIndexesForeign KeysおよびColumnswith TypeおよびDescriptionで文書化します。

ここに画像の説明を入力してください


-1

特にMySQLの場合、常にMySQL Workbenchを使用します。デザイナでデータベースデザインを作成し、実行可能なSQLスクリプトとしてエクスポートします。設計のすべての変更を適用し、生成されたスクリプトを実行すると、設計と実際のデータベースが完全に同期し、ドキュメントが簡単に古くなることはありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.