SQL Server multiple shrink operations - sql-server

I'm trying to shrink all databases (files and logs) in SQL Server 2008 R2.
I have finished the script, but the problem is that when I loop over all databases and execute the query to do shrink file the first 3 or 4 shrinks work but them I have this error :
Msg 0, Level 11, State 0, Line 0
A severe error occurred on the current command. The results, if any,
should be discarded.
The script :
declare #db_name as varchar(30)
declare #db_recorvery_model as varchar(30)
declare #db_files_name as varchar(250)
declare #db_files_physical_name as varchar(250)
declare get_files cursor for
select b.name, a.name
from sys.master_files as a,
sys.databases as b
where a.database_id = b.database_id
order by b.name
open get_files
fetch next from get_files into #db_files_name, #db_files_physical_name
set #db_files_name = (select #db_files_name)
set #db_files_physical_name = (select #db_files_physical_name)
DECLARE #Command as nvarchar(max)
set #Command=''
while(##FETCH_STATUS=0)
BEGIN
if (#db_files_name='master' or #db_files_name='msdb' or #db_files_name='tempdb' or #db_files_name='model')
BEGIN
print 'Bases de dados do sql server: '+#db_files_name
END
ELSE
BEGIN
set #Command = 'USE ' + '[' + #db_files_name + '] DBCC SHRINKFILE ("'+#db_files_physical_name+'", 1 )'
EXEC sp_executesql #Command
print #Command
END
fetch next from get_files into #db_files_name, #db_files_physical_name
set #db_files_name = (select #db_files_name)
set #db_files_physical_name = (select #db_files_physical_name)
END
close get_files
deallocate get_files
Does anyone have any ideas ?
PS: I know that I shouldn't shrink but is a very special environment and not productive.

Can you determine which database flags the error? Can you try running your script on the single database that has the problem and see if it is consistently the same database that triggers the error? Perhaps it's a special database that you've missed that cannot be shrunk that way.
I have a similar environment containing temp databases that are not for long term storage, and I use the following script which has worked perfectly for hundreds of databases:
CREATE procedure [dbo].[ShrinkLog]
#DB varchar(200)
as
declare #LogFile varchar(200)
declare #Sql varchar(500)
SELECT #LogFile = name
FROM sys.master_files
where type_desc = 'LOG'
and db_name(database_id) = #DB
set #Sql = '
Use [' + #DB + ']
DBCC SHRINKFILE([' + #LogFile + '], 1)
'
print(#sql)
exec(#sql)
Keep in mind also that you don't want to run this command unless your server has plenty of hard drive/memory space as well.
Best regards,

If you want to do a log shrink, this will be the best code. I am using it for a while and it never crash to me.
declare #SQL nvarchar(max)
select #SQL = coalesce(#SQL + char(13) + char(10),'') + N'
Use ' + QUOTENAME(d.[name]) + ';' + CHAR(13) + '
ALTER DATABASE ' + QUOTENAME(d.[name]) + ' SET RECOVERY SIMPLE;
DBCC SHRINKFILE (' + quotename(mf.[name],'''') + ', 1);
ALTER DATABASE ' + QUOTENAME(d.[name]) + ' SET RECOVERY FULL;'
FROM sys.databases d
INNER JOIN sys.master_files mf ON [d].[database_id] = [mf].[database_id]
WHERE
d.[database_id] > 4 --no sys dbs
AND d.recovery_model = 1
AND d.is_read_only = 0
AND mf.[type] = 1 --log files
ORDER BY d.name
--print #SQL
execute (#SQL)

Related

Is there a function to compress 'bak' file in sql script?

In SQL Server, I want to clear personal info and backup it
Backup original DB
Restore as another DB name
Clear personal info in another DB
Backup another DB
Delete rest files
Zip Backup DB
I finished 1~5. but couldn't find a way to do 6.
I Want to compress bak file to zip here.
For instance, below code can be used in Powershell script. Is there a way to use this .Net function in SQL script?
[System.IO.Compression.ZipFile]::CreateFromDirectory($CurrentPath, $DeployHistoryFilePath)
Below is my full script.
DECLARE #DBName NVARCHAR(MAX) = N'TestDB'
DECLARE #BackupPath NVARCHAR(MAX) = N'D:\Database\Backup'
EXEC ('master.dbo.xp_create_subdir N'''+ #BackupPath +'''')
DECLARE #BackupName NVARCHAR(MAX) = N'OnCube_' + REPLACE(REPLACE(REPLACE(CONVERT(NVARCHAR(MAX), GETDATE(), 120), N'-', N''), N':', N''), N' ', N'_')
DECLARE #DiskFile NVARCHAR(MAX) = #BackupPath + N'\' + #BackupName + N'.bak'
BACKUP DATABASE #DBName TO DISK = #DiskFile
DECLARE #SQL NVARCHAR(MAX) = 'SELECT TOP (1) #OriginalMdf = name FROM ' + #DBName + '.sys.database_files WHERE file_id = 1'
DECLARE #OriginalMdf NVARCHAR(MAX)
EXEC sp_executesql #SQL, N'#OriginalMdf NVARCHAR(MAX) OUT', #OriginalMdf out
SET #SQL = 'SELECT TOP (1) #OriginalLdf = name FROM ' + #DBName + '.sys.database_files WHERE file_id = 2'
DECLARE #OriginalLdf NVARCHAR(MAX)
EXEC sp_executesql #SQL, N'#OriginalLdf NVARCHAR(MAX) OUT', #OriginalLdf out
DECLARE #PartialMdf NVARCHAR(MAX) = #BackupPath + N'\' + #BackupName + N'.mdf'
DECLARE #PartialLdf NVARCHAR(MAX) = #BackupPath + N'\' + #BackupName + N'_0.ldf'
RESTORE FILELISTONLY FROM DISK = #DiskFile
RESTORE DATABASE #BackupName
FROM DISK = #DiskFile
WITH MOVE #OriginalMdf TO #PartialMdf,
MOVE #OriginalLdf TO #PartialLdf
EXEC (N'
USE [' + #BackupName + ']
UPDATE Person
SET
PatientNo = NULL
, PatientName = N''Cleared'' + CONVERT(NVARCHAR(MAX), RawID)
, RoomNo = NULL
, BedNo = NULL
, Birthday = NULL
, Sex = NULL
, Address = NULL
, AdmitDate = NULL
, AdmitNo = NULL
, Description = NULL
, DischargedDate = NULL
')
DECLARE #ClearedDiskFile NVARCHAR(MAX) = #BackupPath + N'\' + #BackupName + N'_PatientInfoCleared.bak'
BACKUP DATABASE #BackupName TO DISK = #ClearedDiskFile
EXEC('DROP DATABASE [' + #BackupName + ']')
EXEC ('xp_cmdshell ''del "' + #DiskFile + '"''')
-- I Want to compress bak file to zip here
-- For instance, below code can be used in Powershell script. Is there a way to use this .Net function in SQL script?
-- [System.IO.Compression.ZipFile]::CreateFromDirectory($CurrentPath, $DeployHistoryFilePath)
PRINT N'Success to make ' + #ClearedDiskFile + '. Patient informations are all cleared'
Is there a way to use this .Net function in SQL script?
Yes, you can use SQL CLR with C#
see samples Using 7-zip and SharpZipLib here:
also , you can create zip file from SQL without Powershell script:
Create zip file from SQL Server

Database Files show in master_files but not in database_files

I have a few SQL databases, that I inherited.
I have a fresh install of SQL 2012
I have attached the databases to the server without an issue.
Yet, where I run Select * From sys.database_files; they are not in there, but when I run Select * From sys.master_files; they are.
This is messing up some code I am attempting to write by throwing the following errors:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near 'I:'.
Msg 8985, Level 16, State 1, Line 1
Could not locate file 'I:\SQL Databases\Cloud.CMS_log.ldf' for database 'master' in sys.database_files. The file either does not exist, or was dropped.
How can I fix it so they are there in sys.database_files so my code runs?
Declare #TempDBList Table
(
Id int,
DBName VarChar(250),
FileType int,
DBFile VarChar(1000)
);
Declare #BackupLocation VarChar(Max) = 'I:\SQL Databases\Backup';
Declare #FileLocation VarChar(Max);
Declare #DBName VarChar(250);
Declare #FileType Int;
Declare #DBBackup VarChar(Max);
Declare #LogBackup VarChar(Max);
Declare #Sql VarChar(Max);
Insert Into #TempDBList
(id, DBName, FileType, DBFile)
Select a.database_id DBid, a.Name , b.type FileType, b.physical_name As FileLocation
From sys.databases a
Inner Join sys.master_files b On b.database_id = a.database_id
Where b.state = 0 AND a.database_id > 4;
Select #DBName = DBName, #FileType = FileType, #FileLocation = DBFile From #TempDBList Order By DBName;
While ##ROWCOUNT <> 0
Begin
--- Set all databases to Simple Recovery
Set #Sql = 'Alter DATABASE ' + QUOTENAME(#DBName) + ' Set RECOVERY SIMPLE';
Exec(#Sql);
Set #DBBackup = #BackupLocation + #DBName + '\' + #DBName + '_' + Convert(Varchar(500), GetDate(), 112)+ '.bak';
Set #LogBackup = #BackupLocation + #DBName + '\' + #DBName + '_' + Convert(Varchar(500), GetDate(), 112)+ '.log.bak';
If #FileType = 1
Begin
Set #Sql = 'Backup Database ' + QUOTENAME(#DBName) + ' To Disk = ' + #DBBackup;
Exec(#Sql);
Exec('DBCC SHRINKFILE(''' + #FileLocation + ''', TruncateOnly)');
End
Else If #FileType = 0
Begin
Set #Sql = 'Backup Log ' + QUOTENAME(#DBName) + ' To Disk = ' + #LogBackup;
Exec(#Sql);
Exec('DBCC SHRINKFILE(''' + #FileLocation + ''', TruncateOnly)');
End
End
Screenshot for both sys.database_files & sys.master_files
http://prntscr.com/57p49b
sys.master_files is a system wide view and will show you all the files on the instance you are connected to (where you have sufficient permission), sys.database_files is a per database view, and will only show files in the specified database. You either need to connect to the correct database to see the files, e.g:
USE Master;
SELECT *
FROM sys.database_files;
Or use the 3 part object name:
SELECT *
FROM master.sys.database_files;
EDIT
I can only apologise for not explaining myself very well, but the above does point out why you cannot see files in sys.database_files that you can see in sys.master_files.
Look at the following screenshot:
You can see that after connecting to a different database (USE TestDB) different files are showing in sys.database_files, but the record count (and the actual records) in sys.master_files is the same regardless of database.
Now, looking at your actual error:
Could not locate file 'I:\SQL Databases\Cloud.CMS_log.ldf' for database 'master' in sys.database_files.
This explains the problem, you are connected to the database master, so sys.database_files would only show the files in the master database (master, and masterlog). You are looking for CMS_log which is presumably located in the database CMS, so to view this file in sys.database_files you would need to run:
USE CMS;
SELECT * FROM sys.database_files;
Or
SELECT * FROM CMS.sys.database_files;
Your actual error comes because you are trying to shrink the file CMS_Log while connected to the master database, which you cannot do, you would need to run:
USE CMS;
DBCC SHRINKFILE('CMS_Log', TRUNCATEONLY);
Hopefully this explains why you are getting the error.
FULL SCRIPT
DECLARE #BackupLocation VARCHAR(MAX) = '',
#DBName SYSNAME,
#DataFile SYSNAME,
#LogFile SYSNAME,
#SQL NVARCHAR(MAX);
DECLARE FileCursor CURSOR STATIC FORWARD_ONLY READ_ONLY
FOR
SELECT DBName = d.Name,
DataFile = MAX(CASE WHEN f.Type = 0 THEN f.Name END),
LogFile = MAX(CASE WHEN f.Type = 1 THEN f.Name END)
FROM sys.databases d
INNER JOIN sys.master_files f
ON d.database_id = f.database_id
WHERE d.Name NOT IN ('master', 'tempdb', 'model', 'msdb')
AND d.Name NOT LIKE 'ReportServer$%'
GROUP BY d.Name;
OPEN FileCursor;
FETCH NEXT FROM FileCursor INTO #DBName, #DataFile, #LogFile;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = '
USE ' + QUOTENAME(#DBName) + ';
ALTER DATABASE ' + QUOTENAME(#DBName) + ' SET RECOVERY SIMPLE;
BACKUP DATABASE ' + QUOTENAME(#DBName) + ' TO DISK = ''' + #BackupLocation +
+ #DBName + '_' + CONVERT(VARCHAR(8), GETDATE(), 112) + '.bak'';
ALTER DATABASE ' + QUOTENAME(#DBName) + ' SET RECOVERY FULL;
BACKUP LOG ' + QUOTENAME(#DBName) + ' TO DISK = ''' + #BackupLocation +
+ #DBName + '_' + CONVERT(VARCHAR(8), GETDATE(), 112) + '.log.bak'';
DBCC SHRINKFILE(' + #DataFile + ', TRUNCATEONLY);
DBCC SHRINKFILE(' + #LogFile + ', TRUNCATEONLY);';
EXECUTE sp_executesql #SQL;
FETCH NEXT FROM FileCursor INTO #DBName, #DataFile, #LogFile;
END
CLOSE FileCursor;
DEALLOCATE FileCursor;
This generates and executes a command like the following for each database:
USE [TestDB];
ALTER DATABASE [TestDB] SET RECOVERY SIMPLE;
BACKUP DATABASE [TestDB] TO DISK = 'I:\SQL Databases\Backup\TestDB_20141119.bak';
ALTER DATABASE [TestDB] SET RECOVERY FULL;
BACKUP LOG [TestDB] TO DISK = 'I:\SQL Databases\Backup\TestDB_20141119.log.bak';
DBCC SHRINKFILE(TestDB, TRUNCATEONLY);
DBCC SHRINKFILE(TestDB_log, TRUNCATEONLY);

Within While Loop how to execute "Use [database name] Go"

I need to shrink the log file for every database weekly.
I am writing a while loop query to loop each database. but i don't think it is allowed to do the following:
declare #database_id int
declare #database varchar(255)
declare #log varchar(255)
declare #cmd varchar(500)
while (select count(*) from #LogFiles where processed = 0) > 0
begin
set #database_id = (select min(database_id) from #LogFiles where processed = 0)
set #database = (select name from #LogFiles where database_id = #database_id and [type] = 0)
set #log = (select name from #LogFiles where database_id = #database_id and [type] = 1)
select #database, #log
set #cmd = 'Use ' + #Database
exec(#cmd)
set #cmd = 'DBCC SHRINKFILE (' + #log + ');'
exec(#cmd)
update #LogFiles
set processed = 1
where database_id = #database_id
end
Or is there another way to do so?
Thanks
As was mentioned in multiple comments, this really, really, REALLY isn't a good idea. Shrinking these files just so they can grow again next week is wasted effort and, since log file autogrow events can't take advantage of instant file initialization (since, unlike data file allocations, log file allocations really have to be zeroed out before use), this can really impact end user performance in ways that you can't predict or control.
That said, ditch the #temp table and cursor while loop. Technically this still uses a loop to concatenate but it's so much easier to set up and look at.
DECLARE #sql NVARCHAR(MAX); SET #sql = N'';
SELECT #sql = #sql + N'
USE ' + QUOTENAME(db) + ';
PRINT DB_NAME();
CHECKPOINT; -- since we now know it is simple recovery
DBCC SHRINKFILE(' + QUOTENAME(f) + ') WITH NO_INFOMSGS;'
FROM
(
SELECT DB_NAME(database_id), name
FROM sys.master_files
WHERE database_id > 4 AND [type] = 1
-- AND LOWER(name) NOT IN (N'reportserver', N'reportservertempdb')
) AS x(db, f);
PRINT #sql;
--EXEC sp_executesql #sql;
Check out the PRINT output. When you're satisfied it's going to do what you think, uncomment the EXEC and run it again.

How to create a UDF or View in another database that references the correct sys.objects table in the caller?

Using SQL Server 2008, I'd like to create a UDF that gives me the create date of an object. This is the code:
create function dbo.GetObjCreateDate(#objName sysname) returns datetime as
begin
declare #result datetime
select #result = create_date from sys.objects where name = #objname
return #result
end
go
I'd like to put this UDF in the master database or some other shared database so that it is accessible from anywhere, except that if I do that then the sys.objects reference pulls from the master database instead of the database that I'm initiating my query from. I know you can do this as the information_schema views sit in master and just wrap calls to local instances of sys.objects, so I'm hoping there's a simple way to do that with my UDF as well.
Try this:
CREATE FUNCTION dbo.GetObjCreateDate(#objName sysname, #dbName sysname)
RETURNS datetime AS
BEGIN
DECLARE #createDate datetime;
DECLARE #params nvarchar(50);
DECLARE #sql nvarchar(500);
SET #params = '#createDate datetime OUTPUT';
SELECT #sql = 'SELECT #createDate = create_date FROM ' + #dbName + '.sys.objects WHERE name = ''' + #objname + '''';
EXEC sp_executesql #sql, #params, #createDate = #createDate OUTPUT;
RETURN #createDate
END
;
Why not do this instead?
Create a stored procedure that creates a view in the master database containing all of the information in sys.objects from each database on the server.
Create a DDL Trigger that gets fired whenever a CREATE, ALTER or DROP statement is executed for a database. The trigger would then execute the stored procedure in step #1. This allows the view to be automatically updated.
(Optional) Create a user defined function that queries the view for the creation date of a given object.
Stored Procedure DDL:
USE [master];
GO
CREATE PROCEDURE dbo.BuildAllServerObjectsView
AS
SET NOCOUNT ON;
IF OBJECT_ID('master.dbo.AllServerObjects') IS NOT NULL
EXEC master..sp_SQLExec 'DROP VIEW dbo.AllServerObjects;';
IF OBJECT_ID('tempdb..Databases') IS NOT NULL
DROP TABLE #Databases;
DECLARE #CreateView varchar(8000);
SET #CreateView = 'CREATE VIEW dbo.AllServerObjects AS' + CHAR(13)+CHAR(10) + CHAR(13)+CHAR(10);
SELECT name COLLATE SQL_Latin1_General_CP1_CI_AS AS 'name'
INTO #Databases
FROM sys.databases
ORDER BY name;
DECLARE #DatabaseName nvarchar(100);
WHILE (SELECT COUNT(*) FROM #Databases) > 0
BEGIN
SET #DatabaseName = (SELECT TOP 1 name FROM #Databases ORDER BY name);
SET #CreateView +='SELECT N'+QUOTENAME(#DatabaseName, '''')+' AS ''database_name''' + CHAR(13)+CHAR(10)
+ ' ,name COLLATE SQL_Latin1_General_CP1_CI_AS AS ''object_name''' + CHAR(13)+CHAR(10)
+ ' ,object_id' + CHAR(13)+CHAR(10)
+ ' ,principal_id' + CHAR(13)+CHAR(10)
+ ' ,schema_id' + CHAR(13)+CHAR(10)
+ ' ,parent_object_id' + CHAR(13)+CHAR(10)
+ ' ,type' + CHAR(13)+CHAR(10)
+ ' ,type_desc' + CHAR(13)+CHAR(10)
+ ' ,create_date' + CHAR(13)+CHAR(10)
+ ' ,modify_date' + CHAR(13)+CHAR(10)
+ ' ,is_ms_shipped' + CHAR(13)+CHAR(10)
+ ' ,is_published' + CHAR(13)+CHAR(10)
+ ' ,is_schema_published' + CHAR(13)+CHAR(10)
+ ' FROM ' + QUOTENAME(#DatabaseName) + '.sys.objects';
IF (SELECT COUNT(*) FROM #Databases) > 1
SET #CreateView += CHAR(13)+CHAR(10) + CHAR(13)+CHAR(10) + ' UNION' + CHAR(13)+CHAR(10);
ELSE
SET #CreateView += ';';
DELETE #Databases
WHERE name = #DatabaseName;
END;
--PRINT #CreateView --<== Uncomment this to see the DDL for the view.
EXEC master..sp_SQLExec #CreateView;
IF OBJECT_ID('tempdb..Databases') IS NOT NULL
DROP TABLE #Databases;
GO
Function DDL:
USE [master];
GO
CREATE FUNCTION dbo.GetObjCreateDate(#DatabaseName sysname, #objName sysname) RETURNS DATETIME AS
BEGIN
DECLARE #result datetime;
SELECT #result = create_date
FROM master.dbo.AllServerObjects
WHERE [database_name] = #DatabaseName
AND [object_name] = #objname;
RETURN #result;
END
GO
Sample Usage:
SELECT master.dbo.GetObjCreateDate('MyDatabase', 'SomeObject') AS 'Created';
SELECT master.dbo.GetObjCreateDate(DB_NAME(), 'spt_monitor') AS 'Created';
Does it have to be a function? If you just want it accessible everywhere, a trick is to put your code in a varchar and sp_executesql it:
create procedure dbo.GetObjCreateDate(#objName sysname)
as
declare #sql nvarchar(max)
select #sql = 'select create_date from sys.objects where name = ''' + #objname + ''''
EXEC sp_executesql #sql
go
There seems to be an undocumented stored procedure that allows you to create your own system objects: sp_ms_marksystemobject
You can read more on http://www.mssqltips.com/tip.asp?tip=1612
Have a look at How to Write Your Own System Functions. I believe that it may help you

What is the best way to copy a database?

When I want to make a copy of a database, I always create a new empty database, and then restore a backup of the existing database into it. However, I'm wondering if this is really the least error-prone, least complicated, and most efficient way to do this?
It is possible to skip the step of creating the empty database. You can create the new database as part of the restore process.
This is actually the easiest and best way I know of to clone a database. You can eliminate errors by scripting the backup and restore process rather than running it through the SQL Server Management Studio
There are two other options you could explore:
Detach the database, copy the .mdf file and re-attach.
Use SQL Server Integration Services (SSIS) to copy all the objects over
I suggest sticking with backup and restore and automating if necessary.
Here's a dynamic sql script I've used in the past. It can be further modified but it will give you the basics. I prefer scripting it to avoid the mistakes you can make using the Management Studio:
Declare #OldDB varchar(100)
Declare #NewDB varchar(100)
Declare #vchBackupPath varchar(255)
Declare #query varchar(8000)
/*Test code to implement
Select #OldDB = 'Pubs'
Select #NewDB = 'Pubs2'
Select #vchBackupPath = '\\dbserver\C$\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Backup\pubs.bak'
*/
SET NOCOUNT ON;
Select #query = 'Create Database ' + #NewDB
exec(#query)
Select #query = '
Declare #vBAKPath varchar(256)
declare #oldMDFName varchar(100)
declare #oldLDFName varchar(100)
declare #newMDFPath varchar(100)
declare #newLDFPath varchar(100)
declare #restQuery varchar(800)
select #vBAKPath = ''' + #vchBackupPath + '''
select #oldLDFName = name from ' + #OldDB +'.dbo.sysfiles where filename like ''%.ldf%''
select #oldMDFName = name from ' + #OldDB +'.dbo.sysfiles where filename like ''%.mdf%''
select #newMDFPath = physical_name from ' + #NewDB +'.sys.database_files where type_desc = ''ROWS''
select #newLDFPath = physical_name from ' + #NewDB +'.sys.database_files where type_desc = ''LOG''
select #restQuery = ''RESTORE DATABASE ' + #NewDB +
' FROM DISK = N'' + '''''''' + #vBAKpath + '''''''' +
'' WITH MOVE N'' + '''''''' + #oldMDFName + '''''''' +
'' TO N'' + '''''''' + #newMDFPath + '''''''' +
'', MOVE N'' + '''''''' + #oldLDFName + '''''''' +
'' TO N'' + '''''''' + #newLDFPath + '''''''' +
'', NOUNLOAD, REPLACE, STATS = 10''
exec(#restQuery)
--print #restQuery'
exec(#query)
Backup and Restore is the most straight-forward way I know. You have to be careful between servers as security credentials don't come with the restored database.
The Publish to Provider functionality has worked great for me. See Scott Gu's Blog Entry.
If you need something really robust look at redgate software's tools here...if you are doing much SQL at all, these are worth the $$.
::================ BackUpAllMyDatabases.cmd ============= START
::BackUpAllMyDatabases.cmd
:: COMMAND LINE BATCH SCRIPT FOR TAKING BACKUP OF ALL DATABASES
::RUN THE SQL SCRIPT VIA THE COMMAND LINE WITH LOGGING
sqlcmd -S localhost -e -i "BackUpAllMyDatabases.sql" -o Result_Of_BackUpAllMyDatabases.log
::VIEW THE RESULTS
Result_Of_BackUpAllMyDatabases.log
::pause
::================ BackUpAllMyDatabases.cmd ============= END
--=================================================BackUpAllMyDatabases.sql start
DECLARE #DBName varchar(255)
DECLARE #DATABASES_Fetch int
DECLARE DATABASES_CURSOR CURSOR FOR
select
DATABASE_NAME = db_name(s_mf.database_id)
from
sys.master_files s_mf
where
-- ONLINE
s_mf.state = 0
-- Only look at databases to which we have access
and has_dbaccess(db_name(s_mf.database_id)) = 1
-- Not master, tempdb or model
--and db_name(s_mf.database_id) not in ('Master','tempdb','model')
group by s_mf.database_id
order by 1
OPEN DATABASES_CURSOR
FETCH NEXT FROM DATABASES_CURSOR INTO #DBName
WHILE ##FETCH_STATUS = 0
BEGIN
declare #DBFileName varchar(256)
set #DBFileName = #DbName + '_' + replace(convert(varchar, getdate(), 112), '-', '.') + '.bak'
--REMEMBER TO PUT HERE THE TRAILING \ FOR THE DIRECTORY !!!
exec ('BACKUP DATABASE [' + #DBName + '] TO DISK = N''D:\DATA\BACKUPS\' +
#DBFileName + ''' WITH NOFORMAT, INIT, NAME = N''' +
#DBName + '-Full Database Backup'', SKIP, NOREWIND, NOUNLOAD, STATS = 100')
FETCH NEXT FROM DATABASES_CURSOR INTO #DBName
END
CLOSE DATABASES_CURSOR
DEALLOCATE DATABASES_CURSOR
--BackUpAllMyDatabases==========================end
--======================RestoreDbFromFile.sql start
-- Restore database from file
-----------------------------------------------------------------
use master
go
declare #backupFileName varchar(100), #restoreDirectory varchar(100),
#databaseDataFilename varchar(100), #databaseLogFilename varchar(100),
#databaseDataFile varchar(100), #databaseLogFile varchar(100),
#databaseName varchar(100), #execSql nvarchar(1000)
-- Set the name of the database to restore
set #databaseName = 'ReplaceDataBaseNameHere'
-- Set the path to the directory containing the database backup
set #restoreDirectory = 'ReplaceRestoreDirectoryHere' -- such as 'c:\temp\'
-- Create the backup file name based on the restore directory, the database name and today's date
#backupFileName = #restoreDirectory + #databaseName + '-' + replace(convert(varchar, getdate(), 110), '-', '.') + '.bak'
-- set #backupFileName = 'D:\DATA\BACKUPS\server.poc_test_fbu_20081016.bak'
-- Get the data file and its path
select #databaseDataFile = rtrim([Name]),
#databaseDataFilename = rtrim([Filename])
from master.dbo.sysaltfiles as files
inner join
master.dbo.sysfilegroups as groups
on
files.groupID = groups.groupID
where DBID = (
select dbid
from master.dbo.sysdatabases
where [Name] = #databaseName
)
-- Get the log file and its path
select #databaseLogFile = rtrim([Name]),
#databaseLogFilename = rtrim([Filename])
from master.dbo.sysaltfiles as files
where DBID = (
select dbid
from master.dbo.sysdatabases
where [Name] = #databaseName
)
and
groupID = 0
print 'Killing active connections to the "' + #databaseName + '" database'
-- Create the sql to kill the active database connections
set #execSql = ''
select #execSql = #execSql + 'kill ' + convert(char(10), spid) + ' '
from master.dbo.sysprocesses
where db_name(dbid) = #databaseName
and
DBID <> 0
and
spid <> ##spid
exec (#execSql)
print 'Restoring "' + #databaseName + '" database from "' + #backupFileName + '" with '
print ' data file "' + #databaseDataFile + '" located at "' + #databaseDataFilename + '"'
print ' log file "' + #databaseLogFile + '" located at "' + #databaseLogFilename + '"'
set #execSql = '
restore database [' + #databaseName + ']
from disk = ''' + #backupFileName + '''
with
file = 1,
move ''' + #databaseDataFile + ''' to ' + '''' + #databaseDataFilename + ''',
move ''' + #databaseLogFile + ''' to ' + '''' + #databaseLogFilename + ''',
norewind,
nounload,
replace'
exec sp_executesql #execSql
exec('use ' + #databaseName)
go
-- If needed, restore the database user associated with the database
/*
exec sp_revokedbaccess 'myDBUser'
go
exec sp_grantdbaccess 'myDBUser', 'myDBUser'
go
exec sp_addrolemember 'db_owner', 'myDBUser'
go
use master
go
*/
--======================RestoreDbFromFile.sql

Resources