💡 What Does This Stored Procedure Do?
This procedure:
1️⃣ Creates a .BAK backup file for the entire database locally.
- Filename includes timestamp:
MyDatabase_ddMMyyyy_HH_mm.bak
2️⃣ Loops through all user tables in the database.
- For each table:
- Checks if the remote server has a table named
TableName_Suffix.
- If it doesn't exist, → creates it (matching schema).
- If it exists, → clears existing data.
- Then → inserts all rows from the local table into the remote one.
✅ No need to specify each table manually.
✅ Supports SQL Authentication to the remote server.
✅ Handles schema differences automatically.
📌 Why Use It?
If you're managing data pipelines or DR (disaster recovery) scenarios where:
- You want local backups for restore points
- You also want to push all tables' data to another server (e.g., for reporting, BI, or standby)
- And you want to version the table names with suffixes (like a server or environment tag)
→ This single procedure automates the entire process!
🧭 Example Usage
✅ Backup MyDatabase to D:\SQL_Backups
✅ Copy all tables to the remote server 192.168.1.100, database RemoteDB
✅ Add suffix kartik to remote table names.
EXEC dbo.usp_BackupDatabaseAndAllTablesToRemote
@DatabaseName = 'MyDatabase',
@ServerSuffix = 'kartik',
@LocalBackupPath = 'D:\SQL_Backups\',
@RemoteServerName = '192.168.1.100',
@RemoteDatabase = 'RemoteDB',
@RemoteUser = 'sa',
@RemotePassword = 'YourPassword'
✅ The Complete T-SQL Procedure.
Here’s the full script you can deploy on your SQL Server:
CREATE OR ALTER PROCEDURE dbo.usp_BackupDatabaseAndAllTablesToRemote
@DatabaseName NVARCHAR(255),
@ServerSuffix NVARCHAR(100),
@LocalBackupPath NVARCHAR(500),
@RemoteServerName NVARCHAR(255),
@RemoteDatabase NVARCHAR(255),
@RemoteUser NVARCHAR(100) = NULL,
@RemotePassword NVARCHAR(100) = NULL
AS
BEGIN
SET NOCOUNT ON;
-- Step 1: Generate timestamped .bak filename
DECLARE @DatePart NVARCHAR(50) = REPLACE(CONVERT(CHAR(8), GETDATE(), 103), '/', '')
DECLARE @TimePart NVARCHAR(5) = REPLACE(CONVERT(CHAR(5), GETDATE(), 108), ':', '_')
DECLARE @FileName NVARCHAR(500) = @DatabaseName + '_' + @DatePart + '_' + @TimePart + '.bak'
DECLARE @FullBackupPath NVARCHAR(1000) = @LocalBackupPath + @FileName
-- Step 2: Backup the database to disk
DECLARE @BackupSQL NVARCHAR(MAX) = 'BACKUP DATABASE [' + @DatabaseName + '] TO DISK = N''' + @FullBackupPath + ''' WITH INIT'
EXEC (@BackupSQL)
PRINT '✔ Database backed up to: ' + @FullBackupPath
-- Step 3: Loop through all user tables
DECLARE @TableName NVARCHAR(255)
DECLARE table_cursor CURSOR FOR
SELECT TABLE_SCHEMA + '.' + TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG = @DatabaseName
OPEN table_cursor
FETCH NEXT FROM table_cursor INTO @TableName
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @TargetTable NVARCHAR(255) = REPLACE(@TableName, '.', '_') + '_' + @ServerSuffix
DECLARE @CreateTable NVARCHAR(MAX) = ''
DECLARE @Sql NVARCHAR(MAX) = ''
-- Build CREATE TABLE statement
SELECT @CreateTable = 'CREATE TABLE ' + QUOTENAME(@TargetTable) + ' ('
SELECT @CreateTable = @CreateTable + CHAR(10) +
QUOTENAME(c.name) + ' ' +
t.name +
CASE
WHEN t.name IN ('varchar', 'char', 'nvarchar', 'nchar') THEN '(' +
CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length AS VARCHAR) END + ')'
WHEN t.name IN ('decimal', 'numeric') THEN '(' + CAST(c.precision AS VARCHAR) + ',' + CAST(c.scale AS VARCHAR) + ')'
ELSE ''
END + ','
FROM sys.columns c
JOIN sys.types t ON c.user_type_id = t.user_type_id
WHERE c.object_id = OBJECT_ID(@TableName)
SET @CreateTable = LEFT(@CreateTable, LEN(@CreateTable)-1) + ')'
-- Step 3a: Create remote table if it doesn't exist
SET @Sql = '
IF NOT EXISTS (
SELECT 1 FROM OPENROWSET(
''SQLNCLI'',
''Server=' + @RemoteServerName + ';' +
ISNULL('UID=' + @RemoteUser + ';PWD=' + @RemotePassword + ';', '') + ''',
''SELECT TABLE_NAME FROM ' + @RemoteDatabase + '.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ''''' + @TargetTable + ''''''')
)
BEGIN
DECLARE @c NVARCHAR(MAX) = N''' + REPLACE(@CreateTable, '''', '''''') + '''
EXEC (''INSERT INTO OPENROWSET(''''SQLNCLI'''', ''''Server=' + @RemoteServerName + ';' +
ISNULL('UID=' + @RemoteUser + ';PWD=' + @RemotePassword + ';', '') + '''',
''''SET FMTONLY OFF; EXEC('''''''' + @c + '''''''') ON ' + @RemoteDatabase + '''') SELECT 1'')
END
'
EXEC(@Sql)
-- Step 3b: Delete existing remote data
SET @Sql = '
EXEC (''DELETE FROM OPENROWSET(''''SQLNCLI'''', ''''Server=' + @RemoteServerName + ';' +
ISNULL('UID=' + @RemoteUser + ';PWD=' + @RemotePassword + ';', '') + '''',
''''SELECT * FROM ' + @RemoteDatabase + '.dbo.' + @TargetTable + '''')'')'
EXEC(@Sql)
-- Step 3c: Insert local data into remote table
SET @Sql = '
INSERT INTO OPENROWSET(
''SQLNCLI'',
''Server=' + @RemoteServerName + ';' +
ISNULL('UID=' + @RemoteUser + ';PWD=' + @RemotePassword + ';', '') + ''',
''SELECT * FROM ' + @RemoteDatabase + '.dbo.' + @TargetTable + ''')
SELECT * FROM ' + @TableName
EXEC(@Sql)
PRINT '✔ Copied: ' + @TableName + ' → ' + @TargetTable
FETCH NEXT FROM table_cursor INTO @TableName
END
CLOSE table_cursor
DEALLOCATE table_cursor
PRINT '✅ All tables copied successfully.'
END
✅ Benefits
- Fully automated – no need to list tables manually
- Disaster recovery ready – local .bak backup for safe restores
- Remote replication – easy table-level replication to another server
- Flexible naming – append environment/server suffix for clarity
If you found this useful, feel free to share or comment, and let's discuss more SQL Server automation ideas!
Join the conversation! Your thoughts help the community grow.