• And it won't restore a database backup that has more files than the database you're replacing.

    I have been using the following code for generating the 'move' parameters, which handles this situation by putting new files in the default file path:

    DECLARE @Move nvarchar(max);

    SET @Move = NULL

    SELECT @Move = COALESCE(@Move + ',

    ', ' ') + 'MOVE N''' + lfn.LogicalName + ''' TO N'''

    + COALESCE(mf.physical_name, -- Use filename and path from existing file

    -- Or put new files in 'default paths':

    CASE lfn.[Type]

    WHEN 'D' THEN CONCAT(CONVERT(nvarchar(max), SERVERPROPERTY('instancedefaultdatapath')), LogicalName, '.mdf')

    WHEN 'L' THEN CONCAT(CONVERT(nvarchar(max), SERVERPROPERTY('instancedefaultlogpath')), LogicalName, '.ldf')

    END

    ) + ''''

    FROM #logicalfilenames lfn

    LEFT JOIN (

    SELECT DatabaseName = d.name, mf.name, mf.physical_name

    FROM sys.master_files mf

    JOIN sys.databases d ON d.database_id = mf.database_id

    ) mf ON mf.name = lfn.LogicalName AND mf.DatabaseName = @dbname