Liste des informations sur tous les fichiers de base de données dans SQL Server

90

Est-il possible de lister les informations sur les fichiers (MDF / LDF) de toutes les bases de données sur un serveur SQL?

Je voudrais obtenir une liste montrant quelle base de données utilise quels fichiers sur le disque local.

Ce que j'ai essayé:

  • exec sp_databases toutes les bases de données
  • select * from sys.databases affiche beaucoup d'informations sur chaque base de données - mais malheureusement, il ne montre pas les fichiers utilisés par chaque base de données.
  • select * from sys.database_filesaffiche les fichiers mdf / ldf de la masterbase de données - mais pas les autres bases de données
M4N
la source

Réponses:

123

Vous pouvez utiliser sys.master_files .

Contient une ligne par fichier d'une base de données telle qu'elle est stockée dans la base de données master. Il s'agit d'une vue unique à l'échelle du système.

Mikael Eriksson
la source
4
Merci, c'est ce que je recherchais (joint à sys.databases)!
M4N
1
sélectionnez * à partir de sys.master_files
Cosmin
2
@ M4N Si vous souhaitez simplement obtenir le nom de la base de données, vous pouvez également appeler à la DB_NAME(database_id)place en rejoignantsys.databases
Cleptus
84

Si vous voulez obtenir l'emplacement de la base de données, vous pouvez cocher Obtenir l' emplacement de toutes les bases de données .
vous pouvez utiliser sys.master_filespour obtenir l'emplacement de la base de données et sys.databsepour obtenir le nom de la base de données

SELECT
    db.name AS DBName,
    type_desc AS FileType,
    Physical_Name AS Location
FROM
    sys.master_files mf
INNER JOIN 
    sys.databases db ON db.database_id = mf.database_id
Mehdi Haghshenas
la source
18

J'utilise un script pour obtenir un espace vide dans chaque fichier:

Create Table ##temp
(
    DatabaseName sysname,
    Name sysname,
    physical_name nvarchar(500),
    size decimal (18,2),
    FreeSpace decimal (18,2)
)   
Exec sp_msforeachdb '
Use [?];
Insert Into ##temp (DatabaseName, Name, physical_name, Size, FreeSpace)
    Select DB_NAME() AS [DatabaseName], Name,  physical_name,
    Cast(Cast(Round(cast(size as decimal) * 8.0/1024.0,2) as decimal(18,2)) as nvarchar) Size,
    Cast(Cast(Round(cast(size as decimal) * 8.0/1024.0,2) as decimal(18,2)) -
        Cast(FILEPROPERTY(name, ''SpaceUsed'') * 8.0/1024.0 as decimal(18,2)) as nvarchar) As FreeSpace
    From sys.database_files
'
Select * From ##temp
drop table ##temp

La taille est exprimée en Ko.

Jānis
la source
Que Use [?]doit-on faire? Il donne une erreur indiquant qu'il ne peut pas trouver cette procédure stockée. Le supprimer n'affiche que plusieurs fois les bases de données système.
Abel
4

J'ai créé cette requête:

SELECT 
    db.name AS                                   [Database Name], 
    mf.name AS                                   [Logical Name], 
    mf.type_desc AS                              [File Type], 
    mf.physical_name AS                          [Path], 
    CAST(
        (mf.Size * 8
        ) / 1024.0 AS DECIMAL(18, 1)) AS         [Initial Size (MB)], 
    'By '+IIF(
            mf.is_percent_growth = 1, CAST(mf.growth AS VARCHAR(10))+'%', CONVERT(VARCHAR(30), CAST(
        (mf.growth * 8
        ) / 1024.0 AS DECIMAL(18, 1)))+' MB') AS [Autogrowth], 
    IIF(mf.max_size = 0, 'No growth is allowed', IIF(mf.max_size = -1, 'Unlimited', CAST(
        (
                CAST(mf.max_size AS BIGINT) * 8
        ) / 1024 AS VARCHAR(30))+' MB')) AS      [MaximumSize]
FROM 
     sys.master_files AS mf
     INNER JOIN sys.databases AS db ON
            db.database_id = mf.database_id
Alexandru-Codrin Panaite
la source
3

Vous pouvez également essayer ceci.

 select db_name(dbid) dbname, filename from sys.sysaltfiles
Joe Pi
la source
3

Exécution de sql suivant (cela ne fonctionnera que si vous n'avez pas plusieurs fichiers mdf / ldf pour la même base de données)

SELECT
    db.name AS DBName,
    (select mf.Physical_Name FROM sys.master_files mf where mf.type_desc = 'ROWS' and db.database_id = mf.database_id ) as DataFile,
    (select mf.Physical_Name FROM sys.master_files mf where mf.type_desc = 'LOG' and db.database_id = mf.database_id ) as LogFile
FROM sys.databases db

retournera cette sortie

DBName       DataFile                     LogFile
--------------------------------------------------------------------------------
master       C:\....\master.mdf           C:\....\mastlog.ldf
tempdb       C:\....\tempdb.mdf           C:\....\templog.ldf
model        C:\....\model.mdf            C:\....\modellog.ldf

et le reste des bases de données

Si vos TempDB ont plusieurs MDF (comme le mien), ce script échouera. Cependant, vous pouvez utiliser

WHERE db.database_id > 4

à la fin et il renverra toutes les bases de données à l'exception des bases de données système.

adeel41
la source
Je sais que c'est un petit ensemble de données, mais ce n'est pas une raison d'utiliser des sous-requêtes corrélées. Ils peuvent convenir à Oracle, mais ils réduisent considérablement les performances de SQL Server, car ils entraînent un traitement ligne par ligne. Votre script interrogera la table sys.master_files deux fois pour chaque ligne de la table sys.databases.
Davos
2
En plus du commentaire de Davos ... Ce script échouera également avec des erreurs si vous avez plusieurs fichiers de données ou fichiers journaux pour une base de données. (Par exemple, la sous-requête a renvoyé plus de 1 valeur.)
Arkaine55
@Davos Je sais ce que vous dites mais cela dépend de la fréquence à laquelle vous exécutez cette requête, sinon c'est une pré-optimisation dont vous n'avez probablement pas besoin.
adeel41
2
Je suis généralement d'accord pour dire que l'optimisation précoce est mauvaise, mais ce que je dis, c'est que les sous-requêtes corrélées ne sont qu'un mauvais modèle qui ne devrait jamais être utilisé en premier lieu. Il y a toujours des exceptions aux règles «jamais», mais ce n'est pas l'un de ces cas. Je sais que c'est mineur et que cela n'a peut-être vraiment pas d'importance ici, mais ce n'est pas le problème. Il s'agit d'un forum public que les débutants utilisent pour apprendre les bonnes pratiques, vous devez donc fournir un code de modèle de rôle.
Davos
1
La requête entraînera une erreur si plusieurs fichiers de données sont utilisés dans l'une des bases de données. Voici une version de votre requête utilisant des jointures à la place. À votre santé! SELECT db.name AS DBName, db.database_id, mfr.Physical_Name AS DataFile, mfl.Physical_Name AS LogFile FROM sys.databases db JOIN sys.master_files mfr ON db.database_id = mfr.database_id ET mfr.type_desc = 'ROWS' JOIN sys. .master_files mfl ON db.database_id = mfl.database_id ET mfl.type_desc = 'LOG' ORDER BY db.database_id
Robert
2

En utilisant ce script, vous pouvez afficher le nom de toutes les bases de données et les fichiers utilisés (à l'exception de la base de données système).

select name,physical_name from sys.master_files where database_id > 4
Jorge Cribb
la source
1

Ce script répertorie la plupart de ce que vous recherchez et peut, espérons-le, être modifié selon vos besoins. Notez qu'il crée une table permanente là-dedans - vous voudrez peut-être la changer. Il s'agit d'un sous-ensemble d'un script plus volumineux qui résume également les informations de sauvegarde et de travail sur divers serveurs.

IF OBJECT_ID('tempdb..#DriveInfo') IS NOT NULL
 DROP TABLE #DriveInfo
CREATE TABLE #DriveInfo
 (
    Drive CHAR(1)
    ,MBFree INT
 ) 

INSERT  INTO #DriveInfo
      EXEC master..xp_fixeddrives


IF OBJECT_ID('[dbo].[Tmp_tblDatabaseInfo]', 'U') IS NOT NULL 
   DROP TABLE [dbo].[Tmp_tblDatabaseInfo]
CREATE TABLE [dbo].[Tmp_tblDatabaseInfo](
      [ServerName] [nvarchar](128) NULL
      ,[DBName] [nvarchar](128)  NULL
      ,[database_id] [int] NULL
      ,[create_date] datetime NULL
      ,[CompatibilityLevel] [int] NULL
      ,[collation_name] [nvarchar](128) NULL
      ,[state_desc] [nvarchar](60) NULL
      ,[recovery_model_desc] [nvarchar](60) NULL
      ,[DataFileLocations] [nvarchar](4000)
      ,[DataFilesMB] money null
      ,DataVolumeFreeSpaceMB INT NULL
      ,[LogFileLocations] [nvarchar](4000)
      ,[LogFilesMB] money null
      ,LogVolumeFreeSpaceMB INT NULL

) ON [PRIMARY]

INSERT INTO [dbo].[Tmp_tblDatabaseInfo] 
SELECT 
      @@SERVERNAME AS [ServerName] 
      ,d.name AS DBName 
      ,d.database_id
      ,d.create_date
      ,d.compatibility_level  
      ,CAST(d.collation_name AS [nvarchar](128)) AS collation_name
      ,d.[state_desc]
      ,d.recovery_model_desc
      ,(select physical_name + ' | ' AS [text()]
         from sys.master_files m
         WHERE m.type = 0 and m.database_id = d.database_id
         ORDER BY file_id
         FOR XML PATH ('')) AS DataFileLocations
      ,(select sum(size) from sys.master_files m WHERE m.type = 0 and m.database_id = d.database_id)  AS DataFilesMB
      ,NULL
      ,(select physical_name + ' | ' AS [text()]
         from sys.master_files m
         WHERE m.type = 1 and m.database_id = d.database_id
         ORDER BY file_id
         FOR XML PATH ('')) AS LogFileLocations
      ,(select sum(size) from sys.master_files m WHERE m.type = 1 and m.database_id = d.database_id)  AS LogFilesMB
      ,NULL
FROM  sys.databases d  

WHERE d.database_id > 4 --Exclude basic system databases
UPDATE [dbo].[Tmp_tblDatabaseInfo] 
   SET DataFileLocations = 
      CASE WHEN LEN(DataFileLocations) > 4 THEN  LEFT(DataFileLocations,LEN(DataFileLocations)-2) ELSE NULL END
   ,LogFileLocations =
      CASE WHEN LEN(LogFileLocations) > 4 THEN  LEFT(LogFileLocations,LEN(LogFileLocations)-2) ELSE NULL END
   ,DataFilesMB = 
      CASE WHEN DataFilesMB > 0 THEN  DataFilesMB * 8 / 1024.0   ELSE NULL END
   ,LogFilesMB = 
      CASE WHEN LogFilesMB > 0 THEN  LogFilesMB * 8 / 1024.0  ELSE NULL END
   ,DataVolumeFreeSpaceMB = 
      (SELECT MBFree FROM #DriveInfo WHERE Drive = LEFT( DataFileLocations,1))
   ,LogVolumeFreeSpaceMB = 
      (SELECT MBFree FROM #DriveInfo WHERE Drive = LEFT( LogFileLocations,1))

select * from [dbo].[Tmp_tblDatabaseInfo] 
Gérard
la source
Un excellent script qui peut être copié / collé et utilisé tel quel. Une question cependant, je vois que car LogVolumeFreeSpaceMBil montre toujours le même montant pour tous les fichiers, dans mon cas 44756. Est-il possible d'obtenir l'espace libre réel? Ou est-ce le nombre d'espace libre maximum sur le lecteur où se trouve le LDF?
Abel
Salut Abel - Cela fait un moment que j'ai écrit et je ne suis pas vraiment sûr de votre problème. Il existe une alternative à XP_FIXEDDRIVES appelée sys.dm_os_volume_stats afin que vous puissiez essayer de l'utiliser. Si le problème est que les tailles de fichier de la base de données ne changent pas au fil du temps, cela est normal car SQL Server alloue un gros blob d'espace disque vide pour son utilisation et n'étend pas ce fichier tant qu'il n'a pas été rempli. Il développera un fichier par sauts avec le montant déterminé par les paramètres de fichier pour cette base de données particulière
Gerard
0

La requête produira une erreur si plusieurs fichiers de données (par exemple les types de fichiers ".ndf") sont utilisés dans l'une des bases de données.

Voici une version de votre requête utilisant des jointures au lieu des sous-requêtes.

À votre santé!

SELECT
    db.name AS DBName,
    db.database_id,
    mfr.physical_name AS DataFile,
    mfl.physical_name AS LogFile
FROM sys.databases db
    JOIN sys.master_files mfr ON db.database_id=mfr.database_id AND mfr.type_desc='ROWS'
    JOIN sys.master_files mfl ON db.database_id=mfl.database_id AND mfl.type_desc='LOG'
ORDER BY db.database_id
Robert
la source
0

Le script ci-dessous peut être utilisé pour obtenir les informations suivantes: 1. Informations sur la taille de la base de données 2. FileSpaceInfo 3. AutoGrowth 4. Recovery Model 5. Log_reuse_backup information

CREATE TABLE #tempFileInformation
(
DBNAME          NVARCHAR(256),
[FILENAME]      NVARCHAR(256),
[TYPE]          NVARCHAR(120),
FILEGROUPNAME   NVARCHAR(120),
FILE_LOCATION   NVARCHAR(500),
FILESIZE_MB     DECIMAL(10,2),
USEDSPACE_MB    DECIMAL(10,2),
FREESPACE_MB    DECIMAL(10,2),
AUTOGROW_STATUS NVARCHAR(100)
)
GO

DECLARE @SQL VARCHAR(2000)

SELECT @SQL = '
 USE [?]
            INSERT INTO #tempFileInformation
            SELECT  
                DBNAME          =DB_NAME(),     
                [FILENAME]      =A.NAME,
                [TYPE]          = A.TYPE_DESC,
                FILEGROUPNAME   = fg.name,
                FILE_LOCATION   =a.PHYSICAL_NAME,
                FILESIZE_MB     = CONVERT(DECIMAL(10,2),A.SIZE/128.0),
                USEDSPACE_MB    = CONVERT(DECIMAL(10,2),(A.SIZE/128.0 - ((A.SIZE - CAST(FILEPROPERTY(A.NAME,''SPACEUSED'') AS INT))/128.0))),
                FREESPACE_MB    = CONVERT(DECIMAL(10,2),(A.SIZE/128.0 -  CAST(FILEPROPERTY(A.NAME,''SPACEUSED'') AS INT)/128.0)),
                AUTOGROW_STATUS = ''BY '' +CASE is_percent_growth when 0 then cast (growth/128 as varchar(10))+ '' MB - ''
                                                                  when 1 then cast (growth as varchar(10)) + ''% - '' ELSE '''' END
                                                                  + CASE MAX_SIZE WHEN 0 THEN '' DISABLED '' 
                                                                                  WHEN -1 THEN '' UNRESTRICTED''
                                                                                  ELSE '' RESTRICTED TO '' + CAST(MAX_SIZE/(128*1024) AS VARCHAR(10)) + '' GB '' END
                                                                + CASE IS_PERCENT_GROWTH WHEn 1 then '' [autogrowth by percent]'' else '''' end
    from sys.database_files A
    left join sys.filegroups fg on a.data_space_id = fg.data_space_id
    order by A.type desc,A.name
    ;
    '

    --print @sql

    EXEC sp_MSforeachdb @SQL
    go

    SELECT dbSize.*,fg.*,d.log_reuse_wait_desc,d.recovery_model_desc
    FROM #tempFileInformation fg
    LEFT JOIN sys.databases d on fg.DBNAME = d.name
    CROSS APPLY
    (
        select dbname,
                sum(FILESIZE_MB) as [totalDBSize_MB],
                sum(FREESPACE_MB) as [DB_Free_Space_Size_MB],
                sum(USEDSPACE_MB) as [DB_Used_Space_Size_MB]
            from #tempFileInformation
            where  dbname = fg.dbname
            group by dbname
    )dbSize


go
DROP TABLE #tempFileInformation
Vinod Narwal
la source
0

juste en ajoutant mes 2 cents.

si vous cherchez spécifiquement à trouver l'espace libre total uniquement dans les fichiers de données ou uniquement dans les fichiers journaux de toutes les bases de données, nous pouvons utiliser la colonne "data_space_id". 1 est pour les fichiers de données et 0 pour les fichiers journaux.

CODE:

Create Table ##temp
(
    DatabaseName sysname,
    Name sysname,
    spacetype sysname,
    physical_name nvarchar(500),
    size decimal (18,2),
    FreeSpace decimal (18,2)
)   
Exec sp_msforeachdb '
Use [?];

Insert Into ##temp (DatabaseName, Name,spacetype, physical_name, Size, FreeSpace)
    Select DB_NAME() AS [DatabaseName], Name,   ***data_space_id*** , physical_name,
    Cast(Cast(Round(cast(size as decimal) * 8.0/1024.0,2) as decimal(18,2))/1024 as nvarchar) SizeGB,
    Cast(Cast(Round(cast(size as decimal) * 8.0/1024.0,2)/1024 as decimal(18,2)) -
        Cast(FILEPROPERTY(name, ''SpaceUsed'') * 8.0/1024.0 as decimal(18,2))/1024 as nvarchar) As FreeSpaceGB
    From sys.database_files'


select  
    databasename
    , sum(##temp.FreeSpace) 
from 
    ##temp 
where 
    ##temp.spacetype = 1  
group by 
    DatabaseName

drop table ##temp 

Raj Nair
la source
0

Si vous renommez votre base de données, MS SQL Server ne renomme pas les fichiers sous-jacents.

La requête suivante vous donne le nom actuel de la base de données et le nom du fichier logique (qui peut être le nom d'origine de la base de données lors de sa création) ainsi que les noms de fichiers physiques correspondants.

Remarque: annulez le commentaire de la dernière ligne pour voir uniquement les fichiers de données réels

select  db.database_id, 
        db.name "Database Name", 
        files.name "Logical File Name",
        files.physical_name
from    sys.master_files files 
        join sys.databases db on db.database_id = files.database_id 
--                           and files.type_desc = 'ROWS'

Référence:

https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-master-files-transact-sql?view=sql-server-ver15

https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-databases-transact-sql?view=sql-server-ver15

ssh
la source
-3

Vous pouvez utiliser ce qui suit:

SP_HELPDB [Master]
GO
Iza
la source
Cela ne fournit des informations que pour la base de données spécifiée unique. La question est pour TOUTES les bases de données.
Thronk