Use this procedure
create or alter procedure spDatabaseCreateFromBak(
@NewDatabaseName nvarchar(128),
@BackupFilePath nvarchar(500),
@DryCall bit = null,
@Debug int = null
) as begin
declare @DefaultDataPath nvarchar(max) = cast(serverproperty('InstanceDefaultDataPath') as nvarchar(max));
declare @DefaultLogPath nvarchar(max) = cast(serverproperty('InstanceDefaultLogPath') as nvarchar(max))
-- produce restore sql
declare @dsql nvarchar(max)
begin
create table #FileList (
LogicalName nvarchar(128),
PhysicalName nvarchar(260),
Type char(1),
FileGroupName nvarchar(128),
Size bigint,
MaxSize bigint,
FileId bigint,
CreateLSN numeric(25,0),
DropLSN numeric(25,0),
UniqueId uniqueidentifier,
ReadOnlyLSN numeric(25,0),
ReadWriteLSN numeric(25,0),
BackupSizeInBytes bigint,
SourceBlockSize int,
FileGroupId int,
LogGroupGUID uniqueidentifier,
DifferentialBaseLSN numeric(25,0),
DifferentialBaseGUID uniqueidentifier,
IsReadOnly bit,
IsPresent bit,
TDEThumbprint varbinary(32),
SnapshotUrl nvarchar(360)
)
insert into #FileList
exec ('restore filelistonly from disk = ''' + @BackupFilePath + '''')
if @Debug >= 2
select [FileList] = '#FileList', * from #FileList f;
set @dsql = (
select string_agg(line, char(10))
from (
select line = concat('restore database [',@NewDatabaseName,']')
union all
select line = concat('from disk = ''',@BackupFilePath,''' with')
union all
select concat('move N''', f.LogicalName, ''' to N''', NewPath, ''',')
from #FileList f
outer apply (
select NewPath = concat(@DefaultDataPath, s.FileName)
from (
select top 1 FileName = s.value
from string_split(f.PhysicalName, '\', 1) s
order by s.ordinal desc
) s
) np
union all
select line = 'replace, recovery'
) t
);
end
if @Debug > 0
print @dsql;
if isnull(@DryCall, 0) = 0
exec(@dsql);
end
Example:
exec spDatabaseCreateFromBak
@BackupFilePath = N'D:\Work\Exports\WideWorldImporters-Full.bak'
, @NewDatabaseName = N'WideWorldImporters'
, @DryCall = 0
, @debug = 2
Which would produce such sql:
restore database [WideWorldImporters]
from disk = 'D:\Work\Exports\WideWorldImporters-Full.bak' with
move N'WWI_Primary' to N'D:\SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\WideWorldImporters.mdf',
move N'WWI_UserData' to N'D:\SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\WideWorldImporters_UserData.ndf',
move N'WWI_Log' to N'D:\SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\WideWorldImporters.ldf',
move N'WWI_InMemory_Data_1' to N'D:\SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\WideWorldImporters_InMemory_Data_1',
replace, recovery