Msg 5011, Level 14, State 5, Line 11 ALTER DATABASE statement failed - sql-server

I ran the below scripts
DECLARE #name VARCHAR(50)
DECLARE #Statment VARCHAR(500)
DECLARE DB_cursor CURSOR
FOR
SELECT name
FROM sys.databases
WHERE name NOT IN ( 'master', 'tempdb', 'model', 'msdb',
'ReportServer$SQLEXPRESS',
'ReportServer$SQLEXPRESSTempDB' )
OPEN DB_cursor
FETCH NEXT FROM DB_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #name
ALTER DATABASE [#name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
SET #Statment = 'Backup database ' + #name + ' To disk =N' + ''''
+ 'C:\Mas\' + #name + '.bak' + ''''
PRINT #Statment
EXEC(#Statment)
-- ALTER DATABASE [#name] SET MULTI_USER WITH ROLLBACK IMMEDIATE
-- EXEC sp_dboption #name, N'offline', N'false'
FETCH NEXT FROM DB_cursor INTO #name
END
CLOSE DB_cursor
DEALLOCATE DB_cursor
I got the error below
Msg 5011, Level 14, State 5, Line 11
User does not have permission to alter database '#name', the database does not exist, or the database is not in a state that allows access checks.
Msg 5069, Level 16, State 1, Line 11
ALTER DATABASE statement failed.
Please let me know where I am stuck on how to resolve this issue.
Note:- I ran this script in sa login.

Error message clearly states the reason. It's because Alter database command treats [#name] as a database and not a placeholder. You can include both the statements in dynamic query and then execute. Following should work:
DECLARE #name VARCHAR(50)
DECLARE #Statment VARCHAR(500)
DECLARE #Statment1 VARCHAR(500)
DECLARE #Statment2 VARCHAR(500)
select name from sys.databases where name NOT IN('master','tempdb','model','msdb','ReportServer$SQLEXPRESS','ReportServer$SQLEXPRESSTempDB')
OPEN DB_cursor
FETCH NEXT FROM DB_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
Print #name
SET #Statment = 'ALTER DATABASE ' + #name + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE; '
EXEC(#Statment)
SET #Statment1 = 'BACKUP DATABASE ' + #name + ' To disk =N' +''''+ 'C:\Mas\'+ #name +'.bak'+''''
EXEC(#Statment1)
SET #Statment2 = 'ALTER DATABASE ' + #name + ' SET MULTI_USER WITH ROLLBACK IMMEDIATE; '
EXEC(#Statment2)
EXEC(#Statment)
-- ALTER DATABASE [#name] SET MULTI_USER WITH ROLLBACK IMMEDIATE
-- EXEC sp_dboption #name, N'offline', N'false'
FETCH NEXT FROM DB_cursor INTO #name
END
CLOSE DB_cursor
DEALLOCATE DB_cursor

I change your T-SQL and this worked.
you most change destination of back up file in the anther path like this sample .
DECLARE #name VARCHAR(50)
DECLARE #Statment VARCHAR(500)
DECLARE DB_cursor CURSOR
FOR
SELECT name
FROM sys.databases
WHERE name NOT IN ( 'master', 'tempdb', 'model', 'msdb',
'ReportServer$SQLEXPRESS',
'ReportServer$SQLEXPRESSTempDB' )
OPEN DB_cursor
FETCH NEXT FROM DB_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #name
-- DECLARE #A NVARCHAR(800) = ' ALTER DATABASE [' + #name + '] SET Multi_USER WITH ROLLBACK IMMEDIATE '
DECLARE #A NVARCHAR(800) = ' ALTER DATABASE [' + #name + '] SET SINGLE_USER WITH ROLLBACK IMMEDIATE '
EXECUTE Sp_ExecuteSQL #A
SET #Statment = 'Backup database ' + #name + ' To disk =N' + ''''
+ 'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER2012\MSSQL\Backup\'
+ #name + '.bak' + ''''
PRINT #Statment
EXEC(#Statment)
-- ALTER DATABASE [#name] SET MULTI_USER WITH ROLLBACK IMMEDIATE
-- EXEC sp_dboption #name, N'offline', N'false'
FETCH NEXT FROM DB_cursor INTO #name
END
CLOSE DB_cursor
DEALLOCATE DB_cursor
Like down picture
you most grate access to SQL Server user in your path of Back up

The SQL command ALTER DATABASE does not allow a parameter hence it is treating #name as being the actual name and not as a parameter.
ALTER DATABASE
NAME
Specifies a logical name for the file.
logical_file_name
Is the name used in Microsoft SQL Server when referencing the file. The name must be unique within the database and conform to the rules for identifiers. The name can be a character or Unicode constant, a regular identifier, or a delimited identifier. For more information, see Using Identifiers.

You most use SP_ExecuteSQL for change state of Database
DECLARE #A NVARCHAR(800) = ' ALTER DATABASE [' +
#name +
'] SET SINGLE_USER WITH ROLLBACK IMMEDIATE '
EXECUTE Sp_ExecuteSQL #A
And then you can set database in single user mode.

Related

update statement value in multi table at once

I have over 100 tables in SQL Server 2000 with the same column name in each table. Now I want to update a value in 100 tables at once using a SQL update statement.
How do I do that? I try to google and stackoverflow but not really help.
Thanks so much
Create a cursor for all table in your database and using dynamic query to execute.
This script will be help you do this.
--USE [Your DB]
--GO
DECLARE #tableName VARCHAR(100)
DECLARE #sqlQuery VARCHAR(MAX)
DECLARE curTable CURSOR FOR SELECT name FROM sys.objects WHERE type_desc = 'USER_TABLE' AND name NOT IN ('sysdiagrams')
OPEN curTable
FETCH NEXT FROM curTable INTO #tableName
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #sqlQuery = 'UPDATE ' + #tableName + 'SET [YourCol1] = [YourVal1], [YourCol2] = [YourVal2] ...'
PRINT #sqlQuery
EXECUTE sp_executesql #sqlQuery
FETCH NEXT FROM curTable INTO #tableName
END
CLOSE curTable
DEALLOCATE curTable

How can I quickly delete all databases whose name matches a patttern?

I have many databases that on my SQL Server box that start with a prefix zzz.
Is there a way to do a DROP DATABASE (or some other method) that will remove and delete the data files? If a connection is opened, I want it closed.
Basically I just want them gone.
Generate a drop script, copy/paste & run:
exec master.sys.sp_msforeachdb 'if ''?'' like ''ZZZ%'' print ''drop database [?]'''
Or drop directly in the SQL string if your brave.
use master;
go
-- this will drop all dbs that start with t5....
declare #strsql varchar(500)
declare #curname sysname
select #curname = name from sys.databases
where name like 't5%'
while( ##rowcount> 0)
begin
set #strsql ='ALTER DATABASE ' +#curname +' SET OFFLINE WITH ROLLBACK IMMEDIATE'
exec (#strsql)
set #strsql ='drop database '+#curname
exec (#strsql)
select #curname = name from sys.databases
where name like 't5%'
end
You could write a dynamic SQL to do this:
use master
go
declare #dbnames nvarchar(max)
declare #statement nvarchar(max)
declare #closeconnection nvarchar(max)
set #dbnames = ''
set #statement = ''
select #dbnames = #dbnames + ',[' + name + ']' from sys.databases where name like 'zzz%'
if len(#dbnames) = 0
begin
print 'no databases to drop'
end
else
BEGIN
SET #closeconnection = 'alter database ' + substring(#dbnames, 2, len(#dbnames))
+ ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE'
set #statement = 'drop database ' + substring(#dbnames, 2, len(#dbnames))
print #statement
EXEC sp_executesql #closeconnection;
exec sp_executesql #statement;
end
Normally, the syntax to close all active connections to a database is:
--set it to single user to disable any other connections
ALTER DATABASE YourDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE
--do your stuff here
--set it back to multiple users
ALTER DATABASE YourDatabase SET MULTI_USER
Alternatively, you could also generate a dynamic select list that populates your drop database statement along with close connection statements like this:
USE master;
Go
SELECT 'DROP DATABASE '+ name,
'alter database ' + name + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE'
FROM sys.databases WHERE name like 'zzz%';
GO
Courtesy: #SeriousM and OFH
I modified benjamin's script a bit so you only have to declare the prefix once.
use master;
declare #dbPrefix varchar(10)
set #dbPrefix = 'zzz_%';
declare #strsql varchar(500)
declare #curname sysname
select #curname = name from sys.databases
where name like #dbPrefix
while( ##rowcount> 0)
begin
set #strsql ='ALTER DATABASE ' +#curname +' SET SINGLE_USER WITH ROLLBACK IMMEDIATE'
exec (#strsql)
set #strsql ='drop database '+#curname
exec (#strsql)
select #curname = name from sys.databases
where name like #dbPrefix
end

how to delete only Windows Login in SQL Server

I am using below code to delete SQL Logins
declare #name varchar(1000)
declare #xtype varchar(20)
declare #sqlstring nvarchar(4000)
declare SPViews_cursor cursor for
SELECT QUOTENAME(NAME) AS name
FROM sys.server_principals
open SPViews_cursor
fetch next from SPViews_cursor into #name
while ##fetch_status = 0
begin
set #sqlstring = 'drop LOGIN ' + #name
exec sp_executesql #sqlstring
set #sqlstring = ' '
fetch next from SPViews_cursor into #name
end
close SPViews_cursor
deallocate SPViews_cursor
but it is dropping all logins, I just need to drop Windows login so only SQL auth. can be possible. Any suggestion? And can this code be made shorter?
Change your query to this:
SELECT QUOTENAME(NAME) AS name
FROM sys.server_principals
WHERE type = 'U'
U means Window Login. You can find more info here.
USE type_desc or type column to filter 'Windows Login'
SELECT QUOTENAME(NAME) AS name
FROM sys.server_principals
where type_desc = 'WINDOWS_LOGIN'

Switching database context at run time

I am using below code to switch db context to master and create procedure and setup start up script.
BEGIN TRY
DECLARE #dbName NVARCHAR(100)
SET #dbName = DB_NAME()
USE MASTER
IF NOT EXISTS (
SELECT name
FROM sys.objects
WHERE object_id = OBJECT_ID('spSetTrustWorthyOn')
)
EXEC (
'CREATE PROCEDURE spSetTrustWorthyOn
AS
BEGIN
ALTER DATABASE [' + #dbName + '] SET TRUSTWORTHY ON
END'
)
EXECUTE sp_procoption 'spSetTrustWorthyOn'
,'startup'
,'ON'
END TRY
BEGIN CATCH
END CATCH
GO
Now Issue is when I want to switch back to existing database.I could not find any way to go back to my original database.
I also can not hard code the database as this is dynamic query and we have multiple databases.
Any help will be much appreciated.
Thanks
Instead of a USE statement for the master database, qualify the catalog views and use EXEC sp_executesql statement with the master database qualified. This will avoid changing the database context in the outer script.
DECLARE
#dbName sysname = DB_NAME()
,#sql nvarchar(MAX);
BEGIN TRY
IF NOT EXISTS (
SELECT *
FROM master.sys.objects
WHERE object_id = OBJECT_ID(N'spSetTrustWorthyOn')
)
BEGIN
SET #sql = N'CREATE PROCEDURE spSetTrustWorthyOn
AS
BEGIN
ALTER DATABASE ' + QUOTENAME(#dbName) + ' SET TRUSTWORTHY ON;
END;';
EXECUTE master..sp_executesql #sql;
EXECUTE sp_procoption
'spSetTrustWorthyOn'
,'startup'
,'ON';
END;
END TRY
BEGIN CATCH
THROW;
END CATCH;
GO

SQL Server 2008 Management Console: Automatically write results to a script and execute it

I would like to write a script which produces various statements out of a database.
Something like :
select 'DROP TABLE ['+ name + ']' from sys.objects where type = 'T' ;
I would like to automatically collect all output of such statements in a new file, and then I would like to execute this file. Is this possible ?
Important: The output should of course be without headers and without any other error/success, messages and so on.
In the optimal case, all necessary options for this should be set in the script itself, other than setting them in the user interface.
First, you create you dynamic script, something like...
DECLARE #sql NVARCHAR(MAX)
SELECT #sql =
COALESCE(#sql + CHAR(13), '') +
'DROP TABLE ['+ name + ']'
FROM sys.objects
WHERE [type] = 'T'
Execute that...
EXEC(#sql)
Then print that out to Messages-window...
PRINT #sql
And finally go to Messages-window, right-click it, select "Save results as...", Save as type > all files, and write your file name like myfile.sql
EDIT
I would never, EVER execute something like this automatically and without transaction. I'd rather save a script from Messages-window, open it, review it and then execute.
Are you wanting something like this?
If you only want to print the script use osql and a script something like this
DECLARE #schema VARCHAR(255)
DECLARE #table VARCHAR(255)
DECLARE PrintOutputCursor CURSOR LOCAL FAST_FORWARD FOR
SELECT [TABLE_SCHEMA], [TABLE_NAME]
FROM INFORMATION_SCHEMA.TABLES
OPEN PrintOutputCursor
FETCH NEXT FROM PrintOutputCursor INTO #schema, #table
WHILE ##FETCH_STATUS = 0 BEGIN
PRINT 'DROP TABLE ['+ #schema + '].[' + #table + '];'
FETCH NEXT FROM PrintOutputCursor INTO #schema, #table
END
CLOSE PrintOutputCursor
DEALLOCATE PrintOutputCursor
If you want to execute the script using osql use this script (NOT RECOMMENDED)
DECLARE #schema VARCHAR(255)
DECLARE #table VARCHAR(255)
DECLARE #exec VARCHAR(4000)
DECLARE PrintOutputCursor CURSOR LOCAL FAST_FORWARD FOR
SELECT [TABLE_SCHEMA], [TABLE_NAME]
FROM INFORMATION_SCHEMA.TABLES
OPEN PrintOutputCursor
FETCH NEXT FROM PrintOutputCursor INTO #schema, #table
WHILE ##FETCH_STATUS = 0 BEGIN
SET #exec = 'DROP TABLE ['+ #schema + '].[' + #table + '];'
-- Uncomment the following to execute the dynamic statement
-- EXEC (#exec)
FETCH NEXT FROM PrintOutputCursor INTO #schema, #table
END
CLOSE PrintOutputCursor
DEALLOCATE PrintOutputCursor

Resources