Change a SQL Server 2008 R2 database collation - sql

I have created a database and I forgot to set its collation. So all my chars are like ???? in it. The default one is SQL_Latin1_General_CP1_CI_AS and I want to change it to Persian_100_CI_AS.
I used this SQL statement:
USE master;
GO
ALTER DATABASE land_gis
COLLATE Persian_100_CI_AS ;
GO
But I get this error :
Msg 5030, Level 16, State 2, Line 1
The database could not be exclusively locked to perform the operation.
Msg 5072, Level 16, State 1, Line 1
ALTER DATABASE failed. The default collation of database 'land_gis' cannot be
set to Persian_100_CI_AS.
I can not drop and rebuild database. Is there any way to change it?
Thanks a lot
By the way, I'm using SQL Server 2008 R2.

Seems like your database is in use - if you're confident that you'll do no harm - you can use this code to get exclusive access:
USE master;
GO
ALTER DATABASE land_gis
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
ALTER DATABASE land_gis
COLLATE Persian_100_CI_AS ;
GO
Then your ALTER DATABASE COLLATE call should work .
WARNING: this call to SET SINGLE_USER WITH ROLLBACK IMMEDIATE will disconnect anyone who might be connected to that database without warning, without chance of saving data! USE WITH CAUTION! especially in production environments!!

You can use sp_lock then find the spid associated with concerned DB and kill them (but first you can check them whats running behind them by
DBCC inputbuffer(spid))
USE master;
GO
ALTER DATABASE land_gis
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
ALTER DATABASE land_gis
COLLATE Persian_100_CI_AS ;
GO

Related

How can i use master db in stored procedures

I'm trying to create restore db proc. I encountered a problem because i cannot use the command 'use master'. I have try with dynamic SQL but there is no result:
My code:
alter proc dbo.RestoreDB
(
#location as varchar(4000)
)
as
begin
declare #setMasterDb as varchar(400) = 'use master'
exec (#setMasterDb);
ALTER DATABASE [testDb] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
RESTORE DATABASE [testDb] FROM DISK = #location WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 5
ALTER DATABASE [testDb] SET MULTI_USER
end
GO
Is there workaround?
Switching database contexts (USE someDBName) in the middle of a Stored Proc (or function) is not allowed. Also, you do not need to be pointed at the master db context to run a BACKUP/RESTORE, you can be pointed to almost any DB. To fix your issue, just remove your DB switching and point your query window any DB except the one you want to restore.
EDIT: Updated to point to any DB EXCEPT the one you're trying to restore. Thanks to #DMason for that comment.

How to drop a database when it's currently in use?

NB. I don't want to mark the check box in the wizard for deletion. This question's strictly about scripting the behavior.
When I run the following script to get a fresh start, I get the error that the database Duck can't be deleted because it's currently in use.
use Master
drop database Duck
drop login WorkerLogin
drop login AdminLogin
go
Be that as it may (even though I'm the only user currently in the system and I run no other queries but that's another story), I need to close all the existing connections. One way is to wait it out or restart the manager. However I'd like to script in that behavior so I can tell the stubborn server to drop the duck down. (Yes, "typo" intended.)
What do I need to add to the dropping statement?
Try below code.
USE master;
ALTER DATABASE [Duck] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [Duck] ;
For deep discussion see this answer.
You have to kill first all active connections before you can drop the database.
ALTER DATABASE YourDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE
--do you stuff here
ALTER DATABASE YourDatabase SET MULTI_USER
http://wiki.lessthandot.com/index.php/Kill_All_Active_Connections_To_A_Database
How do you kill all current connections to a SQL Server 2005 database?
if you're ssms tab is not currently on the db to be dropped (meaning you are in the master db), then these will help:
https://dba.stackexchange.com/questions/2387/sql-server-cannot-drop-database-dbname-because-it-is-currently-in-use-but-n
https://dba.stackexchange.com/questions/34264/how-to-force-drop-database-in-sql-server-2008

Error In Database Renaming

I need to rename one of my database and tried a query like this
ALTER DATABASE Test MODIFY NAME = NewTest
But this throws an error
Msg 5030, Level 16, State 2, Line 1
The database could not be exclusively locked to perform the operation.
Can any one give me any suggestion?
Try something like;
USE master
GO
ALTER DATABASE Test
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
GO
ALTER DATABASE Test MODIFY NAME = NewTest
GO
ALTER DATABASE NewTest
SET MULTI_USER
GO
Be aware of the fact that this may not rename the physical file on the hard drive though.
There are a couple of things you need to investigate. The reason you're getting that error could be due to one or more of the following things:
The account you're using does not have permission to run the command
The DB is locked by another process/user
The database contains a file group that is read-only
You can try and force single user mode to check 2.
ALTER DATABASE SINGLE_USER ROLLBACK IMMEDIATE.
That will kill any concurrent connections to the DB allowing you to rule out number two.
You have two options:
Look for and kill all connections like OMG Priories suggest
Open the database in Single Server Mode as described here:
http://technet.microsoft.com/en-us/library/ms345598(v=sql.105).aspx

How to pass a database name as a parameter in SQL Server

USE master
GO
DECLARE #DbName nvarchar(MAX)
SET #DbName = N'DataBase'
ALTER DATABASE #DbName
SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE #DbName SET OFFLINE WITH NO_WAIT
GO
ALTER DATABASE #DbName SET ONLINE
GO
ALTER DATABASE #DbName
SET MULTI_USER
GO
I know i can use EXEC but it's a bit ugly....
It is impossible to use DB name from variable.
Use Dynamic Querying, even if it is ugly.
You can't use the database name in a variable.
You have several options:
Different DML scripts for each DB
Dynamic SQL
Firstly, you can't parameterise DDL statements like this. Secondly, GO is a batch terminator and parameters won't be available after this.
I don't recall if MSSqlServer allows the same flexibility as Oracle and MySQL, but in those you can set the default database for each connection. If the queries and statements do not specify a database (use (dbname)), it uses the default. Perhaps that is sufficient parametrization for your purposes?

Drop database only if Backup is successful

This might be an easy one for some one but I haven't found a simple solution yet.
I'm automating a larger process at the moment, and one step is to back up then drop the database, before recreating it from scratch.
I've got a script that will do the back up and drop as follows:
Use [Master]
BACKUP DATABASE [databaseName]
TO DISK='D:\Backup\databaseName\20100122.bak'
ALTER DATABASE [databaseName]
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
DROP DATABASE [databaseName]
but I'm worried that the DROP will happen even if the BACKUP fails.
How can I change the script so if the BACKUP fails, the DROP won't happen?
Thanks in advance!
If your SQL Server version is 2005 or greater, you can wrap your statements with a try catch. If the backup fails, it will jump to the catch without dropping the database...
Use [Master]
BEGIN TRY
BACKUP DATABASE [databaseName]
TO DISK='D:\Backup\databaseName\20100122.bak'
ALTER DATABASE [databaseName]
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
DROP DATABASE [databaseName]
END TRY
BEGIN CATCH
PRINT 'Unable to backup and drop database'
END CATCH
You can catch any error codes that occur with the SQL server error variable as follows. A zero indicates no error occurred. Note that the value is set every time a T-SQL statement is executed, so you need to catch it as soon as you have backed up:
USE [Master]
DECLARE #errorCode int
BACKUP DATABASE [databaseName]
TO DISK='D:\Backup\databaseName\20100122.bak'
SET #errorCode = ##ERROR
IF (#errorCode = 0)
BEGIN
ALTER DATABASE [databaseName]
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
DROP DATABASE [databaseName]
END
This is the simplest way I can think of, as well as allowing you to catch known error codes and handle them differently if you need to. SELECT * FROM master.sys.messages gives you a list of all known error codes and messages if you want to take it further.