Πώς κάνουμε μαζικά detach / attach βάσεις δεδομένων στον SQL Server

- Πώς επαναφέρουμε μία Oracle Database που βρίσκεται σε archive-log mode με RMAN Restore - 1 Δεκέμβριος 2025
- Πώς μπορούμε να συνδέσουμε SQL Server με άλλον SQL Server με τη χρήση Linked Server - 3 Νοέμβριος 2025
- Πώς απελευθερώνουμε δεσμευμένο χώρο από datafiles / tempfiles μίας βάσης δεδομένων της Oracle - 1 Σεπτέμβριος 2025
Κάποιες φορές θα χρειαστεί να μετακινήσουμε βάσεις δεδομένων στον SQL Server. Αυτή η διαδικασία γίνεται και με backup / restore είτε αλλάζοντας το status της βάσης σε offline στο άρθρο όμως θα ασχοληθούμε τις διαδικασίες του detach και attach. Στο άρθρο θα δούμε ένα script που δημιουργεί τις εντολές που ολοκληρώνουν αυτή την εργασία.
Για ποιους λόγους χρειάζεται να γίνει
Ο συνήθης λόγος είναι για να μεταφέρουμε τη βάση σε διαφορετικό instance ή ακόμα και διαφορετικό server. Από εκεί και πέρα μπορούμε να μεταφέρουμε τα αρχεία της βάσης σε ξεχωριστό δίσκο λόγω επιδόσεων και χώρων. Τέλος μπορούμε να κάνουμε attach μία βάση σε ένα instance πιο πρόσφατης έκδοσης αναβαθμίζοντας την.
Τι πρέπει να προσέξουμε
Με αυτή τη διαδικασία έχουμε κάποιους περιορισμούς. Ας αναλύσουμε τα πιο βασικά:
- Θα πρέπει μετά την μεταφορά των βάσεων να δημιουργηθούν τα logins και να συνδεθούν με τους χρήστες της κάθε βάσεις διότι χάνετε η σύνδεση αυτή κατά την μεταφορά.
- Η διαδικασία του attach γίνεται μόνο σε instance ίδιας έκδοσης με αυτή που έγινε το detach ή νεότερης
- Αν γίνει η βάση attach σε νεότερη έκδοση το compatibility level δεν αλλάζει από μόνο του πάρα την εκτέλεση της εντολής alter database compatibility.
- Όταν μεταφέρουμε μια βάση δεν μεταφέρονται και τα jobs μαζί της τα οποία πάντα είναι αποθηκευμένα στην συστεμική βάση msdb.
Η διαδικασία
Ο στόχος του script είναι να παράγει την εντολές για να κάνουμε detach και attach. Εκτελούμε τις εντολές detach στο instance με τις βάσεις που θέλουμε να μεταφέρουμε. Αφου ολοκληρωθεί μεταφέρουμε τα αρχεία των βάσεων. Τέλος συνδεόμαστε στο instance που θέλουμε να τις κάνουμε attach και εκτελούμε τα attach εντολές.
Παράδειγμα εντολών:
EXEC sp_detach_db @dbname = 'db_test' , @skipchecks = 'true';
EXEC sp_attach_db @dbname = 'db_test' ,@filename1 = 'C:\Program Files\Microsoft SQL Server\MSSQL15.SQL19\MSSQL\DATA\ddd.mdf' ,@filename2 = 'C:\Program Files\Microsoft SQL Server\MSSQL15.SQL19\MSSQL\DATA\fff_log.ldf'
Το script
Πριν την εκτέλεση του θα μπορούμε να ορίσουμε αν θα γίνει το attach στο ίδιο drive με την παράμετρο @Drive_New, αν θέλουμε μόνο μια συγκεκριμένη βάση με την παράμετρο @dbname και τέλος αν θέλουμε ή όχι και τις συστημικές βάσεις με τη παράμετρο @whichdb:
USE [master];
GO
DECLARE @database NVARCHAR(200) ,
@cmd NVARCHAR(1000) ,
@detach_cmd NVARCHAR(4000) ,
@attach_cmd NVARCHAR(4000) ,
@file NVARCHAR(1000) ,
@i INT ,
@whichdb INT=0,
@dbname nvarchar(200)='%%',
@Drive_Now nvarchar(10)='',
@Drive_New nvarchar(10)='';
create table #tempattach(attach_script varchar(max));
create table #tempdetach(detach_script varchar(max));
-- set 4 for only userdbs, 0 for all dbs
set @whichdb = 4
--if u want to attach db on new drive with same path uncomment with the correct drive letters
--set @Drive_Now = 'C:\' set @Drive_New = 'Z:\'
--uncomment if u pick only one DBname
--set @dbname = '%DBA%'
DECLARE dbname_cur CURSOR STATIC LOCAL FORWARD_ONLY
FOR
SELECT RTRIM(LTRIM([name]))
FROM sys.databases
WHERE database_id > @whichdb
and name like @dbname;
OPEN dbname_cur
FETCH NEXT FROM dbname_cur INTO @database
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @i = 1;
SET @attach_cmd =
'EXEC sp_attach_db @dbname = ''' + @database + '''' + CHAR(10);
-- Change skip checks to false if you want to update statistics before you detach.
SET @detach_cmd =
'EXEC sp_detach_db @dbname = ''' + @database
+ ''' , @skipchecks = ''true'';' + CHAR(10);
-- Get a list of files for the database
DECLARE dbfiles_cur CURSOR STATIC LOCAL FORWARD_ONLY
FOR
SELECT physical_name
FROM sys.master_files
WHERE database_id = DB_ID(@database)
ORDER BY [file_id];
OPEN dbfiles_cur
FETCH NEXT FROM dbfiles_cur INTO @file
WHILE @@FETCH_STATUS = 0
BEGIN
SET @attach_cmd = @attach_cmd + ' ,@filename'
+ CAST(@i AS NVARCHAR(10)) + ' = ''' + @file + ''''
+ CHAR(10);
SET @i = @i + 1;
FETCH NEXT FROM dbfiles_cur INTO @file
END
CLOSE dbfiles_cur;
DEALLOCATE dbfiles_cur;
insert into #tempattach values(REPLACE(@attach_cmd,@Drive_Now,@Drive_New));
insert into #tempdetach values(@detach_cmd);
FETCH NEXT FROM dbname_cur INTO @database
END
CLOSE dbname_cur;
DEALLOCATE dbname_cur;
select * from #tempdetach
select * from #tempattach
drop table #tempattach
drop table #tempdetach
Με το που εκτελέσουμε θα παραχθούν οι εντολές για το detach και attach όλων των βάσεων:


