SQL GO disrupts chain of local variables - sql

I use script for DB backup as below:
---- INITIALIZATION
-- UNIFIED DATE
DECLARE #DAT DATETIME
SELECT #DAT = GETDATE()
-- DEFAULT BACKUPS LOCATION
DECLARE #PATH VARCHAR(20)
SELECT #PATH = 'Q:\DBbackup\Default\'
---- DATABASE BACKUPS
-- DB1
DECLARE #DBNAME VARCHAR(64)
SELECT #DBNAME = 'DB1'
DECLARE #BACKUPNAME VARCHAR(64)
DECLARE #DESCRIPTION VARCHAR (255)
SELECT #BACKUPNAME = (#PATH + #DBNAME +'_'+ CONVERT(VARCHAR(19),#DAT,121) + '.bak')
SELECT #DESCRIPTION = #DBNAME + ' Full ad hoc backup ' + CONVERT(VARCHAR(20),#DAT)
SELECT #BACKUPNAME
BACKUP DATABASE #DBNAME TO DISK = #BACKUPNAME WITH FORMAT, INIT, NAME = #DESCRIPTION, SKIP, NOREWIND, NOUNLOAD, STATS = 10, COMPRESSION
GO
-- DB2
DECLARE #DBNAME VARCHAR(64)
SELECT #DBNAME = 'DB2'
DECLARE #BACKUPNAME VARCHAR(64)
DECLARE #DESCRIPTION VARCHAR (255)
SELECT #BACKUPNAME = (#PATH + #DBNAME + '_' + CONVERT(VARCHAR(19),#DAT,121) + '.bak')
SELECT #DESCRIPTION = #DBNAME + ' Full ad hoc backup ' + CONVERT(VARCHAR(20),#DAT)
BACKUP DATABASE #DBNAME TO DISK = #BACKUPNAME WITH FORMAT, INIT, NAME = #DESCRIPTION, SKIP, NOREWIND, NOUNLOAD, STATS = 10, COMPRESSION
GO
However, for backup DB2 the variables #PATH and #DAT are not found as they apply only to first backup. It seems the GO command cancels the effect of local variables for DB2 backup. Is there any workaround for this situation? I want to use the variables in INIT only once, not duplicate them for each database backup.

SQL Server does not know what GO means. That's an SSMS feature. It causes multiple batches to be sent. Either remove GO (and restructure the variables so that they are declared only once) or store that data in a persistent location such as a temp table.
Unfortunately, no great options. T-SQL is a stone-age language.

Related

Query for backups

I'm new to sql, and I'm trying to do a query for my backups, but I'm getting an error with some of the lines, I have 20 or more databases, but my query doesn't work on all the DB, its the same query for each DB, it display a message:
query:
USE [DB Name];
GO
BACKUP DATABASE DB Name
TO DISK = 'E:\xxxx\xx\DB Name.Bak'
;WITH FORMAT
MEDIANAME = 'DB Name_SQLServerBackups',
NAME = 'Full Backup DB Name'
Is giving the error message:
Msg 102, Level 15, State 1, Line 69
Incorrect syntax near 'DB Name'.
What am I doing wrong? Really appreciate your help.
Try using brackets around the second [DB Name] too and make a few syntax fixes to your command:
USE [DB Name];
GO
BACKUP DATABASE [DB Name]
TO DISK = 'E:\xxxx\xx\DB Name.Bak'
WITH FORMAT
, MEDIANAME = 'DB Name_SQLServerBackups'
, NAME = 'Full Backup DB Name';
(this worked for me)
Your best place to start would be with the scripts put together by Ola Hallengren which are very comprehensive and cover everything you will need.
Try this:
USE master
BACKUP DATABASE [AdventureWorks2012]
TO DISK = N'D:\Backup\AdventureWorks2012.bak'
WITH COPY_ONLY, NOFORMAT,
NOINIT,
NAME = N'AdventureWorks2012-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
--SPlit backup Process
USE master
BACKUP DATABASE [AdventureWorks2012]
TO DISK = N'D:\Backup\AdventureWorks2012_1.bak'
,DISK = N'D:\Backup\AdventureWorks2012_2.bak'
,DISK = N'D:\Backup\AdventureWorks2012_3.bak'
,DISK = N'D:\Backup\AdventureWorks2012_4.bak'
WITH COPY_ONLY, NOFORMAT,
NOINIT,
NAME = N'AdventureWorks2012-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
Here is a simple script that will backup all databases on your server. I would look carefully at this and learn exactly what it is doing. It's a good starting point but I would try to work to create your own scripts, what works best for you. The cursor allows you to iterate through all the databases and STATIC ensures you capture all databases when querying sys.databases.
/* Full database backup for all user databases. */
DECLARE #dbname varchar (300)
DECLARE #filepath varchar (1000)
DECLARE #filedate varchar (20)
DECLARE #filename varchar (256)
DECLARE #subdir varchar (1000)
SET #filepath = 'C:\TestBackup\' --This is your backup directory
SET #filedate = REPLACE(GETDATE(), ':', '_') --CONVERT(VARCHAR(10),GETDATE(),112) --gets the date and timestamp, replaces : with an underscore
DECLARE backup_cursor CURSOR STATIC FORWARD_ONLY FOR
SELECT [name]
FROM master.sys.databases sd
-- WHERE ... exclude databases
OPEN backup_cursor
FETCH NEXT FROM backup_cursor INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #subdir = 'C:\Backup\' + #dbname
EXEC master.dbo.xp_create_subdir #subdir
SET #fileName = #filepath + #dbname + '\' + #dbname + '_' + #fileDate + '.bak'
BACKUP DATABASE #dbname TO DISK = #fileName
WITH CHECKSUM, STOP_ON_ERROR
RESTORE VERIFYONLY FROM DISK = #fileName
WITH STOP_ON_ERROR
FETCH NEXT FROM backup_cursor INTO #dbname
END
CLOSE backup_cursor
DEALLOCATE backup_cursor

SQL Server restore proc with database name parameter

Looking for a stored procedure to restore from a .bak file, but would like to be able to enter the db name as a parameter, i.e. Exec sp_restore #dbname
The paths to the .bak will be identical for all the dbs i.e. all dbs are dev copies of the same production backup.
Each .mdf and .ldf will have the same name as the db itself i.e.
dbname = #dbname, mdf = D:\data\#dbname.mdf, ldf =D:\data\#dbname.ldf
The paths to .mdf and .ldf will be the identical for each db, i.e. D:\data\#dbname.mdf
Using Sql Server Management Studio, you can start performing a restore operation. Before completing the task, you should be able to see a "Script" button. This will create a script with all the parameters you have manually entered, including mdf and ldf location. You can then save this script and execute it at will. You can also modify the resulting script to make the database name an input variable. You can do anything really. It's SQL!
A sample script that restores a database and changes mdf and ldf file locations would look like this:
RESTORE DATABASE [example] FROM DISK = N'E:\Backup\example.BAK' WITH FILE = 1, MOVE N'ExampleData' TO N'E:\dbfiles\example.mdf', MOVE N'example_log' TO N'E:\dbfiles\example.ldf', NOUNLOAD, STATS = 10
GO
You can read more about the RESTORE statement
You can then insert the script in a stored procedure as such:
CREATE PROCEDURE RestoreDb
-- Add the parameters for the stored procedure here
#dbName nvarchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
RESTORE DATABASE #dbName FROM DISK = N'C:\Data\MSSQL\Backup\lolwut.bak' WITH FILE = 1, NOUNLOAD, STATS = 10
END
GO
Procedure for restore DB from bak-file #DeviceName. It works with DBs, wich have two logical files.
How to use:
EXEC RestoreDb #dbName='qqq', #DeviceName = 'D:\temp\1\R.bak'
Sorry for my English, I improve it.
CREATE PROCEDURE RestoreDb
#dbName NVARCHAR(50),
#DeviceName NVARCHAR(400)
AS
SET NOCOUNT ON
DECLARE #Cmd NVARCHAR(1000),
#DataLogicalName NVARCHAR(200),
#LogLogicalName NVARCHAR(200),
#DatabasePath NVARCHAR(200),
#DataPath NVARCHAR(300),
#LogPath NVARCHAR(300)
CREATE TABLE #Files
(
LogicalName nvarchar(128),
PhysicalName nvarchar(260),
[Type] char(1),
FileGroupName nvarchar(128),
Size numeric(20,0),
MaxSize numeric(20,0),
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)
)
SELECT #DatabasePath = 'D:\data\'
SELECT #DataPath = #DatabasePath + #dbName + '.mdf',
#LogPath = #DatabasePath + #dbName + '.ldf'
SELECT #Cmd = 'RESTORE FILELISTONLY
FROM DISK = ''' + #DeviceName + ''''
INSERT #Files
EXEC (#Cmd)
IF NOT EXISTS(SELECT 1 FROM #Files) GOTO ERRORFILES
IF (SELECT COUNT(*) FROM #Files) > 2 GOTO ERRORFILESCOUNT
SELECT #DataLogicalName = LogicalName
FROM #Files
WHERE [Type] = 'D'
SELECT #LogLogicalName = LogicalName
FROM #Files
WHERE [Type] = 'L'
RESTORE DATABASE #DbName
FROM DISK = #DeviceName
WITH
MOVE #DataLogicalName TO #DataPath,
MOVE #LogLogicalName TO #LogPath
GOTO EXITSTAT
ERRORFILES:
BEGIN
RAISERROR( 'The list of files contained in the backup set is empty', 16, 1 )
GOTO EXITSTAT
END
ERRORFILESCOUNT:
BEGIN
RAISERROR( 'The count of files contained in the backup set is more than two', 16, 1 )
GOTO EXITSTAT
END
EXITSTAT:

Backup database with different name time-related

My code ,for agent's job on SQL server 2008 , generate the backup file, but it keep OVERWRITE the first bak file everytime the agent's job triggered !!?
how can i make backup with different name time-related
e.g:
testDB201313328.bak
and after 1 minute create file with name :
testDB201313329.bak
instead overwriting the first one
USE msdb ;
GO
DECLARE #fileName VARCHAR(90);
DECLARE #db_name VARCHAR(20);
DECLARE #fileDate VARCHAR(20);
DECLARE #commandtxt VARCHAR(100);
SET #fileName = 'C:\Test_Backups\';
SET #db_name = 'testDB';
SET #fileDate = CONVERT(VARCHAR(8), GETDATE(),112) + convert (varchar(4),DATEPART(HOUR, GETDATE())) + convert ( varchar(4) ,DATEPART(MINUTE, GETDATE())) + convert ( varchar(4) ,DATEPART(SECOND, GETDATE()));
SET #fileName = #fileName + #db_name + RTRIM(#fileDate) + '.bak';
SET #commandtxt = 'BACKUP LOG testDB TO DISK =''' + #fileName + ''' WITH INIT'
-- add a job
EXEC dbo.sp_add_job
#job_name = N'LogBackup',
#description =N'Log Backup on weekdays every 15 minutes from 8am till 6pm' ;
-- add job steps to job
EXEC sp_add_jobstep
#job_name = N'LogBackup',
#step_name = N'Weekdays_Log_Backup',
#subsystem = N'TSQL',
#command = #commandtxt ,
#on_success_action = 1,
#retry_attempts = 5,
#retry_interval = 1 ;
GO
...
First, backups can contain more than one backup set, so are you sure you are overwriting it and not just appending another set within the same file? Otherwise you need to add the time of day to your filename. Hope this helps. Also if its just one or two db, then there is an excellent (free for limited use) app, google SQLBackupAndFTP HTH

full backups occasionally skipping certain databases

We have a job set up to run a script every night to do a full backup on all of our databases. Recently, we noticed that sometimes the last two databases are skipped, but not all of the time. We have a tracking table that we are inserting the state of each database in when we do the backups. On the nights that the last two databases are skipped, the state for those databases doesn't get recorded in the tracking table either. We can't figure out why those databases are being skipped. This is the backup script we are using:
DECLARE #dbname VARCHAR(100),
#dbid INT,
#rcmodel VARCHAR(50),
#state VARCHAR(60),
#date VARCHAR(50),
#time VARCHAR(50),
#sql VARCHAR(3000),
#dir VARCHAR(1000),
#path VARCHAR(100),
#type VARCHAR(10)
SET #path = 'E:\Backups\'
SET #type = 'Full'
SET #date = REPLACE(CONVERT(date,GETDATE(),101),'-','_')
SET #time = REPLACE(CONVERT(TIME(0), GETDATE()),':','_')
SET #path = #path + CONVERT(VARCHAR(30),##SERVERNAME) + '\' + #type + '\'
DECLARE BackupCur CURSOR FOR
SELECT NAME, database_id, recovery_model_desc, state_desc
FROM sys.databases
WHERE NAME <> 'tempdb'
OPEN BackupCur
FETCH NEXT FROM BackupCur INTO #dbname, #dbid, #rcmodel, #state
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO backuptrackingtable (db, statedesc, datecreated)
values (#dbname, #state, GETDATE())
IF #type = 'Full' AND #state = 'ONLINE'
BEGIN
SET #dir = 'EXECUTE master.dbo.xp_create_subdir N'''+#path+#dbname+''''
SET #sql = 'BACKUP DATABASE '+#dbname+' TO DISK = N'''+#path+#dbname+'\'+#dbname+'_'+#date+'.bak'' WITH NOFORMAT, INIT, SKIP, REWIND, NOUNLOAD, COMPRESSION'
PRINT 'Backing up ' + #dbname
EXEC (#dir)
EXEC (#sql)
END
IF #type = 'Log' AND #dbid > 4 AND #rcmodel = 'FULL' AND #state = 'ONLINE'
BEGIN
SET #dir = 'EXECUTE master.dbo.xp_create_subdir N'''+#path+#dbname+''''
SET #sql = 'BACKUP LOG '+#dbname+' TO DISK = N'''+#path+#dbname+'\'+#dbname+'_'+#date+'__'+#time+'.bak'' WITH NOFORMAT, INIT, SKIP, REWIND, NOUNLOAD, COMPRESSION'
PRINT 'Backing up ' + #dbname
EXEC (#dir)
EXEC (#sql)
END
FETCH NEXT FROM BackupCur INTO #dbname, #dbid, #rcmodel, #state
END
CLOSE BackupCur
DEALLOCATE BackupCur
Can think of three possible explanations.
They aren't being returned from the query against sys.databases because they don't exist or the user running the query doesn't have permissions on them.
An unhandled error means that the script aborts before processing them.
##FETCH_STATUS returns -2 at some point because a database has been dropped since the keyset cursor opened.
You would need to put more logging in to investigate further. But you might want to consider using a maintenance plan (dependant on edition) or Ola Hallengren's DB maintenance scripts rather than re-inventing the wheel anyway.

how to pass all database (fast) since sql server 2008 express to sql server 2008 R2 (NO express)

well i had sql 2008 express, and now i have installed, sql server, now i want to delete sql express, but in that instance i have all my database i have worked (plus of 20), so they are very important for me, how can i pass it to sql server 2008 r2, i know i can do database of all but i dont want to work a lot of, there is a way short, for to pass al database? coping a folder? something? thanks!
I Attached all database, and i added, all (but one for one) i added all in the same windows and in 5 minutos i had all database in sql (no express)
Create an SSIS package with 4 steps.
First, a Execute SQL task that backups all DBs to a specific location:
exec sp_msforeachdb '
IF DB_ID(''?'') > 4
Begin
BACKUP DATABASE [?] TO DISK = N''\\Backups\?.BAK'' WITH NOFORMAT, INIT,
NAME = N''?-Full Database Backup'', SKIP, NOREWIND, NOUNLOAD
declare #backupSetId as int
select #backupSetId = position from msdb..backupset where database_name=N''?''
and backup_set_id=(select max(backup_set_id) from msdb..backupset
where database_name=N''?'' )
if #backupSetId is null begin
raiserror(N''Verify failed. Backup information for database ''''?'''' not found.'', 16, 1)
end
RESTORE VERIFYONLY FROM DISK = N''\\Backups\?.BAK'' WITH
FILE = #backupSetId, NOUNLOAD, NOREWIND
End
'
Second, Create a SP to restore DBs using a variable for location and DB name:
CreatePROCEDURE [dbo].[uSPMas_RestoreDB] #DBname NVARCHAR(200),
#BackupLocation NVARCHAR(2000)
AS
BEGIN
SET nocount ON;
create table #fileListTable
(
LogicalName nvarchar(128),
PhysicalName nvarchar(260),
[Type] char(1),
FileGroupName nvarchar(128),
Size numeric(20,0),
MaxSize numeric(20,0),
)
insert into #fileListTable EXEC('RESTORE FILELISTONLY FROM DISK = '''+#BackupLocation+#dbname+'.bak''')
Declare #Dname varchar(500)
Set #Dname = (select logicalname from #fileListTable where type = 'D')
Declare #LName varchar(500)
Set #LName = (select logicalname from #fileListTable where type = 'L')
declare #sql nvarchar(4000)
SET #SQL = 'RESTORE DATABASE ['+ #dbname +'] FROM
DISK = N'''+#BackupLocation + #dbname +'.BAK'' WITH FILE = 1,
MOVE N'''+ #Dname +''' TO N''E:\YourLocation\'+ #dbname +'.mdf'',
MOVE N'''+ #LName +''' TO N''D:\Your2ndLocation\'+ #dbname +'_log.ldf'',
NOUNLOAD, REPLACE, STATS = 10'
exec sp_executesql #SQL
drop table #fileListTable
END
Third, Create a ForEach Loop Container and put a Execute Sql Statement with variable:
EXEC uSPMas_RestoreDB ? , ?
Use the for ForEach Loop Container to pass the variables
Fourth, Create a 'Transfer Logins' task to move over all DB logins