Restore multiple transaction log backup from disk - tsql

We are receiving transaction log backups from a vendor for a off-site database. We have already restored the full backup in Standby mode. we will be receiving multiple transaction log backups everyday. I need a script to restore the transaction log backups to standby mode. The script I am trying to use pulls the files into the filelist, but the script is not doing anything and I can't figure out why.
Can someone help me figure this out?
USE Master;
GO
SET NOCOUNT ON
-- 1 - Variable declaration
DECLARE #dbName sysname
DECLARE #backupPath NVARCHAR(500)
DECLARE #cmd NVARCHAR(500)
DECLARE #fileList TABLE (backupFile NVARCHAR(255))
DECLARE #lastFullBackup NVARCHAR(500)
DECLARE #lastDiffBackup NVARCHAR(500)
DECLARE #backupFile NVARCHAR(500)
-- 2 - Initialize variables
SET #dbName = 'Telcor'
SET #backupPath = 'D:\TelcorLogDump\'
-- 3 - get list of files
SET #cmd = 'DIR /b "' + #backupPath + '"'
INSERT INTO #fileList(backupFile)
EXEC master.sys.xp_cmdshell #cmd
DECLARE backupFiles CURSOR FOR
SELECT backupFile
FROM #fileList
WHERE backupFile LIKE '%.TRN'
AND backupFile LIKE #dbName + '%'
-- AND backupFile > #lastFullBackup
OPEN backupFiles
-- Loop through all the files for the database
FETCH NEXT FROM backupFiles INTO #backupFile
WHILE ##FETCH_STATUS = 0
BEGIN
SET #cmd = 'RESTORE LOG [' + #dbName + '] FROM DISK = '''
+ #backupPath + #backupFile + ''' WITH STANDBY = N''D:\TelcorLogDump\ROLLBACK_UNDO_Telcor.BAK'
PRINT #cmd
FETCH NEXT FROM backupFiles INTO #backupFile
END
CLOSE backupFiles
DEALLOCATE backupFiles

I had to add two extra ticks at the end:
ROM DISK = '''
* #backupPath + #backupFile + ''' WITH STANDBY = N''D:\TelcorLogDump\ROLLBACK_UNDO_Telcor.BAK
'''

Related

How to import multiple CSV files into SQL Server tables?

I am using SQL Server 2017 version, and I want to import multiple .csv files into multiple tables in SQL server.
I found the following script in the net,
--BULK INSERT MULTIPLE FILES From a Folder
--a table to loop thru filenames drop table ALLFILENAMES
CREATE TABLE ALLFILENAMES(WHICHPATH VARCHAR(255),WHICHFILE varchar(255))
--some variables
declare #filename varchar(255),
#path varchar(255),
#sql varchar(8000),
#cmd varchar(1000)
--get the list of files to process:
SET #path = 'C:\Dump\'
SET #cmd = 'dir ' + #path + '*.csv /b'
INSERT INTO ALLFILENAMES(WHICHFILE)
EXEC Master..xp_cmdShell #cmd
UPDATE ALLFILENAMES SET WHICHPATH = #path where WHICHPATH is null
--cursor loop
declare c1 cursor for SELECT WHICHPATH,WHICHFILE FROM ALLFILENAMES where WHICHFILE like '%.csv%'
open c1
fetch next from c1 into #path,#filename
While ##fetch_status <> -1
begin
--bulk insert won't take a variable name, so make a sql and execute it instead:
set #sql = 'BULK INSERT Temp FROM ''' + #path + #filename + ''' '
+ ' WITH (
FIELDTERMINATOR = '','',
ROWTERMINATOR = ''\n'',
FIRSTROW = 2
) '
print #sql
exec (#sql)
fetch next from c1 into #path,#filename
end
close c1
deallocate c1
But the problem is I cannot use the command 'EXEC Master..xp_cmdShell' cause it was disabled by DBA's due to some security reasons, and they are not permitting me to use it. Is there any alternative command that I can use instead of 'xp_cmdShell' in the same script.
In this script near bulk insert command (set #sql = 'BULK INSERT Temp FROM ''' + #path + #filename + ''' '
+ ') I see only one table name 'Test', and how can I mention multiple table names in the Bulk insert command?
Any help please.
It's been a long time since I have had to do this, but this is how I used to do these kinds of things.
DECLARE #intFlag INT
SET #intFlag = 1
WHILE (#intFlag <=100)
BEGIN
PRINT #intFlag
declare #fullpath1 varchar(1000)
select #fullpath1 = '''\\FTP\' + convert(varchar, getdate()- #intFlag , 112) + '_your_file.csv'''
declare #cmd1 nvarchar(1000)
select #cmd1 = 'bulk insert [dbo].[your_table] from ' + #fullpath1 + ' with (FIELDTERMINATOR = ''\t'', FIRSTROW = 5, ROWTERMINATOR=''0x0a'')'
exec (#cmd1)
SET #intFlag = #intFlag + 1
END
GO
As you can tell, this is looping through a bunch of files with dates as file names. The first part of each file name was in this date format: convert(varchar, getdate()- #intFlag , 112)
I'm guessing your files have names that match some specific pattern.
SQl Server has a tool that does this for you. Goto to your SQL Server folder
Open SQL Server Import and Export Wizard.
Choose a Data Source Microsoft Excel
Select the Excel File. And following the steps

Putting Declare Variable in String (of a Bulk Insert)

trying to get an ETL package going which requires bulk inserting a bunch of .csv files off of a drive. Instead of manually having to scroll through the code and change the file path name for each insert (it increments with each month), would just like to declare the variable at the top.
Eg.
DECLARE #Month NVARCHAR(255)
SET #Month = 'November'
DECLARE #Year NVARCHAR(255)
SET #Year = '2019'
BULK INSERT #MonthlyMetrics
FROM '\\SomeServer\SomeFolder\Metrics_#Month_#Year.csv'
WITH
(
FIELDTERMINATOR = ','
, ROWTERMINATOR = '0x0a'
, FIRSTROW = 3
)
GO
There's a dozen of inserts like this where the only part of the file name that changes is the month. i.e. Metrics_November_2019.csv is that actual file name. Since the FROM is a string, not sure how to get the declared variable in there.
You can try using a dynamic SQL to load the data, only you will need to enable xp_cmdshell like this:
This turns on advanced options and is needed to configure xp_cmdshell
sp_configure 'show advanced options', '1';
RECONFIGURE
This enables xp_cmdshell
sp_configure 'xp_cmdshell', '1'
RECONFIGURE
After that you can load the data in your temp table:
DECLARE #dir varchar(300)
DECLARE #files table (FileName varchar(800));
DECLARE #filesCmd varchar(500);
DECLARE #filename varchar(100);
DECLARE #cmd_BulkInsert nvarchar(max);
SET #dir = '\\SomeServer\SomeFolder';
SET #filesCmd = 'DIR /b ' + #dir + ' | findstr csv';
INSERT INTO #files EXECUTE xp_cmdshell #filesCmd;
BEGIN TRY
DECLARE C_TABLE CURSOR LOCAL FORWARD_ONLY READ_ONLY STATIC FOR
SELECT FileName FROM #files WHERE NOT FileName IS NULL;
OPEN C_TABLE;
FETCH NEXT FROM C_TABLE INTO #filename;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #cmd_BulkInsert = N'
BULK INSERT #MonthlyMetrics
FROM '''+#dir+'\'+#filename+'''
WITH
(
FIELDTERMINATOR = '',''
,ROWTERMINATOR = ''0x0a''
,FIRSTROW = 3
)'
EXECUTE sp_executesql #cmd_BulkInsert;
FETCH NEXT FROM C_TABLE INTO #filename;
END
END TRY
BEGIN CATCH
SELECT
GETDATE()
,ERROR_LINE()
,ERROR_MESSAGE()
,ERROR_NUMBER()
,ERROR_STATE()
,ERROR_SEVERITY()
,#cmd_BulkInsert
END CATCH

DDL trigger to remove the article from the replication when it is altered

Using SQL Server 2008 for Transnational replication.
Some times my team folks altering the table during development before removing the table from subscription in the replication. So it leads to replication failure in the environment. To avoid that, planned to write a DDL trigger which will remove the table from subscription when it is getting altered.
Below is the trigger i have written to achieve the same.
CREATE TRIGGER RemoveArticleFromRepliction ON DATABASE
FOR DROP_TABLE
, ALTER_TABLE AS
BEGIN
SET NOCOUNT ON;
DECLARE #EventData XML = EVENTDATA();
DECLARE #TableName VARCHAR(255) = #EventData.value('(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(255)')
DECLARE #CMD VARCHAR(255) = 'IF EXISTS (SELECT 1 FROM SYS.TABLES WHERE NAME = ''' + #TableName + ''') EXEC sp_mck_DropSubscriptionArticle ''' + #TableName + ''''
EXEC #CMD
END
The trigger applied successfully in SQL server 2008.
Note: sp_mck_DropSubscriptionArticle is a custom procedure. the logic to remove the article from subscription is added in it.
When i execute the alter statement, i am getting the below error
Could not find stored procedure 'IF EXISTS (SELECT 1 FROM SYS.TABLES WHERE NAME = 'NOTE') EXEC sp_mck_DropSubscriptionArticle 'NOTE''.
Please help me resolve this issue or suggest me any other approach to fix this problem
Looks like you are missing the brackets after EXEC. Please try the below changed code
CREATE TRIGGER RemoveArticleFromRepliction ON DATABASE
FOR DROP_TABLE
, ALTER_TABLE AS
BEGIN
SET NOCOUNT ON;
DECLARE #EventData XML = EVENTDATA();
DECLARE #TableName VARCHAR(255) = #EventData.value('(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(255)')
DECLARE #CMD VARCHAR(255) = 'IF EXISTS (SELECT 1 FROM SYS.TABLES WHERE NAME = ''' + #TableName + ''') EXEC sp_mck_DropSubscriptionArticle ''' + #TableName + ''''
EXEC (#CMD)
END

SQL Server Exception handling in a cursor defined query

Here is the script I am using to run against all the databases on sql server but somehow the script stops when the database is in transition so all I want to do is the script needs to skip the database that is in transition and proceed with rest of the databases. Any help would be appreciated.
declare #name varchar(max)
SET #starttime = GETDATE()
Declare DB_cursor cursor for
SELECT Name
FROM sys.databases
WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb')
AND is_read_only = 0
AND is_in_standby = 0
AND state = 0
OPEN DB_cursor
FETCH NEXT FROM DB_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC(' use [' + #name + '] IF EXISTS (select name from sys.objects where name=''#Tablename'') UPDATE STATISTICS [' + #SchemaName + '].[' + #TableName +'](['+#StatsName+']) WITH FULLSCAN ')
FETCH NEXT FROM DB_cursor INTO #name
END
CLOSE DB_cursor
DEALLOCATE DB_cursor
Try:
DECLARE #sql NVARCHAR(MAX)
SET #sql = ' use [' + #name + '] IF EXISTS (select name from sys.objects where name=''#Tablename'') UPDATE STATISTICS [' + #SchemaName + '].[' + #TableName +'](['+#StatsName+']) WITH FULLSCAN ' )
EXEC sp_executesql #sql = #sql

Make copies of database

I have a database with all tables needed, on which is perfectly usable. But for test purposes, I need to make copies of the database for, lets say 100 times. (My application will loop on each database to execute some scripts).
The databases generated should bear different names of course. To use Backup/Restore or even Detach/Copy/Attach a 100 times is not do-able. So I would like to know if there's a script which can loop to copy/restore a database several times on different names?
Thanks
Ok found something that's working for me, by simple WHILE LOOP;
DECLARE #index int
DECLARE #dbName varchar(25)
declare #HRNET varchar(200)
declare #HRNET_LOG varchar(200)
declare #sql varchar(2000)
SET #index = 5
WHILE (#index < 200)
BEGIN
-- Construct db name and corresponding files name
SET #dbName = 'BDName' + Right('0000' + CONVERT(NVARCHAR, #index), 4)
set #MDF = '''C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL2008\MSSQL\DATA\' + #dbName + '.mdf'''
SET #LDF = '''C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL2008\MSSQL\DATA\' + #dbName + '_1.ldf'''
-- Restore db from backup bak file
SELECT #sql = 'RESTORE DATABASE ' + #dbName + '
FROM DISK = ''C:\DB Backup\DBName1919.bak''
WITH FILE = 1,
MOVE ''WEEKLY_UK_CO_E_REPORTING_Data'' TO ' + #MDF + ',
MOVE ''WEEKLY_UK_CO_E_REPORTING_Log'' TO ' + #LDF +
', NOUNLOAD, STATS = 10'
exec(#sql)
SET #index = #index + 1
END
GO
To retrieve the backup path location (MDF & LDF), just run the following;
RESTORE FILELISTONLY
FROM DISK = N'C:\DB Backup\DBName1919.bak'