I'm running a T-SQL script that drops a database and then restores it. The script runs against a SQL Server 2008 database. Sometimes there is a problem with the backup file and the database gets stuck in the restoring state.
IF EXISTS (SELECT 1 FROM master.dbo.sysdatabases WHERE name = 'dbname')
BEGIN
ALTER DATABASE [dbname]
SET SINGLE_USER WITH
ROLLBACK IMMEDIATE
END
IF EXISTS (SELECT 1 FROM master.dbo.sysdatabases WHERE name = 'dbname')
BEGIN
DROP DATABASE [dbname]
END
RESTORE DATABASE [dbname]
FROM DISK = N'C:\dbname.bak'
WITH FILE = 1,
NOUNLOAD,
STATS = 10
The next time the script runs the script generates the error message
ALTER DATABASE is not permitted while a database is in the Restoring state.
What is the best way to check if the database is in the restoring state before trying to run the ALTER DATABASE command?
EDIT: The RESTORE DATABASE command that I'm running doesn't use the NO RECOVERY option.
It sounds as though you are performing a database restore with the NORECOVERY option. The reason you would want to do this is if you were planning to apply subsequent transaction log backups after the initial restore.
If you only wish to restore a single database backup then remove the NORECOVERY clause. If you are restoring transaction log backups, the final restore must be done without the NORECOVERY clause or if the last was applied with NORECOVERY you can RESTORE DATABASE DbName WITH RECOVERY to finalize.
To answer your question:
Method 1
SELECT DATABASEPROPERTYEX ('DatabaseName', 'Status')
See SQL Server Books Online: DATABASEPROPERTYEX (Transact-SQL)
Method 2
Review the sys.databases system view in order to determine the current state of a database. For example:
SELECT
state,
state_desc
FROM sys.databases
WHERE [name] = 'DatabaseName'
A state of 1 = RESTORING
See Sys.Databases for documentation regarding this system view.
SELECT DATABASEPROPERTYEX ('MyDb', 'Status')
Others had a similar problem doing a RESTORE with pyodbc. My variation of the problem (with similar symptoms to yours) turned out to be an incorrect bak file. This can be discovered with the following T-SQL, looking for incorrect .mdf or .ldf file names or database names:
RESTORE FILELISTONLY FROM DISK = N'C:\dbname.bak'
Method 2:
SELECT
state,
state_desc
FROM sys.databases
WHERE [name] = 'Databasename'
It is give me exact result.
Related
I have created a small scrip to restore databases from backups. Once the script is run it displays
RESTORE DATABASE successfully processed 28818 pages in 1.568 seconds
(143.584 MB/sec).
I have more code to alter the database, alter a few views and sp too but I am getting the following error; User does not have permission to alter database 'GreyGoo', the database does not exist, or the database is not in a state that allows access checks.
I have noticed too that I cannot see the database in the object explorer
this is what I use to restore the DB from a backup
if DB exists set to a single user
if DB exist drop database
Ran the below script
RESTORE DATABASE GreyGoo FROM DISK = 'C:\Bkp\GreyGoo_backup_2020_03_02_180002_5403592.bak'
WITH
MOVE 'GreyGoo' TO 'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\GreyGoo.mdf',
MOVE 'GreyGoo_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\GreyGoo.ldf',
REPLACE;
set DB to multi-users and other properties
So what is the problem and how can I solve it, I am currently testing my code on SQL Server 2008
Thanks
During your restore process, you will need to ensure your
login / permissions are correct.
if another previous database with same name is not there, if so delete it. Perhaps from a previous attempt
You can also turn off recovery option like below, recovery is default
RESTORE FILELISTONLY
Sample -- MSDN
USE master;
GO
-- First determine the number and names of the files in the backup.
-- AdventureWorks2012_Backup is the name of the backup device.
RESTORE FILELISTONLY
FROM AdventureWorks2012_Backup;
-- Restore the files for MyAdvWorks.
RESTORE DATABASE MyAdvWorks
FROM AdventureWorks2012_Backup
WITH RECOVERY,
MOVE 'AdventureWorks2012_Data' TO 'D:\MyData\MyAdvWorks_Data.mdf',
MOVE 'AdventureWorks2012_Log' TO 'F:\MyLog\MyAdvWorks_Log.ldf';
GO
EXEC msdb.dbo.sp_delete_database_backuphistory #database_name = N'MYDB'
GO
USE [master]
GO
/* Database [MYDB] */
DROP DATABASE [MYDB]
GO
USE [master]
RESTORE DATABASE [MYDB] FROM DISK = N'E:\FTP\local_MYDB_01.bak' WITH FILE = 1, MOVE N'blank' TO N'E:\DBs\2019\MYDB.mdf', MOVE N'blank_log' TO N'E:\DBs\2019\MYDB.ldf', NOUNLOAD, STATS = 5
GO
I have a SQL server data backup size is above 20 GB. My database is in E drive have enough space but my SQL software installed in C drive which has low memory. In this scenario how can i restore my backup to E drive.
You can restore database via SQL Server Management Studio.
While restoring , you can specify MDF and LDF file location to your E: drive.
To specify the new location of the database files, select the Files
page, and then click Relocate all files to folder. Provide a new
location for the Data file folder and Log file folder
THIS MIGHT HELP
steps :
ALTER DATABASE database_name SET OFFLINE;
Move the file or files to the new location.
For each file moved, run the following statement.
ALTER DATABASE database_name MODIFY FILE ( NAME = logical_name, FILENAME = 'new_path\os_file_name' );
Run the following statement.
ALTER DATABASE database_name SET ONLINE;
Verify the file change by running the following query.
SELECT name, physical_name AS CurrentLocation, state_desc
FROM sys.master_files
WHERE database_id = DB_ID(N'<database_name>');
for more details go through url
USE MASTER;
GO
ALTER DATABASE DBName
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
GO
-- Detach DB
EXEC MASTER.dbo.sp_detach_db #dbname = N'DBName'
GO
Step 1:Detach DB
USE MASTER;
GO
ALTER DATABASE DBName
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
GO
-- Detach DB
EXEC MASTER.dbo.sp_detach_db #dbname = N'DBName'
GO
Step 2:
Now move the files from C drive to E drive. You can now reattach the files with E drive.
I'm working on vb.NET 2013 and SQL server 2008R2.
I have this situation to resolve:
I have a database "DB1". I want to create a copy of this database on the same SQL server with another name "DB2", and after make this database ready to connect.
How can I do this through code from Vb.NET?
Check out this tech net link for restore with new file names.
http://technet.microsoft.com/en-us/library/ms190447(v=sql.105).aspx.
Take a backup of database one (DB1).
Verify backup is valid.
Get correct logical and physical file names
Restore with a move command to create database two (DB2).
Change ownership to SA. Defaults to SQL login that creates the database
Here is a script that I tested on my laptop. Nice thing about backup is no need for down time. If you decide to take off line, copy data files, and create database for attach, down time is created.
-- Sample database
USE AdventureWorks2012;
GO
-- 1 - Make a backup
BACKUP DATABASE AdventureWorks2012
TO DISK = 'C:\mssql\backup\AdventureWorks2012.Bak'
WITH FORMAT,
MEDIANAME = 'SQLServerBackups',
NAME = 'Full Backup of AdventureWorks2012';
GO
-- Use master
USE master
GO
-- 2 - Is the backup valid
RESTORE VERIFYONLY
FROM DISK = 'C:\mssql\backup\AdventureWorks2012.Bak';
GO
-- 3 - Check the logical / physical file names
RESTORE FILELISTONLY
FROM DISK = 'C:\mssql\backup\AdventureWorks2012.Bak';
GO
-- 4 - Restore the files change the location and name
RESTORE DATABASE Adv2012
FROM DISK = 'C:\mssql\backup\AdventureWorks2012.Bak'
WITH RECOVERY,
MOVE 'AdventureWorks2012_Data' TO 'c:\mssql\data\MyAdvWorks_Data.mdf',
MOVE 'AdventureWorks2012_Log' TO 'c:\mssql\log\MyAdvWorks_Data.ldf';
GO
-- 5 - Switch owner to system admin
ALTER AUTHORIZATION ON DATABASE::Adv2012 TO SA;
GO
I have been created new database and the log file groth very past, and I get error mesaage that the log is full due to 'BACKUP'.
I looked in the differences between this Database and other databases in the SERVER, and I seen that in all databases log_reuse_wait is 0 and log_reuse_wait_desc is NOTHING and in my database log_reuse_wait is 0 and log_reuse_wait_desc is LOG_BACKUP.
I want to change this property in my database to 0 and NOTHING.
How can I do that?
This is a read-only status variable. It tells you why the log cannot be truncated at this point.
You have to remove the cause of that condition instead of just changing the value (which isn't even possible).
Either backup the database log or switch to SIMPLE recovery mode. You should probably read a little on both just to understand the implications.
David W.'s script did not quite work for me. (SQL Server 2008 r2)
I needed to modify it slightly. Using the script as is I got the message that there was no such file for database [master]. Alter the DATABASE as David W. recommends and then switch to the target database and run the DBCC SHRINKFILE() command.
Also the first argument to DBCC SHRINKFILE() must be the logical name of the database log file, which is represented in the following script as logical_file_name_for_LOG
USE [master]
GO
ALTER DATABASE <db name> SET RECOVERY full
GO
ALTER DATABASE <db name> SET RECOVERY SIMPLE WITH NO_WAIT;
GO
USE [db name]
GO
DBCC SHRINKFILE('<logical_file_name_for_LOG>', 0, TRUNCATEONLY)
i found the solution.
even the database is in SIMPLE mode is wait to BACKUP_LOG, so you need to change the recovery mode to FULL and then back to SIMPLE with no wait
USE [master]
GO
ALTER DATABASE <db name> SET RECOVERY full
GO
ALTER DATABASE <db name> SET RECOVERY SIMPLE WITH NO_WAIT;
GO
USE [db name]
GO
DBCC SHRINKFILE('<log file name>', 0, TRUNCATEONLY)
I know this is old, but the answers are wrong.
If the database has recovery mode FULL and that is intended, then do not change it to simple.
The log_reuse_wait_desc says what the state is before the log can be reused or shrinked. In this case it is LOG_BACKUP, meaning that, to shrink the transaction log, you need to backup the transaction log first and shrink it or backup the log and let the SQLServer reuse the log space.
A description of the log_reuse_wait_desc states can be found here
I am trying to restore a database in my sql server 2005 express edition. I know that to restore the database I need to make it to single user. I am giving this command to make it to single user
USE [master]
ALTER DATABASE database_name SET SINGLE_USER WITH ROLLBACK IMMEDIATE
This command executed properly and I can even see a small image in the object explorer on this database showing that this is now single user.
Now I am trying to restore the database, by following these steps
->right click on the database and tasks and then to restore database. I am selecting the path where the backup file is located and clicking on restore.
But I still get that error "Exclusive access could not be obtained because database is in use(microsoft.sqlserver.smo). Am I missing anything. I have googled it and all most all the sites suggest that database needs to be in single user mode and nothing else.
I did not try the detach and attaching of database method. I have never done that before and would like to know if that is safe to do.
edit: thanks for the answers. Both suggested me same answer so I am marking one answer as chosen.
I even selected overwrite the existing database from options.
First, it's best to back up and restore rather than detach and attach.
Second, it's most likely that the session you're using to set the database to SINGLE_USER is the one that still has it when you try to run the restore (since you're using the GUI, it's connecting under its own session so it's unable to get access).
Either do the restore as a text command or switch the query window to use another database first, such as master. Or you could just close the query window so it's no longer connected.
You can always check who's connected with select * from master.dbo.sysprocesses.
Update
Assuming the database you want to restore already exists, and if you have a single backup file on disk (that doesn't have multiple backups in it) and there's no need to restore log files after restoring the full backup, then restoring via script is super, super easy:
RESTORE DATABASE DBName FROM DISK = 'C:\path\DBNameBackup.bak';
Learning this syntax will make your life easier because then when you set SINGLE_USER you're already in the sole session that is connected. Plus, I find that typing the restore command is faster than using the GUI, and I like the control I have over things. Repetition of this eventually cements it in your mind and you don't have to look up the syntax any more.
It's not even that difficult to restore log files. Just one simple thing to remember, WITH NORECOVERY:
RESTORE DATABASE DBName FROM DISK = 'C:\path\DBNameBackup.bak' WITH NORECOVERY;
RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackup1.log' WITH NORECOVERY;
RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackup2.log' WITH NORECOVERY;
RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackup3.log' WITH NORECOVERY;
... 4 5 6 7 and so on
RESTORE LOG DBName FROM DISK = 'C:\path\DBNameBackupX.log' WITH RECOVERY;
There... you've restored your log files, very easily. You can even restore to an exact point in time using WITH STOPAT! Also, if you forget and accidentally submit the last log restore statement WITH NORECOVERY then you just issue RESTORE DATABASE DBName WITH RECOVERY; to perform the final steps to make the database usable (rolling back uncommitted transactions, etc.).
You can use this script to kill all processes using the database and then try to restore it again:
declare #sql as varchar(20), #spid as int
select #spid = min(spid) from master..sysprocesses where dbid = db_id('<database_name>')
and spid != ##spid
while (#spid is not null)
begin
print 'Killing process ' + cast(#spid as varchar) + ' ...'
set #sql = 'kill ' + cast(#spid as varchar)
exec (#sql)
select
#spid = min(spid)
from
master..sysprocesses
where
dbid = db_id('<database_name>')
and spid != ##spid
end
print 'Process completed...'
Go to "Options" item just under "General" on the left hand side list.
Make sure that "Overwrite the existing database" is checked ("Restore Options" section).
Good luck.