I have written query that allows me to have an overview of all Azure SQL Database inside an Azure SQL Server; this query needs to be run on master:
DECLARE #StartDate date = DATEADD(day, -30, GETDATE()) -- 14 Days
SELECT
database_name AS DatabaseName,
sysso.edition
,sysso.service_objective
,(SELECT TOP 1 storage_in_megabytes FROM sys.resource_stats AS rs2 WHERE rs2.database_name = rs1.database_name ORDER BY rs2.start_time DESC) AS StorageMB
,CAST(MAX(storage_in_megabytes) / 1024 AS DECIMAL(10, 2)) StorageGB
,MIN(end_time) AS StartTime
,MAX(end_time) AS EndTime
,CAST(AVG(avg_cpu_percent) AS decimal(4,2)) AS Avg_CPU
,MAX(avg_cpu_percent) AS Max_CPU
,(COUNT(database_name) - SUM(CASE WHEN avg_cpu_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) * 100 AS [CPU Fit %]
,CAST(AVG(avg_data_io_percent) AS decimal(4,2)) AS Avg_IO
,MAX(avg_data_io_percent) AS Max_IO
,(COUNT(database_name) - SUM(CASE WHEN avg_data_io_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) * 100 AS [Data IO Fit %]
,CAST(AVG(avg_log_write_percent) AS decimal(4,2)) AS Avg_LogWrite
,MAX(avg_log_write_percent) AS Max_LogWrite
,(COUNT(database_name) - SUM(CASE WHEN avg_log_write_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) * 100 AS [Log Write Fit %]
FROM sys.resource_stats AS rs1
inner join sys.databases dbs on rs1.database_name = dbs.name
INNER JOIN sys.database_service_objectives sysso on sysso.database_id = dbs.database_id
WHERE start_time > #StartDate
GROUP BY database_name, sysso.edition, sysso.service_objective
ORDER BY database_name , sysso.edition, sysso.service_objective
Here the output:
I would like to add to this query how many logical CPU each database has.
I know that there is query that I can run on each database but I want to SELECT how many logical CPU each database has by querying the master database.
Is there a way to grab such information form the sys. tables?
Or dynamic SQL is the only way to go?
EDIT:
#Charlieface suggested to use SELECT cpu_count FROM sys.dm_os_sys_info which is right but if I run it on master I only see the CPU used on master. I need to retrieve the CPUs used for each database.
You add the following subquery:
(SELECT cpu_count FROM sys.dm_os_sys_info)
See the documentation.
Further information for each processor can be got from sys.dm_os_nodes
It seems Azure Managed Instance only returns data for master. So you need to insert it into a temp table or table variable and join on that.
DECLARE #sql nvarchar(max);
SELECT #sql = STRING_AGG(CAST('
SELECT ' + d.id + ', cpu_count FROM ' + QUOTENAME(d.name) + '.sys.dm_os_sys_info
' AS nvarchar(max)), '
UNION ALL
' )
FROM sys.databases;
PRINT #sql; --your friend
DECLARE #tmp TABLE (db_id int PRIMARY KEY, cpu_count int NOT NULL);
INSERT #tmp (db_id, cpu_count)
EXEC sp_executesql #sql;
SELECT ....
cpu.cpu_count
FROM ...
LEFT JOIN #tmp cpu ON cpu.db_id = dbs.id;
I am trying to create a function that receives as a parameter a start date and a date end of a period and results in a list totaled with the top 5 products sold for each month of the period.
For example:
CREATE FUNCTION top5Sales(#CurrentDate DATETIME, #EndDate DATETIME)
RETURNS TABLE
RETURN
(
WHILE(#CurrentDate < #EndDate)
BEGIN
SELECT TOP 5
AdventureWorks.Sales.SalesOrderDetail.ProductID,
AdventureWorks.Production.Product.Name,
MONTH(AdventureWorks.Sales.SalesOrderHeader.OrderDate) as 'Month',
YEAR(AdventureWorks.Sales.SalesOrderHeader.OrderDate) as 'Year',
SUM(AdventureWorks.Sales.SalesOrderDetail.OrderQty) as 'Total Quantity Sold',
AVG(AdventureWorks.Sales.SalesOrderDetail.UnitPrice) as 'Average Unit Price',
SUM(AdventureWorks.Sales.SalesOrderDetail.UnitPriceDiscount) as 'Total Discount',
SUM(AdventureWorks.Sales.SalesOrderDetail.LineTotal) as 'Total Value Sold'
FROM
AdventureWorks.Sales.SalesOrderDetail
INNER JOIN
AdventureWorks.Sales.SalesOrderHeader
ON
AdventureWorks.Sales.SalesOrderHeader.SalesOrderID = AdventureWorks.Sales.SalesOrderDetail.SalesOrderID
INNER JOIN
AdventureWorks.Production.Product
ON
AdventureWorks.Production.Product.ProductID = AdventureWorks.Sales.SalesOrderDetail.ProductID
WHERE
MONTH(AdventureWorks.Sales.SalesOrderHeader.OrderDate) = month(#CurrentDate)
and
YEAR(AdventureWorks.Sales.SalesOrderHeader.OrderDate) = year(#CurrentDate)
GROUP BY
AdventureWorks.Production.Product.Name,
AdventureWorks.Sales.SalesOrderDetail.ProductID,
MONTH(AdventureWorks.Sales.SalesOrderHeader.OrderDate),
YEAR(AdventureWorks.Sales.SalesOrderHeader.OrderDate)
ORDER BY
[Total Quantity Sold] DESC
SET
#CurrentDate = DATEADD(MONTH, 1, #CurrentDate)
END
)
In fact, the above code is wrong. It serves only to exemplify the problem and give the path to some possible solution.
You do not have to follow that line of thinking. If there is another more interesting solution to this problem, feel free to expose it.
You can use row_number and top 5 with ties and use single query to return this results as below: Can you check this?
CREATE FUNCTION top5Sales(#CurrentDate DATETIME, #EndDate DATETIME)
RETURNS TABLE
RETURN
(
SELECT Top 5 with ties * from (
SELECT
AdventureWorks.Sales.SalesOrderDetail.ProductID,
AdventureWorks.Production.Product.Name,
MONTH(AdventureWorks.Sales.SalesOrderHeader.OrderDate) as 'Month',
YEAR(AdventureWorks.Sales.SalesOrderHeader.OrderDate) as 'Year',
SUM(AdventureWorks.Sales.SalesOrderDetail.OrderQty) as 'Total Quantity Sold',
AVG(AdventureWorks.Sales.SalesOrderDetail.UnitPrice) as 'Average Unit Price',
SUM(AdventureWorks.Sales.SalesOrderDetail.UnitPriceDiscount) as 'Total Discount',
SUM(AdventureWorks.Sales.SalesOrderDetail.LineTotal) as 'Total Value Sold'
FROM
AdventureWorks.Sales.SalesOrderDetail
INNER JOIN
AdventureWorks.Sales.SalesOrderHeader
ON
AdventureWorks.Sales.SalesOrderHeader.SalesOrderID = AdventureWorks.Sales.SalesOrderDetail.SalesOrderID
INNER JOIN
AdventureWorks.Production.Product
ON
AdventureWorks.Production.Product.ProductID = AdventureWorks.Sales.SalesOrderDetail.ProductID
WHERE
AdventureWorks.Sales.SalesOrderHeader.OrderDate > #CurrentDate
AND AdventureWorks.Sales.SalesOrderHeader.OrderDate <= #EndDate
GROUP BY
AdventureWorks.Production.Product.Name,
AdventureWorks.Sales.SalesOrderDetail.ProductID,
MONTH(AdventureWorks.Sales.SalesOrderHeader.OrderDate),
YEAR(AdventureWorks.Sales.SalesOrderHeader.OrderDate)
-- ORDER BY
-- [Total Quantity Sold] DESC
) a
Order by Row_Number() over(Partition by [ProductId], [Name], [Year], [Month] order by [Total Quantity Sold] Desc
)
I checked the AdventureWorks database and I didn't see a Date table. For a basic overview, you can checkout this video - https://www.brentozar.com/training/t-sql-level/3-number-date-tables-10m/
The following logic wouldn't be in an inline-table function, but it's a fast and simple way of SELECTing the data you're looking for.
DECLARE #sql NVARCHAR(Max),
#CurrentDate DATETIME = '2005-06-01 00:00:00.000',
#EndDate DATETIME = '2008-08-31 00:00:00.000';
SELECT #sql = COALESCE( #sql + CHAR(13) + 'UNION' + CHAR(13), '') +
' SELECT TOP 5 ' + CONVERT(NVARCHAR(8), [Year]) + ' AS [Year], '
+ CONVERT(NVARCHAR(8), [Month]) + ' AS [Month],
sod.ProductId,
SUM(sod.OrderQty) AS Sales
FROM Sales.SalesOrderDetail sod
JOIN Sales.SalesOrderHeader soh
ON sod.SalesOrderId = soh.SalesOrderId
AND YEAR(soh.OrderDate) = ' + CONVERT(NVARCHAR(8), [Year]) + '
AND MONTH(soh.OrderDate) = ' + CONVERT(NVARCHAR(8), [Month]) + '
GROUP BY sod.ProductId'
FROM dbo.[Date]
WHERE [Date] BETWEEN #CurrentDate AND #EndDate
EXEC sp_executesql #sql
If you execute this T-SQL you'll find it's very fast and scalable relative to other methods of getting the same data.
I am trying to get the below queries into one row on a query. Below is just an example, I have about 10 counts to combine into one row
select ISNULL(COUNT(*),0) as ENGLAND from Service_User s
where s.commissioner_id ='1'
select ISNULL(COUNT(*),0) as WALES from Service_User s
where s.commissioner_id ='2'
select ISNULL(COUNT(*),0) as GERMANY from Service_User s
where s.commissioner_id ='3'
I have tried to UNION them but they appear vertically and I want them horizontally.
I would like it to appear like below
Try this. Use Sub-select
SELECT (SELECT Isnull(Count(*), 0)
FROM Service_User s
WHERE s.commissioner_id = '1') AS ENGLAND,
(SELECT Isnull(Count(*), 0)
FROM Service_User s
WHERE s.commissioner_id = '2') AS WALES,
(SELECT Isnull(Count(*), 0)
FROM Service_User s
WHERE s.commissioner_id = '3') AS GERMANY
If you are using Sql Server 2012 or above then it can be shorter .
Try this,
;With CTE As
(
select commissioner_id, ROW_NUMBER()Over(Partition By commissioner_id order by commissioner_id) RowNum from Service_User s
s.commissioner_id in(1,2,3)
)
,CTE1 as
(
Select commissioner_id,MAX(RowNum) from CTE
group By commissioner_id
)
select * from CTE
--pivot this result set
If I knew for fact that my commissioner_id's were not doing to change and I could load the values to pivot on into the query I would go with option 1.
SELECT * FROM (select COUNT(*) As Count,(select case commissioner_id when '01' then 'England' when '02' then 'Wales' when '03' then 'Germany' else 'Other') as [Location] from Service_User group by [Location]) as s PIVOT (SUM(count) FOR [Location] IN ("England","Wales","Germany","Other")) AS PivotOut
Second Option I would create a stored procedure that dynamically loaded the options for commissioner_id and then pivoted. This way as the commissioner_ids are added there is no manual intervention to return the required results.
Create PROCEDURE [dbo].[DynamicSP]
AS
BEGIN
declare #sql as varchar(max)
declare #dynamic varchar(max)
select #dynamic=COALESCE(#dynamic +',','')+commissioner_id
FROM
(select distinct commissioner_id from Service_User) as CommIds order by commissioner_id
set #SQL = '(select COUNT(*) As count,commissioner_id as [Location] from Service_User group by [Location]) as s PIVOT (SUM(count) FOR [Location] IN (' + #dynamic + ')) AS PivotOut'
exec(#sql)
END
The below stored procedure works for SQL Server (before I made some oracle specific changes).
Now this stored procedure must work for Oracle too.
The Oracle Sql Developer which I use complains at the line after the "OPEN CURSOR_ FOR"
Somehow Oracle does not like that I 'group' both select statements and the union and do on this whole result an order by...
What do I wrong? I only know a bit about oracle stored procedures...
create or replace
PROCEDURE GetWorkflowStatusForMatrix(
p_ApplicationId IN varchar2,
CURSOR_ OUT sys_refcursor
)
AS
BEGIN
OPEN CURSOR_ FOR
(
select ApplicationId || ModuleId || UNIT_ID as StatusKey, UNIT_ID, ApplicationId, ModuleId, Owner, "Level", Action, "Comment", LastModifiedUser, LastModifiedDate
from WorkflowStatus where ApplicationId = p_ApplicationId
union
select distinct e.ApplicationId + WorkflowId + UnitId as StatusKey, UnitId, e.ApplicationId, WorkflowId, w.Owner, 'Level1', 'Working', EventType, UserId, EventDateTime as LastModifiedDate
from EventLog e
join WorkflowStatus w on w.ApplicationId = e.ApplicationId and w.ModuleId = e.WorkflowId and w.UNIT_ID = e.UnitId
where e.ApplicationId = p_ApplicationId and w.Owner <> '' and w.Action = 'Created'
)
order by LastModifiedDate DESC;
END;
You need to read up on how to Define Cursors in Oracle - this will help you out..
http://www.techonthenet.com/oracle/cursors/declare.php
create or replace
PROCEDURE GetWorkflowStatusForMatrix(
p_ApplicationId IN varchar2,
CURSOR_ OUT sys_refcursor
)
AS
BEGIN
OPEN CURSOR_ FOR
select ApplicationId || ModuleId || UNIT_ID as StatusKey, UNIT_ID, ApplicationId, ModuleId, Owner, "Level", Action, "Comment", LastModifiedUser, LastModifiedDate
from WorkflowStatus where ApplicationId = p_ApplicationId
union
select distinct e.ApplicationId + WorkflowId + UnitId as StatusKey, UnitId, e.ApplicationId, WorkflowId, w.Owner, 'Level1', 'Working', EventType, UserId, EventDateTime as LastModifiedDate
from EventLog e
join WorkflowStatus w on w.ApplicationId = e.ApplicationId and w.ModuleId = e.WorkflowId and w.UNIT_ID = e.UnitId
where e.ApplicationId = p_ApplicationId and w.Owner <> '' and w.Action = 'Created'
order by LastModifiedDate DESC;
END;
Is it possible to list information about the files (MDF/LDF) of all databases on an SQL Server?
I'd like to get a list showing which database is using what files on the local disk.
What I tried:
exec sp_databases all databases
select * from sys.databases shows a lot of information about each database - but unfortunately it doesn't show the files used by each database.
select * from sys.database_files shows the mdf/ldf files of the master database - but not the other databases
You can use sys.master_files.
Contains a row per file of a database as stored in the master
database. This is a single, system-wide view.
If you want get location of Database you can check Get All DBs Location.
you can use sys.master_files for get location of db and sys.database to get db name
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
I am using script to get empty space in each file:
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
Size is expressed in KB.
I've created this query:
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
Executing following sql (It will only work when you don't have multiple mdf/ldf files for same database)
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
will return this output
DBName DataFile LogFile
--------------------------------------------------------------------------------
master C:\....\master.mdf C:\....\mastlog.ldf
tempdb C:\....\tempdb.mdf C:\....\templog.ldf
model C:\....\model.mdf C:\....\modellog.ldf
and rest of the databases
If your TempDB's have multiple MDF's (like mine have), this script will fail.
However, you can use
WHERE db.database_id > 4
at the end and it will return all databases except system databases.
You can also try this.
select db_name(dbid) dbname, filename from sys.sysaltfiles
Below script can be used to get following information:
1. DB Size Info
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
Using this script you can show all the databases name and files used (with exception of system dbs).
select name,physical_name from sys.master_files where database_id > 4
To get around queries which error when multiple data files (e.g. ".ndf" file types) exist, try this version, it replaces the sub-queries with joins.
Here's a version of your query using joins instead of the sub-queries.
Cheers!
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
Sample Results:
(Please note, the single log file is paired with each MDF and NDF for a single database)
This script lists most of what you are looking for and can hopefully be modified to you needs. Note that it is creating a permanent table in there - you might want to change it. It is a subset from a larger script that also summarises backup and job information on various servers.
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]
If you rename your Database, MS SQL Server does not rename the underlying files.
Following query gives you the current name of the database and the Logical file name (which might be the original name of the Database when it was created) and also corresponding physical file names.
Note: Un-comment the last line to see only the actual data files
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'
Reference:
https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-master-files-transact-sql?view=sql-server-ver15
https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-databases-transact-sql?view=sql-server-ver15
Using the sp_MSForEachDB stored procedure is an option
EXEC sp_MSForEachDB 'use ? select * from sys.database_files'
Additionally to see just the Full Path name and size information
EXEC sp_MSForEachDB '
USE [?];
SELECT DB_NAME() AS DbName,
physical_name AS FullPath,
name AS FileName,
type_desc,
size/128.0 AS CurrentSizeMB,
size/128.0 - CAST(FILEPROPERTY(name, ''SpaceUsed'') AS INT)/128.0 AS FreeSpaceMB
FROM sys.database_files
WHERE type IN (0,1);
'
just adding my 2 cents .
if specifically looking to find total free space only in Data files or only in Log files in all the databases, we can use "data_space_id" column. 1 is for data files and 0 for log files.
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
Also you can use this SQL query for retrieving files list :
SELECT d.name AS DatabaseName,
m.name AS LogicalName,
m.physical_name AS PhysicalName,
size AS FileSize
FROM sys.master_files m
INNER JOIN sys.databases d ON(m.database_id = d.database_id)
where d.name = '<Database Name>'
ORDER BY physical_name ;
You can use the below:
SP_HELPDB [Master]
GO