The following SQL statement works fine:
DECLARE @database VARCHAR(30) = 'DEMO';
BACKUP LOG @database
TO DISK = N'C:\zbackups\DEMO.trn'
WITH NOFORMAT, NOINIT,
NAME = N'MyDatabase Log Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10;
DBCC SHRINKFILE ('DEMO_log', 500);
This however does not:
DECLARE @database VARCHAR(30) = 'DEMO';
BACKUP LOG @database
TO DISK = 'C:\zbackups\' @database '.trn'
WITH NOFORMAT, NOINIT,
NAME = 'MyDatabase Log Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10;
DBCC SHRINKFILE (@database '_log', 500);
Both the TO DISK
directive and the DBCC SHRINKFILE
parameters throw an error when I attempt to concatenate.
How do I use a variable in these location? Would also like to append some datetime parameters to the file path but haven't started researching that yet.
CodePudding user response:
The problem is simply that you can't pass an expression there. Instead of:
TO DISK = 'C:\zbackups\' @database '.trn'
You need:
DECLARE @fullpath nvarchar(1024);
SET @fullpath = 'C:\zbackups\' @database '.trn';
...
TO DISK = @fullpath
...
You can also parameterize the backup name and log file name in a similar way (instead of hard-coding NAME = 'MyDatabase Log Backup'
). But to get the shrink operation to run in the right context (if you really, really, really, really need it, that is), and you can rely on every single database being configured in the same way, you're going to have to hard-code the database name somewhere (e.g. in a USE
statement), or use dynamic SQL to set the context to the right database, e.g.
DECLARE @database sysname = N'DEMO';
DECLARE @fullpath nvarchar(1024) = N'C:\zbackups\' @database '.trn',
@backup_name nvarchar(500) = @database N' log backup',
@log_name nvarchar(500) = @database _ N'_log';
DECLARE @sql nvarchar(max) = N'BACKUP LOG @db
TO DISK = @fullpath
WITH NOFORMAT, NOINIT, NAME = @backup_name,
SKIP, NOREWIND, NOUNLOAD, STATS = 10;
DBCC SHRINKFILE(@log, 500);';
DECLARE @context nvarchar(1024) = QUOTENAME(@database)
N'.sys.sp_executesql';
EXECUTE @context @sql, -- run @sql but in the context of @database
N'@db sysname, @log nvarchar(500),
@fullpath nvarchar(1024), @backup_name nvarchar(500)',
@database, @log_name, @fullpath, @backup_name;
CodePudding user response:
According to https://docs.microsoft.com/en-us/sql/t-sql/statements/backup-transact-sql?view=sql-server-ver16 a variable can be used. I think an expression would be listed if allowed. The same goes for DBCC SHRINKFILE. Try
DECLARE @database VARCHAR(30) = 'DEMO';
DECLARE @target VARCHAR(260) = 'C:\zbackups\' @database '.trn';
DECLARE @logical_name VARCHAR(128) = @database '_log';
BACKUP LOG @database
TO DISK = @target
WITH NOFORMAT, NOINIT,
NAME = 'MyDatabase Log Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10;
DBCC SHRINKFILE (@logical_name, 500);
If the logical file name does not always follow the dbname_log pattern, perhaps lookup the file id and use that instead of the logical name in SHRINKFILE. Be careful of database scope on the connection.
DECLARE @file_id int
SELECT @file_id = file_id
FROM sys.database_files
WHERE physical_name = @target