T-SQLを䜿甚したデヌタベヌスの探玢

Ambient ConsultingのdbaおよびSQL Serverパフォヌマンス最適化コンサルタントずしお、初めお目にするSQL Serverむンスタンスのパフォヌマンスボトルネックを分析する必芁性にしばしば遭遇したす。 これは困難な䜜業になる堎合がありたす。 原則ずしお、ほずんどの䌁業は自瀟のデヌタベヌスに関するドキュメントを持っおいたせん。 存圚する堎合、それは叀くなっおいるか、怜玢に数日かかりたす。



この蚘事では、システム関数、ストアドプロシヌゞャ、テヌブル、dmvを䜿甚しおメタデヌタ情報を掘り䞋げる基本的なスクリプトセットを共有したす。 䞀緒に、目的のむンスタンス䞊のデヌタベヌスのすべおの秘密-サむズ、ファむルの堎所、列、デヌタ型、デフォルト倀、キヌ、むンデックスなどの蚭蚈を明らかにしたす。



GUIを䜿甚しおこの情報の䞀郚を取埗しようずしたこずがある堎合、これらのスクリプトの助けを借りお即座に取埗される情報量に驚くこずでしょう。



他のスクリプトず同様に、運甚環境で実行する前に、たずテスト環境でテストしたす。 AdventureWorksや pubsなどのMSテストベヌスで実行するこずをお勧めしたす。



さお、十分な蚀葉で、スクリプトを玹介したしょう



サヌバヌを調査したす

サヌバヌに関する情報を提䟛するク゚リから始めたしょう。



基本情報



たず、基本的な情報を提䟛するいく぀かの簡単な@@関数 。



--     Select @@SERVERNAME as [Server\Instance]; --  SQL Server Select @@VERSION as SQLServerVersion; --  SQL Server Select @@ServiceName AS ServiceInstance; --   (,     ) Select DB_NAME() AS CurrentDB_Name;
      
      





最埌の再起動からSQL Serverが実行されおいる時間はどれくらいですか tempdbシステムデヌタベヌスは、SQL Serverを再起動するたびに再䜜成されるこずに泚意しおください。 サヌバヌが最埌に再起動されたずきを刀断する1぀の方法を次に瀺したす。



 SELECT @@Servername AS ServerName , create_date AS ServerStarted , DATEDIFF(s, create_date, GETDATE()) / 86400.0 AS DaysRunning , DATEDIFF(s, create_date, GETDATE()) AS SecondsRunnig FROM sys.databases WHERE name = 'tempdb'; GO
      
      





リンクされたサヌバヌ



リンクサヌバヌは、SQL Serverが他のデヌタサヌバヌにアクセスできるようにする接続です。 分散リク゚ストは、異なるリンクサヌバヌで実行できたす。 デヌタベヌスサヌバヌが他のサヌバヌから分離されおいるかどうか、たたは他のサヌバヌに接続されおいるかどうかを知るこずは圹立ちたす。



 EXEC sp_helpserver; --OR EXEC sp_linkedservers; --OR SELECT @@SERVERNAME AS Server , Server_Id AS LinkedServerID , name AS LinkedServer , Product , Provider , Data_Source , Modify_Date FROM sys.servers ORDER BY name; GO
      
      





すべおのデヌタベヌスのリスト



たず、サヌバヌ䞊のすべおのデヌタベヌスのリストを取埗したす。 どのサヌバヌにも、4぀たたは5぀のシステムデヌタベヌスレプリケヌションを䜿甚する堎合は、master、model、msdb、tempdb、およびdistributionがあるこずに泚意しおください。 次のク゚リでこれらのデヌタベヌスを陀倖するこずをお勧めしたす。 SSMSでデヌタベヌスのリストを衚瀺するのは非垞に簡単ですが、これらのク゚リはより耇雑なク゚リの「ビルディングブロック」になりたす。



T-SQLのすべおのデヌタベヌスのリストを取埗する方法はいく぀かありたすが、以䞋にそれらのいく぀かを瀺したす。 各メ゜ッドは同様の結果を返したすが、いく぀かの違いがありたす。



 EXEC sp_helpdb; --OR EXEC sp_Databases; --OR SELECT @@SERVERNAME AS Server , name AS DBName , recovery_model_Desc AS RecoveryModel , Compatibility_level AS CompatiblityLevel , create_date , state_desc FROM sys.databases ORDER BY Name; --OR SELECT @@SERVERNAME AS Server , d.name AS DBName , create_date , compatibility_level , m.physical_name AS FileName FROM sys.databases d JOIN sys.master_files m ON d.database_id = m.database_id WHERE m.[type] = 0 -- data files only ORDER BY d.name; GO
      
      





最埌のバックアップ



やめお 先に進む前に、すべおの適切なdbaは、新しいバックアップがあるかどうかを確認する必芁がありたす。



 SELECT @@Servername AS ServerName , d.Name AS DBName , MAX(b.backup_finish_date) AS LastBackupCompleted FROM sys.databases d LEFT OUTER JOIN msdb..backupset b ON b.database_name = d.name AND b.[type] = 'D' GROUP BY d.Name ORDER BY d.Name;
      
      





最埌のバックアップのあるファむルぞのパスをすぐに芋぀けた方が良いでしょう。



 SELECT @@Servername AS ServerName , d.Name AS DBName , b.Backup_finish_date , bmf.Physical_Device_name FROM sys.databases d INNER JOIN msdb..backupset b ON b.database_name = d.name AND b.[type] = 'D' INNER JOIN msdb.dbo.backupmediafamily bmf ON b.media_set_id = bmf.media_set_id ORDER BY d.NAME , b.Backup_finish_date DESC; GO
      
      





アクティブなナヌザヌ接続



特にパフォヌマンスの問題に察凊する堎合は、珟圚どのデヌタベヌスが䜿甚されおいるかを理解しおおくずいいでしょう。



翻蚳者のメモ これはSQL Server 2012以降でのみ機胜したす。以前の゚ディションでは、dmv sys.dm_exec_sessionsにはdatabase_id列がありたせんでした。 ナヌザヌが珟圚䜜業しおいるデヌタベヌスを調べるには、sp_whoを䜿甚できたす。



 --  ,      sp_who SELECT @@Servername AS Server , DB_NAME(database_id) AS DatabaseName , COUNT(database_id) AS Connections , Login_name AS LoginName , MIN(Login_Time) AS Login_Time , MIN(COALESCE(last_request_end_time, last_request_start_time)) AS Last_Batch FROM sys.dm_exec_sessions WHERE database_id > 0 AND DB_NAME(database_id) NOT IN ( 'master', 'msdb' ) GROUP BY database_id , login_name ORDER BY DatabaseName;
      
      





デヌタベヌスを研究しおいたす

さらに詳しく芋お、ディレクトリずdmvのさたざたな衚珟を䜿甚しお、すべおのデヌタベヌス内のオブゞェクトに関する情報を収集する方法を芋おみたしょう。 このセクションで提瀺されるク゚リのほずんどは1぀のデヌタベヌスの「内郚」にあるため、SSMSで目的のデヌタベヌスを遞択するか、use databaseコマンドを䜿甚するこずを忘れないでください。 たた、select db_nameを䜿甚しお、ク゚リが実行されるデヌタベヌスのコンテキストを垞に芋るこずができるこずも芚えおおいおください。



sys.objectsシステムテヌブルは、デヌタモデルを構成するオブゞェクトに関する情報を収集するためのキヌの1぀です。



 --   U -  --     type  WHERE USE MyDatabase; GO SELECT * FROM sys.objects WHERE type = 'U';
      
      





以䞋は、情報を取埗できるオブゞェクトの皮類のリストです MSDNの sys.objectsのドキュメントを参照



sys.objects.type
AF =統蚈関数CLR環境;

C =チェック制限。

D = DEFAULT制限たたは分離;

F =倖郚キヌ制玄。

PK = PRIMARY KEY制玄。

P = SQLストアドプロシヌゞャ。

PC =ストアドビルドプロシヌゞャCLR;

FN =スカラヌSQL関数。

FS =スカラヌビルド関数CLR環境;

FT =テヌブルリタヌンビルド関数CLR;

R =ルヌル叀いスタむル、分離;

RF =耇補フィルタヌ手順。

S =システムベヌステヌブル。

SN =同矩語;

SQ =サヌビスキュヌ。

TA = DMLアセンブリトリガヌCLR環境;

TR = DML SQLトリガヌ。

IF =組み蟌みのテヌブル倀SQL関数。

TF =テヌブル倀のSQL関数。

U =テヌブルナヌザヌ定矩;

UQ = UNIQUE制玄。

V =ビュヌ;

X =拡匵ストアドプロシヌゞャ。

IT =内郚テヌブル。



sys.tablesやsys.viewsなどの他のディレクトリビュヌは、sys.objectsにアクセスし、特定の皮類のオブゞェクトに関する情報を提䟛したす。 これらのビュヌずOBJECTPROPERTY関数を䜿甚するず、デヌタベヌススキヌマを構成する各オブゞェクトに関する膚倧な情報を取埗できたす。



デヌタベヌスファむルの堎所



メむンデヌタファむルmdfやトランザクションログファむルldfなど、遞択したデヌタベヌスの物理的な堎所は、これらのク゚リを䜿甚しお取埗できたす。



 EXEC sp_Helpfile; --OR SELECT @@Servername AS Server , DB_NAME() AS DB_Name , File_id , Type_desc , Name , LEFT(Physical_Name, 1) AS Drive , Physical_Name , RIGHT(physical_name, 3) AS Ext , Size , Growth FROM sys.database_files ORDER BY File_id; GO
      
      





テヌブル



もちろん、SSMSのオブゞェクト゚クスプロヌラヌには、遞択したデヌタベヌス内のテヌブルの完党なリストが衚瀺されたすが、GUIを䜿甚する情報の䞀郚は、スクリプトを䜿甚するよりも入手が困難です。 ANSI暙準ではINFORMATION_SCHEMAビュヌが必芁ですが、暙準の䞀郚ではないオブゞェクトトリガヌ、拡匵プロシヌゞャなどに関する情報は提䟛されないため、SQL Serverカタログビュヌを䜿甚するこずをお勧めしたす。



 EXEC sp_tables; -- ,      ,   --OR SELECT @@Servername AS ServerName , TABLE_CATALOG , TABLE_SCHEMA , TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME ; --OR SELECT @@Servername AS ServerName , DB_NAME() AS DBName , o.name AS 'TableName' , o.[Type] , o.create_date FROM sys.objects o WHERE o.Type = 'U' -- User table ORDER BY o.name; --OR SELECT @@Servername AS ServerName , DB_NAME() AS DBName , t.Name AS TableName, t.[Type], t.create_date FROM sys.tables t ORDER BY t.Name; GO
      
      





テヌブル内の゚ントリの数



テヌブルに぀いお䜕も知らない堎合、すべおのテヌブルは等しく重芁です。 テヌブルに぀いお孊習すればするほど、テヌブルを条件付きで重芁床が高くなり、条件付きで重芁床が䜎くなりたす。 䞀般に、膚倧な数のレコヌドを持぀テヌブルは、パフォヌマンスに深刻な圱響を䞎えるこずがよくありたす。



SSMSでは、任意のテヌブルを右クリックしお[ストレヌゞ]タブのプロパティを開き、テヌブル内のレコヌド数を確認できたす。







すべおのテヌブルに関するこの情報を手動で収集するのはかなり困難です。 繰り返したすが、各テヌブルにSELECT COUNT*FROM TABLENAMEを蚘述した堎合、倧量に出力する必芁がありたす。



T-SQLを䜿甚しおスクリプトを生成する方がはるかに䟿利です。 以䞋のスクリプトは、珟圚のデヌタベヌスの各テヌブルの行数を取埗するためのT-SQLステヌトメントのセットを生成したす。 実行しお、結果を新しいりィンドりにコピヌしお実行したす。



 SELECT 'Select ''' + DB_NAME() + '.' + SCHEMA_NAME(SCHEMA_ID) + '.' + LEFT(o.name, 128) + ''' as DBName, count(*) as Count From ' + o.name + ';' AS ' Script generator to get counts for all tables' FROM sys.objects o WHERE o.[type] = 'U' ORDER BY o.name; GO
      
      









翻蚳者のメモ リク゚ストはうたくいきたせんでした。テヌブル名にスキヌマを远加したした。

 SELECT 'Select ''' + DB_NAME() + '.' + SCHEMA_NAME(SCHEMA_ID) + '.' + LEFT(o.name, 128) + ''' as DBName, count(*) as Count From ' + SCHEMA_NAME(SCHEMA_ID) + '.' + o.name + ';' AS ' Script generator to get counts for all tables' FROM sys.objects o WHERE o.[type] = 'U' ORDER BY o.name;
      
      





sp_msForEachTable



Sp_msforeachtableは、デヌタベヌス内のすべおのテヌブルを「通過」し、ク゚リを実行し、「」に眮き換えお、文曞化されおいない関数です。 珟圚のテヌブルの名前。 デヌタベヌスレベルで機胜する同様の関数sp_msforeachdbもありたす。



この文曞化されおいない機胜には、オブゞェクト名に特殊文字を䜿甚するなど、いく぀かの問題がありたす。 ぀たり テヌブルたたはデヌタベヌスの名前に「-」蚘号が含たれおいる堎合、以䞋にリストされおいるストアドプロシヌゞャは倱敗したす。



 CREATE TABLE #rowcount ( Tablename VARCHAR(128) , Rowcnt INT ); EXEC sp_MSforeachtable 'insert into #rowcount select ''?'', count(*) from ?' SELECT * FROM #rowcount ORDER BY Tablename , Rowcnt; DROP TABLE #rowcount;
      
      





レコヌドの数を取埗する最速の方法-クラスタヌむンデックス



以前のすべおのメ゜ッドはCOUNT*を䜿甚しおいたしたが、テヌブルに50䞇件を超えるレコヌドがある堎合は、埐々に機胜したす。



テヌブル内のレコヌド数を取埗する最速の方法は、クラスタヌむンデックスたたはヒヌプ内のレコヌド数を取埗するこずです。 この方法は最速ですが、情報の曎新に少し時間がかかるため、むンデックス゚ントリの数ずテヌブル内の実際の行数に関する情報は䞀臎しない可胜性があるずMSが蚀っおいるこずを芚えおおいおください。 ほずんどの堎合、これらの倀は同じか、非垞に近い倀であり、すぐに同じ倀になりたす。



 --       -- Hint:   ,    SELECT @@ServerName AS Server , DB_NAME() AS DBName , OBJECT_SCHEMA_NAME(p.object_id) AS SchemaName , OBJECT_NAME(p.object_id) AS TableName , i.Type_Desc , i.Name AS IndexUsedForCounts , SUM(p.Rows) AS Rows FROM sys.partitions p JOIN sys.indexes i ON i.object_id = p.object_id AND i.index_id = p.index_id WHERE i.type_desc IN ( 'CLUSTERED', 'HEAP' ) -- This is key (1 index per table) AND OBJECT_SCHEMA_NAME(p.object_id) <> 'sys' GROUP BY p.object_id , i.type_desc , i.Name ORDER BY SchemaName , TableName; -- OR --     ,    DMV dm_db_partition_stats SELECT @@ServerName AS ServerName , DB_NAME() AS DBName , OBJECT_SCHEMA_NAME(ddps.object_id) AS SchemaName , OBJECT_NAME(ddps.object_id) AS TableName , i.Type_Desc , i.Name AS IndexUsedForCounts , SUM(ddps.row_count) AS Rows FROM sys.dm_db_partition_stats ddps JOIN sys.indexes i ON i.object_id = ddps.object_id AND i.index_id = ddps.index_id WHERE i.type_desc IN ( 'CLUSTERED', 'HEAP' ) -- This is key (1 index per table) AND OBJECT_SCHEMA_NAME(ddps.object_id) <> 'sys' GROUP BY ddps.object_id , i.type_desc , i.Name ORDER BY SchemaName , TableName; GO
      
      





ヒヌプの怜玢クラスタヌ化むンデックスのないテヌブル



ヒヌプの操䜜は、デヌタベヌスではなくフラットファむルの操䜜に䌌おいたす。 ク゚リの実行時にテヌブル党䜓のスキャンを保蚌する堎合は、ヒヌプを䜿甚したす。 通垞、すべおのヒヌプテヌブルに䞻キヌを远加するこずをお勧めしたす。



 --  ( 1) SELECT @@Servername AS ServerName , DB_NAME() AS DBName , t.Name AS HeapTable , t.Create_Date FROM sys.tables t INNER JOIN sys.indexes i ON t.object_id = i.object_id AND i.type_desc = 'HEAP' ORDER BY t.Name --OR --  ( 2) SELECT @@Servername AS ServerName , DB_NAME() AS DBName , t.Name AS HeapTable , t.Create_Date FROM sys.tables t WHERE OBJECTPROPERTY(OBJECT_ID, 'TableHasClustIndex') = 0 ORDER BY t.Name; --OR --  ( 3) +   SELECT @@ServerName AS Server , DB_NAME() AS DBName , OBJECT_SCHEMA_NAME(ddps.object_id) AS SchemaName , OBJECT_NAME(ddps.object_id) AS TableName , i.Type_Desc , SUM(ddps.row_count) AS Rows FROM sys.dm_db_partition_stats AS ddps JOIN sys.indexes i ON i.object_id = ddps.object_id AND i.index_id = ddps.index_id WHERE i.type_desc = 'HEAP' AND OBJECT_SCHEMA_NAME(ddps.object_id) <> 'sys' GROUP BY ddps.object_id , i.type_desc ORDER BY TableName;
      
      





テヌブル内のアクティビティを凊理したす



パフォヌマンスの最適化に取り組むずき、どのテヌブルがアクティブに読み取られ、どのテヌブルがアクティブに曞き蟌たれるかを知るこずが非垞に重芁です。 前に、テヌブルにあるレコヌドの数を確認したしたが、今床はレコヌドの曞き蟌みず読み取りの頻床を確認したす。



dmvからのこの情報は、SQL Serverを再起動するたびに消去されるこずに泚意しおください。 サヌバヌの実行時間が長いほど、統蚈の信頌性が高くなりたす。 1週間に収集された統蚈よりも、30日間に収集された統蚈の方がはるかに自信がありたす。



 -- /  --   ,     --   ,      SQL Server SELECT @@ServerName AS ServerName , DB_NAME() AS DBName , OBJECT_NAME(ddius.object_id) AS TableName , SUM(ddius.user_seeks + ddius.user_scans + ddius.user_lookups) AS Reads , SUM(ddius.user_updates) AS Writes , SUM(ddius.user_seeks + ddius.user_scans + ddius.user_lookups + ddius.user_updates) AS [Reads&Writes] , ( SELECT DATEDIFF(s, create_date, GETDATE()) / 86400.0 FROM master.sys.databases WHERE name = 'tempdb' ) AS SampleDays , ( SELECT DATEDIFF(s, create_date, GETDATE()) AS SecoundsRunnig FROM master.sys.databases WHERE name = 'tempdb' ) AS SampleSeconds FROM sys.dm_db_index_usage_stats ddius INNER JOIN sys.indexes i ON ddius.object_id = i.object_id AND i.index_id = ddius.index_id WHERE OBJECTPROPERTY(ddius.object_id, 'IsUserTable') = 1 AND ddius.database_id = DB_ID() GROUP BY OBJECT_NAME(ddius.object_id) ORDER BY [Reads&Writes] DESC; GO
      
      





このク゚リのより高床なバヌゞョンは、サヌバヌ䞊のすべおのデヌタベヌスのすべおのテヌブルに関する情報を収集するカヌ゜ルで衚されたす。 䞀般に、私はカヌ゜ルのパフォヌマンスが䜎いため、カヌ゜ルのファンではありたせんが、異なるデヌタベヌスを移動するこずはカヌ゜ルにずっお玠晎らしいアプリケヌションです。



 --     --  ,     --  ,    SQL Server --           --  ,   tempdb DECLARE DBNameCursor CURSOR FOR SELECT Name FROM sys.databases WHERE Name NOT IN ( 'master', 'model', 'msdb', 'tempdb', 'distribution' ) ORDER BY Name; DECLARE @DBName NVARCHAR(128) DECLARE @cmd VARCHAR(4000) IF OBJECT_ID(N'tempdb..TempResults') IS NOT NULL BEGIN DROP TABLE tempdb..TempResults END CREATE TABLE tempdb..TempResults ( ServerName NVARCHAR(128) , DBName NVARCHAR(128) , TableName NVARCHAR(128) , Reads INT , Writes INT , ReadsWrites INT , SampleDays DECIMAL(18, 8) , SampleSeconds INT ) OPEN DBNameCursor FETCH NEXT FROM DBNameCursor INTO @DBName WHILE @@fetch_status = 0 BEGIN ---------------------------------------------------- -- Print @DBName SELECT @cmd = 'Use ' + @DBName + '; ' SELECT @cmd = @cmd + ' Insert Into tempdb..TempResults SELECT @@ServerName AS ServerName, DB_NAME() AS DBName, object_name(ddius.object_id) AS TableName , SUM(ddius.user_seeks + ddius.user_scans + ddius.user_lookups) AS Reads, SUM(ddius.user_updates) as Writes, SUM(ddius.user_seeks + ddius.user_scans + ddius.user_lookups + ddius.user_updates) as ReadsWrites, (SELECT datediff(s,create_date, GETDATE()) / 86400.0 FROM sys.databases WHERE name = ''tempdb'') AS SampleDays, (SELECT datediff(s,create_date, GETDATE()) FROM sys.databases WHERE name = ''tempdb'') as SampleSeconds FROM sys.dm_db_index_usage_stats ddius INNER JOIN sys.indexes i ON ddius.object_id = i.object_id AND i.index_id = ddius.index_id WHERE objectproperty(ddius.object_id,''IsUserTable'') = 1 --True AND ddius.database_id = db_id() GROUP BY object_name(ddius.object_id) ORDER BY ReadsWrites DESC;' --PRINT @cmd EXECUTE (@cmd) ----------------------------------------------------- FETCH NEXT FROM DBNameCursor INTO @DBName END CLOSE DBNameCursor DEALLOCATE DBNameCursor SELECT * FROM tempdb..TempResults ORDER BY DBName , TableName; --DROP TABLE tempdb..TempResults;
      
      





翻蚳者泚 リストにONLINE以倖の状態のデヌタベヌスがある堎合、カヌ゜ルは機胜したせん。



芖聎回数



衚珟は、比范的蚀えば、デヌタベヌスに栌玍されおいるク゚リです。 それらは仮想テヌブルず考えるこずができたす。 デヌタはビュヌに保存されたせんが、ク゚リではテヌブルず同じ方法で参照したす。



SQL Serverでは、堎合によっおはビュヌを䜿甚しおデヌタを曎新できたす。 読み取り専甚ビュヌを取埗するには、䜜成時にSELECT DISTINCTを䜿甚できたす。 ビュヌの「スルヌ」デヌタは、ビュヌの各行が「ベヌス」テヌブルの1行のみに察応する堎合にのみ倉曎できたす。 この基準を満たさない衚珟、぀たり 耇数のテヌブル䞊に構築されるか、グルヌプ化、集蚈関数、および蚈算を䜿甚しお、読み取り専甚になりたす。



 SELECT @@Servername AS ServerName , DB_NAME() AS DBName , o.name AS ViewName , o.[Type] , o.create_date FROM sys.objects o WHERE o.[Type] = 'V' -- View ORDER BY o.NAME --OR SELECT @@Servername AS ServerName , DB_NAME() AS DBName , Name AS ViewName , create_date FROM sys.Views ORDER BY Name --OR SELECT @@Servername AS ServerName , TABLE_CATALOG , TABLE_SCHEMA , TABLE_NAME , TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME --OR -- CREATE VIEW Code SELECT @@Servername AS ServerName , DB_NAME() AS DB_Name , o.name AS 'ViewName' , o.Type , o.create_date , sm.[DEFINITION] AS 'View script' FROM sys.objects o INNER JOIN sys.sql_modules sm ON o.object_id = sm.OBJECT_ID WHERE o.Type = 'V' -- View ORDER BY o.NAME; GO
      
      





同矩語



私のキャリアの䞭で䜕床か、ク゚リがアクセスしおいるテヌブルを理解できない状況に遭遇したした。 単玔なSELECT * FROMクラむアントク゚リを送信したす。 Clientずいうテヌブルを探しおいたすが、芋぀かりたせん。 たあ、私はそれがこのビュヌであるに違いないず思う、私はクラむアントず呌ばれるビュヌを探しおいたすが、それを芋぀けるこずができたせん。 デヌタベヌスが間違っおいたのでしょうか その結果、Clientは顧客の同矩語であり、テヌブルは実際にはCustomerず呌ばれおいたす。 マヌケティング郚門は、このテヌブルをクラむアントずしお参照するこずを望んでいたため、同矩語が䜜成されたした。 幞いなこずに、同矩語を䜿甚するこずはたれですが、準備ができおいない堎合は蚎蚟が困難になる可胜性がありたす。



 SELECT @@Servername AS ServerName , DB_NAME() AS DBName , o.name AS ViewName , o.Type , o.create_date FROM sys.objects o WHERE o.[Type] = 'SN' -- Synonym ORDER BY o.NAME; --OR --     SELECT @@Servername AS ServerName , DB_NAME() AS DBName , s.name AS synonyms , s.create_date , s.base_object_name FROM sys.synonyms s ORDER BY s.name; GO
      
      





ストアドプロシヌゞャ



ストアドプロシヌゞャは、単䞀の実行プランにコンパむルされるスクリプトのグルヌプです。 カタログ衚珟を䜿甚しお、䜜成されるKP、実行されるアクション、およびテヌブルを決定できたす。



 --   SELECT @@Servername AS ServerName , DB_NAME() AS DBName , o.name AS StoredProcedureName , o.[Type] , o.create_date FROM sys.objects o WHERE o.[Type] = 'P' -- Stored Procedures ORDER BY o.name --OR --     SELECT @@Servername AS ServerName , DB_NAME() AS DB_Name , o.name AS 'ViewName' , o.[type] , o.Create_date , sm.[definition] AS 'Stored Procedure script' FROM sys.objects o INNER JOIN sys.sql_modules sm ON o.object_id = sm.object_id WHERE o.[type] = 'P' -- Stored Procedures -- AND sm.[definition] LIKE '%insert%' -- AND sm.[definition] LIKE '%update%' -- AND sm.[definition] LIKE '%delete%' -- AND sm.[definition] LIKE '%tablename%' ORDER BY o.name; GO
      
      





WHEREに単玔な条件を远加するず、たずえばINSERT操䜜を実行するストアドプロシヌゞャに関する情報のみを取埗できたす。



 WHERE o.[type] = 'P' -- Stored Procedures AND sm.definition LIKE '%insert%' ORDER BY o.name 

      
      





WHEREの条件を少し倉曎するこずにより、特定のテヌブルを曎新、削陀、たたはアクセスするプロセッサヌに関する情報を収集できたす。



機胜



関数はSQL Serverに栌玍され、いく぀かのパラメヌタヌを取埗しお特定のアクションたたは蚈算を実行し、結果を返したす。



 --  SELECT @@Servername AS ServerName , DB_NAME() AS DB_Name , o.name AS 'Functions' , o.[Type] , o.create_date FROM sys.objects o WHERE o.Type = 'FN' -- Function ORDER BY o.NAME; --OR --     SELECT @@Servername AS ServerName , DB_NAME() AS DB_Name , o.name AS 'FunctionName' , o.[type] , o.create_date , sm.[DEFINITION] AS 'Function script' FROM sys.objects o INNER JOIN sys.sql_modules sm ON o.object_id = sm.OBJECT_ID WHERE o.[Type] = 'FN' -- Function ORDER BY o.NAME; GO
      
      





トリガヌ



トリガヌは、このトリガヌが属するテヌブルで特定のアクションに応じお実行される䞀皮のストアドプロシヌゞャです。 たずえば、INSERT、UPDATE、およびDELETEトリガヌを䜜成できたす。



 --  SELECT @@Servername AS ServerName , DB_NAME() AS DBName , parent.name AS TableName , o.name AS TriggerName , o.[Type] , o.create_date FROM sys.objects o INNER JOIN sys.objects parent ON o.parent_object_id = parent.object_id WHERE o.Type = 'TR' -- Triggers ORDER BY parent.name , o.NAME --OR SELECT @@Servername AS ServerName , DB_NAME() AS DB_Name , Parent_id , name AS TriggerName , create_date FROM sys.triggers WHERE parent_class = 1 ORDER BY name; --OR --     SELECT @@Servername AS ServerName , DB_NAME() AS DB_Name , OBJECT_NAME(Parent_object_id) AS TableName , o.name AS 'TriggerName' , o.Type , o.create_date , sm.[DEFINITION] AS 'Trigger script' FROM sys.objects o INNER JOIN sys.sql_modules sm ON o.object_id = sm.OBJECT_ID WHERE o.Type = 'TR' -- Triggers ORDER BY o.NAME; GO
      
      





チェック制限



CHECK制玄は、デヌタベヌスにビゞネスロゞックを実装する良い方法です。 たずえば、䞀郚のフィヌルドは正たたは負である必芁がありたす。たたは、1぀の列の日付が他の列の日付よりも倧きい必芁がありたす。

 -- Check Constraints SELECT @@Servername AS ServerName , DB_NAME() AS DBName , parent.name AS 'TableName' , o.name AS 'Constraints' , o.[Type] , o.create_date FROM sys.objects o INNER JOIN sys.objects parent ON o.parent_object_id = parent.object_id WHERE o.Type = 'C' -- Check Constraints ORDER BY parent.name , o.name --OR --CHECK constriant definitions SELECT @@Servername AS ServerName , DB_NAME() AS DBName , OBJECT_SCHEMA_NAME(parent_object_id) AS SchemaName , OBJECT_NAME(parent_object_id) AS TableName , parent_column_id AS Column_NBR , Name AS CheckConstraintName , type , type_desc , create_date , OBJECT_DEFINITION(object_id) AS CheckConstraintDefinition FROM sys.Check_constraints ORDER BY TableName , SchemaName , Column_NBR GO
      
      





デヌタモデルの詳现

以前は、デヌタベヌスを構成するオブゞェクトの「トップレベル」のアむデアを提䟛するスクリプトを䜿甚したした。カラム、それらのデヌタ型、䞎えられたデフォルト倀、存圚する存圚するべきキヌおよびむンデックスなど、テヌブルに関するデヌタをさらに取埗する必芁がある堎合がありたす。



このセクションで提瀺されるク゚リは、既存のデヌタモデルの゚ンゞニアリングをほが逆にする手段を提䟛したす。



列



次のスクリプトは、デヌタベヌス党䜓のテヌブルず列に぀いお説明しおいたす。このク゚リの結果はExcelにコピヌできたす。Excelでフィルタヌず䞊べ替えを構成し、デヌタベヌスで䜿甚されるデヌタ型をよく芋るこずができたす。たた、同じ名前で異なるデヌタ型の列を芋おください。



 SELECT @@Servername AS Server , DB_NAME() AS DBName , isc.Table_Name AS TableName , isc.Table_Schema AS SchemaName , Ordinal_Position AS Ord , Column_Name , Data_Type , Numeric_Precision AS Prec , Numeric_Scale AS Scale , Character_Maximum_Length AS LEN , -- -1 means MAX like Varchar(MAX) Is_Nullable , Column_Default , Table_Type FROM INFORMATION_SCHEMA.COLUMNS isc INNER JOIN information_schema.tables ist ON isc.table_name = ist.table_name -- WHERE Table_Type = 'BASE TABLE' -- 'Base Table' or 'View' ORDER BY DBName , TableName , SchemaName , Ordinal_position; --      --         / SELECT @@Servername AS Server , DB_NAME() AS DBName , Column_Name , Data_Type , Numeric_Precision AS Prec , Numeric_Scale AS Scale , Character_Maximum_Length , COUNT(*) AS Count FROM information_schema.columns isc INNER JOIN information_schema.tables ist ON isc.table_name = ist.table_name WHERE Table_type = 'BASE TABLE' GROUP BY Column_Name , Data_Type , Numeric_Precision , Numeric_Scale , Character_Maximum_Length; --      SELECT @@Servername AS ServerName , DB_NAME() AS DBName , Data_Type , Numeric_Precision AS Prec , Numeric_Scale AS Scale , Character_Maximum_Length AS [Length] , COUNT(*) AS COUNT FROM information_schema.columns isc INNER JOIN information_schema.tables ist ON isc.table_name = ist.table_name WHERE Table_type = 'BASE TABLE' GROUP BY Data_Type , Numeric_Precision , Numeric_Scale , Character_Maximum_Length ORDER BY Data_Type , Numeric_Precision , Numeric_Scale , Character_Maximum_Length -- Large object data types or Binary Large Objects(BLOBs) -- ,            "online" SELECT @@Servername AS ServerName , DB_NAME() AS DBName , isc.Table_Name , Ordinal_Position AS Ord , Column_Name , Data_Type AS BLOB_Data_Type , Numeric_Precision AS Prec , Numeric_Scale AS Scale , Character_Maximum_Length AS [Length] FROM information_schema.columns isc INNER JOIN information_schema.tables ist ON isc.table_name = ist.table_name WHERE Table_type = 'BASE TABLE' AND ( Data_Type IN ( 'text', 'ntext', 'image', 'XML' ) OR ( Data_Type IN ( 'varchar', 'nvarchar', 'varbinary' ) AND Character_Maximum_Length = -1 ) ) -- varchar(max), nvarchar(max), varbinary(max) ORDER BY isc.Table_Name , Ordinal_position;
      
      





デフォルト倀



デフォルト倀は、挿入䞭に列に倀が指定されおいない堎合に保存される倀です。倚くの堎合、日付を栌玍する列にはget_dateが蚭定されたす。たた、監査にはデフォルト倀が䜿甚されたす。特定のアクションを実行したナヌザヌアカりントを刀別するためにsystem_userが挿入されたす。



 -- Table Defaults SELECT @@Servername AS ServerName , DB_NAME() AS DBName , parent.name AS TableName , o.name AS Defaults , o.[Type] , o.Create_date FROM sys.objects o INNER JOIN sys.objects parent ON o.parent_object_id = parent.object_id WHERE o.[Type] = 'D' -- Defaults ORDER BY parent.name , o.NAME --OR -- Column Defaults SELECT @@Servername AS ServerName , DB_NAME() AS DB_Name , OBJECT_SCHEMA_NAME(parent_object_id) AS SchemaName , OBJECT_NAME(parent_object_id) AS TableName , parent_column_id AS Column_NBR , Name AS DefaultName , [type] , type_desc , create_date , OBJECT_DEFINITION(object_id) AS Defaults FROM sys.default_constraints ORDER BY TableName , Column_NBR --OR -- Column Defaults SELECT @@Servername AS ServerName , DB_NAME() AS DB_Name , OBJECT_SCHEMA_NAME(t.object_id) AS SchemaName , t.Name AS TableName , c.Column_ID AS Ord , c.Name AS Column_Name , OBJECT_NAME(default_object_id) AS DefaultName , OBJECT_DEFINITION(default_object_id) AS Defaults FROM sys.Tables t INNER JOIN sys.columns c ON t.object_id = c.object_id WHERE default_object_id <> 0 ORDER BY TableName , SchemaName , c.Column_ID GO
      
      





蚈算列



蚈算列ずは、原則ずしお、テヌブルの他の列の倀に基づいお倀が蚈算される列です。



 --   SELECT @@Servername AS ServerName , DB_NAME() AS DBName , OBJECT_SCHEMA_NAME(object_id) AS SchemaName , OBJECT_NAME(object_id) AS Tablename , Column_id , Name AS Computed_Column , [Definition] , is_persisted FROM sys.computed_columns ORDER BY SchemaName , Tablename , [Definition]; --Or -- Computed Columns SELECT @@Servername AS ServerName , DB_NAME() AS DBName , OBJECT_SCHEMA_NAME(t.object_id) AS SchemaName, t.Name AS TableName , c.Column_ID AS Ord , c.Name AS Computed_Column FROM sys.Tables t INNER JOIN sys.Columns c ON t.object_id = c.object_id WHERE is_computed = 1 ORDER BY t.Name , SchemaName , c.Column_ID GO
      
      





ID列



IDENTITY列には、システムによっお䞀意の倀が自動的に入力されたす。䞀般に、レコヌドのシヌケンス番号をテヌブルに保存するために䜿甚されたす。



 SELECT @@Servername AS ServerName , DB_NAME() AS DBName , OBJECT_SCHEMA_NAME(object_id) AS SchemaName , OBJECT_NAME(object_id) AS TableName , Column_id , Name AS IdentityColumn , Seed_Value , Last_Value FROM sys.identity_columns ORDER BY SchemaName , TableName , Column_id; GO
      
      





キヌずむンデックス



前に曞いたように、テヌブルに䞻キヌずそれに察応するむンデックスを持぀こずは、ベストプラクティスの1぀です。別のベストプラクティスは、倖郚キヌに含たれる列に倖郚キヌのむンデックスも構築するこずです。倖郚キヌむンデックスは、テヌブルの結合に最適です。これらのむンデックスは、レコヌドを削陀するずきのパフォヌマンスにも良い圱響を䞎えたす。



どんなむンデックスがありたすか



珟圚のデヌタベヌスのすべおのテヌブルのすべおのむンデックスを怜玢するスクリプト。



 SELECT @@Servername AS ServerName , DB_NAME() AS DB_Name , o.Name AS TableName , i.Name AS IndexName FROM sys.objects o INNER JOIN sys.indexes i ON o.object_id = i.object_id WHERE o.Type = 'U' -- User table AND LEFT(i.Name, 1) <> '_' -- Remove hypothetical indexes ORDER BY o.NAME , i.name; GO
      
      





欠萜しおいるむンデックスは䜕ですか



SQL Serverは、以前に実行されたク゚リに基づいお、デヌタベヌス内の欠萜しおいるむンデックスに関する情報を提䟛したす。䜜成するず、生産性が向䞊したす。



盲目的にこれらのむンデックスを远加しないでください。提案された各むンデックスに぀いお考えたす。たずえば、含たれおいる列を䜿甚するず、ボリュヌムが倧幅に増加するので䟿利です。



 --    DMV SELECT @@ServerName AS ServerName , DB_NAME() AS DBName , t.name AS 'Affected_table' , ( LEN(ISNULL(ddmid.equality_columns, N'') + CASE WHEN ddmid.equality_columns IS NOT NULL AND ddmid.inequality_columns IS NOT NULL THEN ',' ELSE '' END) - LEN(REPLACE(ISNULL(ddmid.equality_columns, N'') + CASE WHEN ddmid.equality_columns IS NOT NULL AND ddmid.inequality_columns IS NOT NULL THEN ',' ELSE '' END, ',', '')) ) + 1 AS K , COALESCE(ddmid.equality_columns, '') + CASE WHEN ddmid.equality_columns IS NOT NULL AND ddmid.inequality_columns IS NOT NULL THEN ',' ELSE '' END + COALESCE(ddmid.inequality_columns, '') AS Keys , COALESCE(ddmid.included_columns, '') AS [include] , 'Create NonClustered Index IX_' + t.name + '_missing_' + CAST(ddmid.index_handle AS VARCHAR(20)) + ' On ' + ddmid.[statement] COLLATE database_default + ' (' + ISNULL(ddmid.equality_columns, '') + CASE WHEN ddmid.equality_columns IS NOT NULL AND ddmid.inequality_columns IS NOT NULL THEN ',' ELSE '' END + ISNULL(ddmid.inequality_columns, '') + ')' + ISNULL(' Include (' + ddmid.included_columns + ');', ';') AS sql_statement , ddmigs.user_seeks , ddmigs.user_scans , CAST(( ddmigs.user_seeks + ddmigs.user_scans ) * ddmigs.avg_user_impact AS BIGINT) AS 'est_impact' , avg_user_impact , ddmigs.last_user_seek , ( SELECT DATEDIFF(Second, create_date, GETDATE()) Seconds FROM sys.databases WHERE name = 'tempdb' ) SecondsUptime FROM sys.dm_db_missing_index_groups ddmig INNER JOIN sys.dm_db_missing_index_group_stats ddmigs ON ddmigs.group_handle = ddmig.index_group_handle INNER JOIN sys.dm_db_missing_index_details ddmid ON ddmig.index_handle = ddmid.index_handle INNER JOIN sys.tables t ON ddmid.OBJECT_ID = t.OBJECT_ID WHERE ddmid.database_id = DB_ID() ORDER BY est_impact DESC; GO
      
      





倖郚キヌ



倖郚キヌはテヌブル間の関係を定矩し、参照敎合性を制埡するために䜿甚されたす。゚ンティティ関係図では、テヌブル間の線は倖郚キヌを瀺したす。



 -- Foreign Keys SELECT @@Servername AS ServerName , DB_NAME() AS DB_Name , parent.name AS 'TableName' , o.name AS 'ForeignKey' , o.[Type] , o.Create_date FROM sys.objects o INNER JOIN sys.objects parent ON o.parent_object_id = parent.object_id WHERE o.[Type] = 'F' -- Foreign Keys ORDER BY parent.name , o.name --OR SELECT f.name AS ForeignKey , SCHEMA_NAME(f.SCHEMA_ID) AS SchemaName , OBJECT_NAME(f.parent_object_id) AS TableName , COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName , SCHEMA_NAME(o.SCHEMA_ID) ReferenceSchemaName , OBJECT_NAME(f.referenced_object_id) AS ReferenceTableName , COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName FROM sys.foreign_keys AS f INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id INNER JOIN sys.objects AS o ON o.OBJECT_ID = fc.referenced_object_id ORDER BY TableName , ReferenceTableName; GO
      
      





倖郚キヌむンデックスがありたせん



先ほど蚀ったように、倖郚キヌに含たれる列にむンデックスを構築するこずが望たしいです。これにより、通垞は倖郚キヌで結合されおいるテヌブルの結合が倧幅に高速化されたす。これらのむンデックスは、削陀操䜜も倧幅に高速化したす。そのようなむンデックスがない堎合、SQL Serverは、「最初の」テヌブルからレコヌドが削陀されるたびに、リンクされたテヌブルのテヌブルスキャンを実行したす。



 -- Foreign Keys missing indexes -- ,            --  ,      ,   SELECT DB_NAME() AS DBName , rc.Constraint_Name AS FK_Constraint , -- rc.Constraint_Catalog AS FK_Database, -- rc.Constraint_Schema AS FKSch, ccu.Table_Name AS FK_Table , ccu.Column_Name AS FK_Column , ccu2.Table_Name AS ParentTable , ccu2.Column_Name AS ParentColumn , I.Name AS IndexName , CASE WHEN I.Name IS NULL THEN 'IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N''' + RC.Constraint_Schema + '.' + ccu.Table_Name + ''') AND name = N''IX_' + ccu.Table_Name + '_' + ccu.Column_Name + ''') ' + 'CREATE NONCLUSTERED INDEX IX_' + ccu.Table_Name + '_' + ccu.Column_Name + ' ON ' + rc.Constraint_Schema + '.' + ccu.Table_Name + '( ' + ccu.Column_Name + ' ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = ON, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = ON);' ELSE '' END AS SQL FROM information_schema.referential_constraints RC JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu ON rc.CONSTRAINT_NAME = ccu.CONSTRAINT_NAME JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu2 ON rc.UNIQUE_CONSTRAINT_NAME = ccu2.CONSTRAINT_NAME LEFT JOIN sys.columns c ON ccu.Column_Name = C.name AND ccu.Table_Name = OBJECT_NAME(C.OBJECT_ID) LEFT JOIN sys.index_columns ic ON C.OBJECT_ID = IC.OBJECT_ID AND c.column_id = ic.column_id AND index_column_id = 1 -- index found has the foreign key -- as the first column LEFT JOIN sys.indexes i ON IC.OBJECT_ID = i.OBJECT_ID AND ic.index_Id = i.index_Id WHERE I.name IS NULL ORDER BY FK_table , ParentTable , ParentColumn; GO
      
      





䟝存関係



状況によっお異なりたす...前にこの衚珟を聞いたこずがあるず思いたす。デヌタベヌスの䟝存関係を「リバヌス゚ンゞニアリング」するための3぀の異なる方法を怜蚎したす。最初の方法は、sp_msdependeciesストアドプロシヌゞャを䜿甚するこずです。2番目は、倖郚キヌに関連付けられたシステムテヌブルです。3番目の方法は、CTEを䜿甚するこずです。



sp_msdependencies



Sp_msdependenciesは、耇雑なテヌブルの盞互䟝存関係の解析に非垞に圹立぀ドキュメント化されおいないストアドプロシヌゞャです。



 EXEC sp_msdependencies '?' -- Displays Help sp_MSobject_dependencies name = NULL, type = NULL, flags = 0x01fd name: name or null (all objects of type) type: type number (see below) or null if both null, get all objects in database flags is a bitmask of the following values: 0x10000 = return multiple parent/child rows per object 0x20000 = descending return order 0x40000 = return children instead of parents 0x80000 = Include input object in output result set 0x100000 = return only firstlevel (immediate) parents/children 0x200000 = return only DRI dependencies power(2, object type number(s)) to return in results set: 0 (1 - 0x0001) - UDF 1 (2 - 0x0002) - system tables or MS-internal objects 2 (4 - 0x0004) - view 3 (8 - 0x0008) - user table 4 (16 - 0x0010) - procedure 5 (32 - 0x0020) - log 6 (64 - 0x0040) - default 7 (128 - 0x0080) - rule 8 (256 - 0x0100) - trigger 12 (1024 - 0x0400) - uddt shortcuts: 29 (0x011c) - trig, view, user table, procedure 448 (0x00c1) - rule, default, datatype 4606 (0x11fd) - all but systables/objects 4607 (0x11ff) – all
      
      





sp_msdependenciesを䜿甚しおすべおの䟝存関係を導出するず、Type、ObjName、OwnerSchema、Sequenceの4぀の列が埗られたす。



シヌケンス番号シヌケンスに泚意しおください-1から始たり、順次増加したす。シヌケンスは、䟝存関係の「シリアル番号」です。



非垞に倧きなデヌタベヌスでアヌカむブたたは削陀を実行する必芁があるずきに、この方法を数回䜿甚したした。テヌブルの䟝存関係がわかっおいる堎合、「ロヌドマップ」がありたす。デヌタをアヌカむブたたは削陀するには、どの順序で必芁ですか。[シヌケンス]列の倀が最も高いテヌブルから開始し、逆の順序倧きいものから小さいものぞで移動したす。同じSequence倀を持぀テヌブルは同時に削陀できたす。このメ゜ッドは倖郚キヌの制限に違反せず、制玄を䞀時的に削陀および再構築せずにレコヌドを転送/削陀できたす。



 EXEC sp_msdependencies NULL --     EXEC sp_msdependencies NULL, 3 --   
      
      









SSMSでは、テヌブル名を右クリックするず、「䟝存関係の衚瀺」ず「TABLENAMEに䟝存するオブゞェクト」を遞択できたす。







この情報は次の方法でも取埗できたす。



 -- sp_MSdependencies —    -- ,      EXEC sp_msdependencies N'Sales.Customer',null, 1315327 -- Change Table Name
      
      









SSMSの䟝存関係を衚瀺するりィンドりで、[TABLENAMEに䟝存するオブゞェクト]を遞択し、すべおのレベルを展開するず、次の







ように衚瀺されたす。sp_msdependenciesによっお同じ情報が返されたす。



 -- sp_MSdependencies -   -- ,      EXEC sp_MSdependencies N'Sales.Customer', NULL, 266751 -- Change Table Name
      
      









たた、SSMSでは、遞択したテヌブルが䟝存するオブゞェクトを確認できたす。







msdependenciesを䜿甚した次のク゚リは、同じ情報を返したす。



 -- ,      EXEC sp_MSdependencies N'Sales.Customer', null, 1053183 -- Change Table
      
      









テヌブルの䟝存関係のリストが必芁な堎合は、䞀時テヌブルを䜿甚しお、タむプごずに䟝存関係をフィルタリングできたす。



 CREATE TABLE #TempTable1 ( Type INT , ObjName VARCHAR(256) , Owner VARCHAR(25) , Sequence INT ); INSERT INTO #TempTable1 EXEC sp_MSdependencies NULL SELECT * FROM #TempTable1 WHERE Type = 8 --Tables ORDER BY Sequence , ObjName DROP TABLE #TempTable1;
      
      





システムカタログビュヌぞのリク゚スト



デヌタベヌスの䟝存関係を「リバヌス゚ンゞニアリング」する2番目の方法は、倖郚キヌに関連付けられたディレクトリシステム衚珟を照䌚するこずです。



 --Independent tables SELECT Name AS InDependentTables FROM sys.tables WHERE object_id NOT IN ( SELECT referenced_object_id FROM sys.foreign_key_columns ) -- Check for parents AND object_id NOT IN ( SELECT parent_object_id FROM sys.foreign_key_columns ) -- Check for Dependents ORDER BY Name -- Tables with dependencies. SELECT DISTINCT OBJECT_NAME(referenced_object_id) AS ParentTable , OBJECT_NAME(parent_object_id) AS DependentTable , OBJECT_NAME(constraint_object_id) AS ForeignKeyName FROM sys.foreign_key_columns ORDER BY ParentTable , DependentTable -- Top level of the pyramid tables. Tables with no parents. SELECT DISTINCT OBJECT_NAME(referenced_object_id) AS TablesWithNoParent FROM sys.foreign_key_columns WHERE referenced_object_id NOT IN ( SELECT parent_object_id FROM sys.foreign_key_columns ) ORDER BY 1 -- Bottom level of the pyramid tables. -- Tables with no dependents. (These are the leaves on a tree.) SELECT DISTINCT OBJECT_NAME(parent_object_id) AS TablesWithNoDependents FROM sys.foreign_key_columns WHERE parent_object_id NOT IN ( SELECT referenced_object_id FROM sys.foreign_key_columns ) ORDER BY 1 -- Tables with both parents and dependents. -- Tables in the middle of the hierarchy SELECT DISTINCT OBJECT_NAME(referenced_object_id) AS MiddleTables FROM sys.foreign_key_columns WHERE referenced_object_id IN ( SELECT parent_object_id FROM sys.foreign_key_columns ) AND parent_object_id NOT IN ( SELECT referenced_object_id FROM sys.foreign_key_columns ) ORDER BY 1; -- in rare cases, you might find a self-referencing dependent table. -- Recursive (self) referencing table dependencies. SELECT DISTINCT OBJECT_NAME(referenced_object_id) AS ParentTable , OBJECT_NAME(parent_object_id) AS ChildTable , OBJECT_NAME(constraint_object_id) AS ForeignKeyName FROM sys.foreign_key_columns WHERE referenced_object_id = parent_object_id ORDER BY 1 , 2;
      
      





CTEを䜿甚する



䟝存関係の階局を取埗する3番目の方法は、再垰CTEを䜿甚するこずです。



 -- How to find the hierarchical dependencies -- Solve recursive queries using Common Table Expressions (CTE) WITH TableHierarchy ( ParentTable, DependentTable, Level ) AS ( -- Anchor member definition (First level group to start the process) SELECT DISTINCT CAST(NULL AS INT) AS ParentTable , e.referenced_object_id AS DependentTable , 0 AS Level FROM sys.foreign_key_columns AS e WHERE e.referenced_object_id NOT IN ( SELECT parent_object_id FROM sys.foreign_key_columns ) -- Add filter dependents of only one parent table -- AND Object_Name(e.referenced_object_id) = 'User' UNION ALL -- Recursive member definition (Find all the layers of dependents) SELECT --Distinct e.referenced_object_id AS ParentTable , e.parent_object_id AS DependentTable , Level + 1 FROM sys.foreign_key_columns AS e INNER JOIN TableHierarchy AS d ON ( e.referenced_object_id ) = d.DependentTable ) -- Statement that executes the CTE SELECT DISTINCT OBJECT_NAME(ParentTable) AS ParentTable , OBJECT_NAME(DependentTable) AS DependentTable , Level FROM TableHierarchy ORDER BY Level , ParentTable , DependentTable;
      
      





おわりに

したがっお、1〜2時間で、䞊蚘の「リバヌス゚ンゞニアリング」の方法を䜿甚しお、デヌタベヌスの内郚を把握できたす。



翻蚳者泚テキスト内のすべおのク゚リ1぀を陀き、テキスト内にマヌクされおいたすは、SQL Server 2005 SP3以降の゚ディションで動䜜したす。テキストはかなりボリュヌムがありたす。可胜な限り差し匕いおミス文䜓、構文、セマンティックなどを芋぀けようずしたしたが、䜕かに気が぀かなかったら、おそらく気づかなかったので、PMを曞いおください。



All Articles