데이터베이스를 어떻게 문서화합니까?


227

나는 대부분의 고객들이 그들의 데이터베이스를 전혀 문서화하지 않았다는 것을 알았고, 나는 그것이 꽤 무섭다는 것을 안다. 더 나은 방법을 소개하기 위해 사람들이 사용하는 도구 / 프로세스를 알고 싶습니다.

  • 데이터베이스를 어떻게 문서화합니까? (SQL- 서버)
  • 어떤 도구를 사용하십니까?
  • 데이터베이스 스키마 / 메타-데이터의 문서 저장 형식?
    • 워드 문서
    • 엑셀 스프레드 시트
    • 일반 텍스트
  • 문서화 프로세스 또는 정책?

리버스 엔지니어링에 대해 이야기하지 않고 기존 데이터베이스를 문서화하는 것이 아니라 주로 시스템 / 데이터베이스를 개발하는 동안 문서화 모범 사례에 대해 이야기합니다.

답변:


78

매우 유연하기 때문에 확장 속성을 사용하고 있습니다. 대부분의 표준 문서 도구를 사용할 수 있으며 MS_Description사용자 정의 도구로 자신 만의 도구를 사용할 수 있습니다.

이 프리젠 테이션을 참조하십시오 : # 41- 레버 가져 오기 및 거북이 선택 : 메타 데이터로 리프팅

그리고이 코드 : http://code.google.com/p/caderoux/wiki/LeversAndTurtles


3
무언가를 변경하고 그에 따라 확장 속성을 변경하여 잊어 버릴 수 있습니다. 이러한 불일치를 자동으로 감지 할 수 있습니까?
AK

2
최소한 데이터베이스 스키마 (sys.tables / sys.columns)를 쿼리하고 확장 속성 (sys.extended_properties)에 조인하여 문서화되지 않은 필드를 식별 한 다음 배포 할 때 실행할 스크립트를 테스트로 전환 할 수 있습니다.
Micah

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 문서로 변환하는 완전한 코드입니다 (BTW는 테이블을 다시 작성하는 데 유효한 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

문서가 작성된 경우 문서는 단어 문서로 구성됩니다. 몇 가지 관계 다이어그램이 포함됩니다. 테이블 목록 및 각 테이블의 내용과 다른 테이블과의 관계에 대한 간략한 설명입니다. 설명서의 한 장에는 보안 설정이 포함되어 있습니다. "사용자"는 응용 프로그램에 필요한 사용 권한은 무엇입니까?

일반적으로 내가 일한 회사에서 고객이 감사를 수행하는 사람 일 때만 데이터베이스 문서가 작성되므로 재무 및 정부 고객에게 사용이 제한되는 경향이 있습니다.

면책 조항 : 너무 많은 개발자가 코드가 문서 라는 태도를 취하고 나도 죄를지었습니다.


10
코드에 밀접하게 묶여 있지 않은 문서 (예 : 자동 생성 스키마 다이어그램 + 잘 명명 된 데이터베이스 객체와는 달리 별도의 Word 문서)에서 발견 한 큰 문제는이 문서가 다음과 같이 잘못 전개된다는 것입니다. 시간이 흐른다. 그 이유는 간단합니다. 별도의 문서가 정보를 효과적으로 복제합니다. 소스와 자동 으로 동기화 할 수있는 방법이 없으면 매우 빨리 폐기됩니다. 이것을 데이터베이스에서 실시간으로 스키마 다이어그램을 생성하고 코드 내에서 적절한 주석을 가져 오는 도구와 비교하십시오.
Nick Chammas


14

재밌 네요, 다른 사람들도 이걸 어떻게하는지 궁금 했어요 ..

첫 번째 큰 데이터베이스 프로젝트를 개발하는 동안 Microsoft SQL Server Management Studio 10.0.1600.22는 원하는 문서 세부 정보를 추가 할 수있는 워드 문서 또는 기타 문서 소프트웨어로 내보낼 수있는 데이터베이스 다이어그램을 지원합니다. SQL Management Studio에서 연결 한 데이터베이스를 확장하고 개체 탐색기에서 "데이터베이스 다이어그램"을 마우스 오른쪽 단추로 클릭하고 "새 데이터베이스 다이어그램"을 선택하여 다른 테이블 간의 모든 관계를 보여주는 대화식 다이어그램을 생성하십시오. 다이어그램에 포함 할 테이블을 지정할 수도 있으므로 이미지를 한 조각 씩 문서화하려는 경우 이미지가 열악하게 표시되지 않습니다. 이미지를 다른 편집 소프트웨어로 내보내고 원하는만큼 주석을 달 수 있습니다.

또한 데이터베이스를 생성하는 스크립트에서 많은 / 주석 /을 권장 합니다.

일반적으로 그것은 모든 것이 무엇인지 적는 작업이 많이 있지만, 당신이나 다른 불쌍한 영혼이 2 년 후에 당신의 창조물을 업데이트하기 위해 돌아올 때와 같은 장기적으로 좋은 생각입니다! :)


3
외래 키 제약 조건은 ER-diagrams 에서와 같이 테이블 어딘가에 연결되어 있으므로 SQL Server 다이어그램을 사용하지 않습니다 . 커넥터를 기본 및 외래 키 필드에 연결하는 것이 좋습니다.
R. Schreurs

13

모든 객체에 대해 MS_description 확장 속성을 설정 한 다음 ApexSQL Doc을 사용 하여 전체 데이터베이스를 문서화했습니다 . 예전에는 HTML 문서를 만들었지 만 최근에는 PDF를 선호합니다


12

데이터 모델링 도구를 사용하여 데이터베이스에 "적합한"것 이외의 데이터베이스에 대한 중요한 정보를 문서화 할 수 있습니다. 개인 정보 / 보안 / 민감성 우려, 청지기 직분, 거버넌스 등과 같은 메타 데이터

데이터베이스를 문서화하는 데 필요한 것 이상이 될 수 있지만 비즈니스에 중요하고 데이터를 관리하는 데 도움이되는 것들입니다.

공식 도구는 또한 하나 이상의 데이터베이스 / 인스턴스 / 서버에 저장된 데이터를 관리하는 데 도움이됩니다. 이것은 패키지 응용 프로그램 세계보다 결코 사실이 아닙니다.


10

Documenting 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 Server 2012 및 Windows 8을 통해 Windows 2000 및 Windows XP의 모든 버전의 Windows Server 및 소비자 Windows 운영 체제에서 작동합니다. SQL Power Doc도 문서화 할 수 있습니다. Windows Azure SQL 데이터베이스


10

DB 사전 생성기

알맞은 GUI 및 내보내기 / 가져 오기 옵션이있는 오픈 소스 데이터베이스 설명서 도구입니다. 확장 특성을 사용하여 문서를 저장합니다. 기본 키 열과 외래 키 열에 대한 자동 설명도 생성합니다.


1
.NET Framework 4.0이 필요하며 SQL Server 및 SQL Express에서만 작동
kevinsky

8

실제로 확장 속성 (MS_Description)이 사용됩니다. 이러한 설명을 메타 데이터의 일부로 쉽게 사용할 수있게하는 것은 문서 생성기뿐만 아니라 "지능형"을 제공하는 도구 (예 : 우수한 Softtree의 SQL Assistant http://www.softtreetech.com/)에 의해서도 가능합니다 . isql.htm (마지막으로 확인하지 않은 시간) 또는 SQL Sever Management Studio의 Intellisense (sql2008 이후)에서 빌드

또한 Tangurena와 Nick Chammas가 올바르게 지적 했으므로 개발자와 DBA 가이 메모를 추가하는 것이 쉬워야한다고 생각합니다. 개발자는 문서를 업데이트하고 중복 작업을 싫어하는 것을 매우 꺼려합니다. 특히 배운 사람에게는 충분합니다. 전체 직업 생활 동안 물건을 최적화합니다. 따라서 소스 코드와 가까운 곳에서 문서를 업데이트하기가 쉽지 않으면 작동하지 않습니다. 어느 시점에서 나는 웹을 검색하고 이것에 대한 해결책을 찾지 못했기 때문에 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 다이어그램 (데이터베이스 다이어그램) 은 항상 우리 팀에게 가장 유용한 다이어그램 이었습니다

그러나 우리가 만든 각 테이블과 열의 속성 에 " Decription " 을 쓰는 규칙이 있습니다.

그런 다음 우리는 소프트웨어 이름이 사용하는 엔터프라이즈 설계자 문서화하는 Tables모두와 함께 Indexes, Foreign Keys그리고 Columns함께 Type하고 설명 .

여기에 이미지 설명을 입력하십시오


-1

특히 MySQL의 경우 항상 MySQL Workbench를 사용 합니다. 디자이너에서 데이터베이스 디자인을 만든 다음 실행 가능한 SQL 스크립트로 내 보냅니다. 디자인의 모든 변경 사항을 적용한 다음 생성 된 스크립트를 실행하면 디자인과 실제 데이터베이스가 서로 완벽하게 동기화되고 문서가 쉽게 구식이되지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.