I write a simple procedure to shrink database log,just need to input the database name:
ALTER proc [dbo].[sp_shrinkDBAndDBLog]
#databaseName nvarchar(100)
as
begin
declare #logName nvarchar(100),
#dynamicSQL nvarchar(500)
set #dynamicSQL='ALTER DATABASE '+#databaseName+' SET RECOVERY SIMPLE WITH NO_WAIT'
exec(#dynamicSQL)
--select name from HLJEDI_SYS.sys.sysfiles where groupid=0;
set #dynamicSQL=N'select #logName= name from '+#databaseName+'.sys.database_files where type_desc=''LOG'''
exec sp_executesql #dynamicSQL,N'#logName nvarchar(100) output',#logName output
--select * from sys.sysfiles where groupid=0
set #dynamicSQL='DBCC SHRINKFILE (N'''+#logName+''',11,TRUNCATEONLY)'
exec(#dynamicSQL)
--DBCC SHRINKFILE (N'CUC_OA_LOG' , 11, TRUNCATEONLY)
set #dynamicSQL='ALTER DATABASE '+#databaseName+' SET RECOVERY FULL WITH NO_WAIT'
exec(#dynamicSQL)
--ALTER DATABASE OA SET RECOVERY FULL --(Restore to Full Schema)
end
but when i execute with:
exec sp_shrinkDBAndDBLog 'DBName'
it has error:
sys.database_files can't find database 'master' file 'eca2_log'。The file was been deleted and not exists。
And what is the problem? Thank you if you tell me and show the detail and princeple.
Looks like you might be missing a USE { database } command before you execute the DBCC SHRINKFILE command, and so the DBCC is not getting executed on the correct database.
Related
I use the database name in several places in my script, and I want to be able to quickly change it, so I'm looking for something like this:
DECLARE #DBNAME VARCHAR(50)
SET #DBNAME = 'TEST'
CREATE DATABASE #DBNAME
GO
ALTER DATABASE #DBNAME SET COMPATIBILITY_LEVEL = 90
GO
ALTER DATABASE #DBNAME SET RECOVERY SIMPLE
GO
But it doesn't work. So what's the correct way to write this code?
Put the entire script into a template string, with {SERVERNAME} placeholders. Then edit the string using:
SET #SQL_SCRIPT = REPLACE(#TEMPLATE, '{SERVERNAME}', #DBNAME)
and then run it with
EXECUTE (#SQL_SCRIPT)
It's hard to believe that, in the course of three years, nobody noticed that my code doesn't work!
You can't EXEC multiple batches. GO is a batch separator, not a T-SQL statement. It's necessary to build three separate strings, and then to EXEC each one after substitution.
I suppose one could do something "clever" by breaking the single template string into multiple rows by splitting on GO; I've done that in ADO.NET code.
And where did I get the word "SERVERNAME" from?
Here's some code that I just tested (and which works):
DECLARE #DBNAME VARCHAR(255)
SET #DBNAME = 'TestDB'
DECLARE #CREATE_TEMPLATE VARCHAR(MAX)
DECLARE #COMPAT_TEMPLATE VARCHAR(MAX)
DECLARE #RECOVERY_TEMPLATE VARCHAR(MAX)
SET #CREATE_TEMPLATE = 'CREATE DATABASE {DBNAME}'
SET #COMPAT_TEMPLATE='ALTER DATABASE {DBNAME} SET COMPATIBILITY_LEVEL = 90'
SET #RECOVERY_TEMPLATE='ALTER DATABASE {DBNAME} SET RECOVERY SIMPLE'
DECLARE #SQL_SCRIPT VARCHAR(MAX)
SET #SQL_SCRIPT = REPLACE(#CREATE_TEMPLATE, '{DBNAME}', #DBNAME)
EXECUTE (#SQL_SCRIPT)
SET #SQL_SCRIPT = REPLACE(#COMPAT_TEMPLATE, '{DBNAME}', #DBNAME)
EXECUTE (#SQL_SCRIPT)
SET #SQL_SCRIPT = REPLACE(#RECOVERY_TEMPLATE, '{DBNAME}', #DBNAME)
EXECUTE (#SQL_SCRIPT)
You can also use sqlcmd mode for this (enable this on the "Query" menu in Management Studio).
:setvar dbname "TEST"
CREATE DATABASE $(dbname)
GO
ALTER DATABASE $(dbname) SET COMPATIBILITY_LEVEL = 90
GO
ALTER DATABASE $(dbname) SET RECOVERY SIMPLE
GO
EDIT:
Check this MSDN article to set parameters via the SQLCMD tool.
Unfortunately you can't declare database names with a variable in that format.
For what you're trying to accomplish, you're going to need to wrap your statements within an EXEC() statement. So you'd have something like:
DECLARE #Sql varchar(max) ='CREATE DATABASE ' + #DBNAME
Then call
EXECUTE(#Sql) or sp_executesql(#Sql)
to execute the sql string.
You cannot use a variable in a create table statement. The best thing I can suggest is to write the entire query as a string and exec that.
Try something like this:
declare #query varchar(max);
set #query = 'create database TEST...';
exec (#query);
How can I drop a database table with sql server agent jobs, and upload a new .bak file using a scripts in sql
This is a well functioning script for sql server agent jobs. How can I do the same to replace the same for tables with .bak file ?
DECLARE #jobId binary(16)
SELECT #jobId = job_id FROM msdb.dbo.sysjobs WHERE (name = N'Name of Your Job')
IF (#jobId IS NOT NULL)
BEGIN
EXEC msdb.dbo.sp_delete_job #jobId
END
DECLARE #ReturnCode int
EXEC #ReturnCode = msdb.dbo.sp_add_job #job_name=N'Name of Your Job'
I am a bit confused with the replace with .bak file, but I assume that you mean that the .bak file is containing the CREATE TABLE sql script.
To drop the database table:
DROP TABLE [schema].[table_name];
To recreate the database table from a backup script file:
-- Declare variable.
DECLARE #BulkColumn nvarchar(max);
-- Read information from the backup script file and store it in the variable.
SELECT #BulkColumn = [BulkColumn] FROM OPENROWSET(BULK N'<PATH_TO_FILE>', SINGLE_CLOB) AS Contents;
-- Execute the contents of the script dynamically.
EXECUTE sp_executesql #BulkColumn;
You can test this first in SSMS, to avoid any undesired issues, make sure you know what the backup script file looks like before executing it.
Creat a SQL Job and add a step of Type: Transact-SQL script and select the correct Database, paste in the script and give it a try.
I am trying to alter database through a DDL trigger which will fire on creation. However I am getting a below error.
CREATE TRIGGER ddl_trig_database
ON ALL SERVER
FOR CREATE_DATABASE
AS
declare #dbname as nvarchar(100)
declare #sql as nvarchar(max)
select #dbname =
CAST(eventdata().query(
'/EVENT_INSTANCE/DatabaseName[1]/text()'
) as NVarchar(128))
select #sql = N'SET IMPLICIT_TRANSACTIONS OFF
ALTER DATABASE ' + #dbname+ N' SET COMPATIBILITY_LEVEL = 110
SET IMPLICIT_TRANSACTIONS ON'
exec (#sql)
GO
create database test
Error:
Msg 226, Level 16, State 6, Line 22
ALTER DATABASE statement not allowed within multi-statement transaction.
The statement has been terminated.
I am on SQL Server 2014 on Windows 2012.
If you want a specific compatibility level for each new database created - just set that compatibility level in the model database which is the "template" for all new databases being created ...
No need for a system-level trigger for this ....
I realized the DDL trigger will be on its own transaction and Alter is not allowed if a transaction is already started. So to workaround with this problem I have created SQL Job. and put the Alters in the Job and modified the Trigger to call msdb..start_sql_job.
--Trigger
CREATE TRIGGER ddl_trig_database
ON ALL SERVER
FOR CREATE_DATABASE
AS
exec msdb..sp_start_job 'Initialize Database'
GO
--Job
declare #dbname as nvarchar(100)
declare #sql as nvarchar(max)
select top 1 #dbname = name from sys.databases
where name like 'gtp%' and create_date >= getdate() - .08
order by create_date desc
IF #dbname is not null
begin
select #sql = N'ALTER DATABASE ' + #dbname+ N' SET COMPATIBILITY_LEVEL = 110'
exec sp_executesql #sql
print 'Altered database'
end
print 'completed'
I am trying to change the recovery model of the current database.
This is what I have:
DECLARE #dbName VARCHAR(50)
SELECT #dbName = DB_NAME()
ALTER DATABASE #dbName SET RECOVERY SIMPLE WITH NO_WAIT
#dbName gives me:
Incorrect syntax near '#dbName'.
I tried:
ALTER DATABASE database_id SET RECOVERY SIMPLE WITH NO_WAIT
database_id gives me:
Msg 5011, Level 14, State 5, Line 3 User does not have permission to
alter database 'database_id', the database does not exist, or the
database is not in a state that allows access checks.
How should I execute this on the current database?
DECLARE #sql NVARCHAR(MAX) = N'ALTER DATABASE '
+ QUOTENAME(DB_NAME())
+ ' SET RECOVERY SIMPLE WITH NO_WAIT;';
EXEC sp_executesql #sql;
We are connecting to a database in C# and then running a few sql scripts on it.
I need to be able to shrink the current database without specifying the name.
We do not have the database name in the program we are just given the connection and running the scripts.
This is what I started with:
ALTER DATABASE SSSIndexes SET RECOVERY SIMPLE WITH NO_WAIT
GO
DBCC SHRINKFILE(N'SSSIndexes_Log', 1) <-- my issue is here
GO
But I won't know the database name or the log file name.
Can it be done?
You can get the current database and shrink it by calling:
DECLARE #dbName VARCHAR(50)
SELECT #dbName = DB_NAME()
DBCC SHRINKDATABASE(#dbName)
To do just the log file:
DECLARE #logName VARCHAR(50)
SELECT #logName = name FROM sys.master_files WHERE database_id = db_id() AND type = 1
DBCC SHRINKFILE(#logName, 1)