What are orphaned datafiles?
Orphaned database files are files not associated with any attached database (live database).
Sometimes when you drop a database from a SQL Server instance, the underlying files are not removed.
If you manage a lot of development and test environments, this can certainly occur.
Usually, when you take a database offline and forget to put it back online before remove.
Why should you care about them?
Offline databases and orphaned files may be using unnecessary space in your SQL Server storage.
How can I check them?
Offline databases
Run the script below to list all offline databases from your instance.
SELECT
'DB_NAME' = db.name,
'FILE_NAME' = mf.name,
'FILE_TYPE' = mf.type_desc,
'FILE_PATH' = mf.physical_name
FROM sys.databases db
INNER JOIN sys.master_files mf ON db.database_id = mf.database_id
WHERE db.state = 6
Orphaned database files
You can run the script below and find the orphaned database from an instance.
DECLARE @DefaultDataPath VARCHAR(512), @DefaultLogPath VARCHAR(512);
SET @DefaultDataPath = CAST(SERVERPROPERTY('InstanceDefaultDataPath') AS VARCHAR(512));
SET @DefaultLogPath = CAST(SERVERPROPERTY('InstanceDefaultLogPath') AS VARCHAR(512));
IF OBJECT_ID('tempdb..#OrphanedDataFiles') IS NOT NULL
DROP TABLE #OrphanedDataFiles;
CREATE TABLE #OrphanedDataFiles (
Id INT IDENTITY(1,1),
[FileName] NVARCHAR(512),
Depth smallint,
FileFlag bit,
Directory VARCHAR(512) NULL,
FullFilePath VARCHAR(512) NULL);
INSERT INTO #OrphanedDataFiles ([FileName], Depth, FileFlag)
EXEC MASTER..xp_dirtree @DefaultDataPath, 1, 1;
UPDATE #OrphanedDataFiles
SET Directory = @DefaultDataPath, FullFilePath = @DefaultDataPath + [FileName]
WHERE Directory IS NULL;
INSERT INTO #OrphanedDataFiles ([FileName], Depth, FileFlag)
EXEC MASTER..xp_dirtree @DefaultLogPath, 1, 1;
UPDATE #OrphanedDataFiles
SET Directory = @DefaultLogPath, FullFilePath = @DefaultLogPath + [FileName]
WHERE Directory IS NULL;
SELECT
f.[FileName],
f.Directory,
f.FullFilePath
FROM #OrphanedDataFiles f
LEFT JOIN sys.master_files mf ON f.FullFilePath = REPLACE(mf.physical_name,'\\', '\')
WHERE mf.physical_name IS NULL AND f.FileFlag = 1
ORDER BY f.[FileName], f.Directory
DROP TABLE #OrphanedDataFiles;
Also, you can do this using dba tools (PowerShell).
How to fix it?
Since they are still offline, they probably not necessary.
- Consider removing the files.
- If there is a potential, you may need something from them, backup first.
More information
Multi-server Script to Find Orphaned Data Files using PowerShell, Prashanth Jayaram- SQLShack.
Microsoft – ALTER DATABASE SET options.