একাধিক ডাটাবেস সি: ডি থেকে: একবারে সরাবেন


17

আমার সি সি: ড্রাইভ, একটি দ্রুত এসএসডি, এর মধ্যে প্রায় 32 গিগাবাইট গ্রাহক 323 ডাটাবেস সহ এসকিউএল সার্ভার 2008 আর 2 রয়েছে।

যেহেতু আমি আমার সি: ড্রাইভে কিছু জায়গা দাবি করতে চাই, তাই আমি তাদের আমার ডি: ড্রাইভে স্থানান্তর করতে চাই।

আমি এই এমএসডিএন নিবন্ধটি পেয়েছি , তবে এটি কেবল একটি ডাটাবেস স্থানান্তরিত করার পদ্ধতি বলে মনে হচ্ছে।

আমার সমস্ত ডাটাবেসগুলি একবারে সরানোর জন্য কোনও স্বয়ংক্রিয় উপায় বা স্ক্রিপ্ট আছে?

উত্তর:


20

আমি এই ধরণের কাজের জন্য পাওয়ারশেল ব্যবহার করি। আসলে, আমি পাওয়ারশেল তৈরি করার জন্য পাওয়ারশেল ব্যবহার করি কারণ আমার কাছে একটি স্ক্রিপ্ট রয়েছে যা আমার ডাটাবেসগুলির মধ্য দিয়ে লুপ হয়ে যাবে এবং আমার চূড়ান্ত সরানো স্ক্রিপ্ট তৈরি করবে। আপনাকে একবারে প্রতিটি ডাটাবেস সরিয়ে নিতে হবে, তবে এটি আপনাকে কমপক্ষে 90% কাজের স্ক্রিপ্ট করতে সহায়তা করবে।

#load SMO
Add-PSSnapin SqlServerCmdletSnapin100
Add-PSSnapin SqlServerProviderSnapin100
#Added line if using SQL Server 2012 or later
Import-module SQLPS
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null

#Create server object and output filename 
$server = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server "localhost"
$outputfile=([Environment]::GetFolderPath("MyDocuments"))+"\FileMover.ps1"

#set this for your new location
$newloc="X:\NewDBLocation"

#get your databases
$db_list=$server.Databases

#build initial script components
"Add-PSSnapin SqlServerCmdletSnapin100" > $outputfile
"Add-PSSnapin SqlServerProviderSnapin100" >> $outputfile
"Import-Module SQLPS" >> $outputfile 
"[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') `"localhost`" | out-null" >> $outputfile
"`$server = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server " >> $outputfile

foreach($db_build in $db_list)
{
    #only process user databases
    if(!($db_build.IsSystemObject))
    {
        #script out all the file moves
        "#----------------------------------------------------------------------" >> $outputfile
        "`$db=`$server.Databases[`""+$db_build.Name+"`"]" >> $outputfile

        $dbchange = @()
        $robocpy =@()
        foreach ($fg in $db_build.Filegroups)
        {
            foreach($file in $fg.Files)
            {
                $shortfile=$file.Filename.Substring($file.Filename.LastIndexOf('\')+1)
                $oldloc=$file.Filename.Substring(0,$file.Filename.LastIndexOf('\'))
                $dbchange+="`$db.FileGroups[`""+$fg.Name+"`"].Files[`""+$file.Name+"`"].Filename=`"$newloc`\"+$shortfile+"`""
                $robocpy+="ROBOCOPY `"$oldloc`" `"$newloc`" $shortfile /copyall /mov"

            }
        }

        foreach($logfile in $db_build.LogFiles)
        {
            $shortfile=$logfile.Filename.Substring($logfile.Filename.LastIndexOf('\')+1)
            $oldloc=$logfile.Filename.Substring(0,$logfile.Filename.LastIndexOf('\'))
            $dbchange+="`$db.LogFiles[`""+$logfile.Name+"`"].Filename=`"$newloc`\"+$shortfile+"`""
            $robocpy+="ROBOCOPY `"$oldloc`" `"$newloc`" $shortfile /copyall /mov"
        }

        $dbchange+="`$db.Alter()" 
        $dbchange+="Invoke-Sqlcmd -Query `"ALTER DATABASE ["+$db_build.Name+"] SET OFFLINE WITH ROLLBACK IMMEDIATE;`" -Database `"master`"" 

        $dbchange >> $outputfile
        $robocpy >> $outputfile

        "Invoke-Sqlcmd -Query `"ALTER DATABASE ["+$db_build.Name+"] SET ONLINE;`" -Database `"master`""  >> $outputfile
    }
}

আউটপুটটি আপনার মাই ডকুমেন্টস ফোল্ডারে একটি ফাইলমোভার.পিএস 1 স্ক্রিপ্ট হবে যা দেখতে এরকম কিছু দেখাচ্ছে:

    Add-PSSnapin SqlServerCmdletSnapin100
    Add-PSSnapin SqlServerProviderSnapin100
    Import-Module SQLPS
    [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') "localhost" | out-null
    $server = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server 
    #----------------------------------------------------------------------
    $db=$server.Databases["AdventureWorks2012"]
    $db.FileGroups["PRIMARY"].Files["AdventureWorks2012_Data"].Filename="X:\NewDBLocation\AdventureWorks2012_Data.mdf"
    $db.LogFiles["AdventureWorks2012_Log"].Filename="X:\NewDBLocation\AdventureWorks2012_log.ldf"
    $db.Alter()
    Invoke-Sqlcmd -Query "ALTER DATABASE [AdventureWorks2012] SET OFFLINE WITH ROLLBACK IMMEDIATE;" -Database "master"
    ROBOCOPY "C:\DBData" "X:\NewDBLocation" AdventureWorks2012_Data.mdf /copyall /mov
    ROBOCOPY "C:\DBFiles\Log" "X:\NewDBLocation" AdventureWorks2012_log.ldf /copyall /mov
    Invoke-Sqlcmd -Query "ALTER DATABASE [AdventureWorks2012] SET ONLINE;" -Database "master"
    #----------------------------------------------------------------------
    $db=$server.Databases["AdventureWorks2012DW"]
    $db.FileGroups["PRIMARY"].Files["AdventureWorksDW2012_Data"].Filename="X:\NewDBLocation\AdventureWorksDW2012_Data.mdf"
    $db.LogFiles["AdventureWorksDW2012_Log"].Filename="X:\NewDBLocation\AdventureWorks2012DW_log.ldf"
    $db.Alter()
    Invoke-Sqlcmd -Query "ALTER DATABASE [AdventureWorks2012DW] SET OFFLINE WITH ROLLBACK IMMEDIATE;" -Database "master"
    ROBOCOPY "C:\DBData" "X:\NewDBLocation" AdventureWorksDW2012_Data.mdf /copyall /mov
    ROBOCOPY "C:\DBData" "X:\NewDBLocation" AdventureWorks2012DW_log.ldf /copyall /mov
    Invoke-Sqlcmd -Query "ALTER DATABASE [AdventureWorks2012DW] SET ONLINE;" -Database "master"

...

আদেশ সহকারে

  • স্ক্রিপ্টটি সমস্ত ফাইল, তাদের উত্সের অবস্থান নির্বিশেষে একই গন্তব্যে নিয়ে যায়। কাস্টম অবস্থানের পথগুলির জন্য আপনাকে টুইঙ্ক করতে হবে।
  • স্ক্রিপ্টটি সার্ভারে চালানোর জন্য ডিজাইন করা হয়েছে যাতে আপনার ফাইলগুলি সরানো দরকার (লোকালহোস্টের সমস্ত ব্যবহার দেখুন ')। আপনি যদি এটিকে দূর থেকে চালান তবে লোকালহোস্টটি আপনার উদাহরণের নামের সাথে প্রতিস্থাপন করুন।
  • আপনি এটি হিসাবে চালিত ব্যবহারকারীর এসকিউএল সার্ভার ফাইল নাম তথ্য আপডেট করার জন্য এবং ফাইলগুলি সরানোর জন্য উভয় পদক্ষেপের সাথে জড়িত সমস্ত ফোল্ডারের পাথের অ্যাক্সেসের প্রয়োজন রয়েছে।
  • .SetOffline () এবং .SetOnline পদ্ধতিগুলির ফানকি প্রকৃতির কারণে আমি অফলাইন / অনলাইন সম্পাদনের জন্য ইনভোক এসকিউএলসিএমডি ব্যবহার করি। আমি এটি আরও নির্ভরযোগ্য বলে মনে করেছি।

@ মাইকফাল আমি দেখেছি আপনি সম্পাদনাটি অনুমোদিত করেছেন। যেহেতু প্রশ্নটি ২০০৮-এর সাথে ট্যাগ করা হয়েছে তাতে সংযোজনটি আরও সুস্পষ্ট হওয়া উচিত না (সাহসী বা কিছু)? (আমার কোনও ধারণা নেই, তবে আমি অনুমান করছি যে এটি ২০১২ ব্যতীত অন্য কোনও সংস্করণে কাজ করবে না বা কিছু ভঙ্গ করবে)।
ypercubeᵀᴹ

1
আমি সে সম্পর্কে ভেবেছিলাম এবং এটিকে এসকিউএল সার্ভার ২০১২ আর 2 এ চালিয়েছি - এটি অ্যাড-পিএসএসএনপিন স্কেলসার্ভারস্মিলেটলেটস্নাপিন ১০০ সেমিডিলেটগুলির সাথে ত্রুটি ছুঁড়ে ফেলেছে তবে আপনি যতক্ষণ না স্ক্রিপ্টের মূল অংশের আগে ইম্পোর্ট-মডিউল এসকিউএলপিএস অন্তর্ভুক্ত করবেন ততক্ষণ প্রক্রিয়াটি করে প্রক্রিয়া চলমান। প্রযুক্তিগতভাবে এটির চারপাশে পরীক্ষা করার ক্ষেত্রে আরও ভাল ত্রুটি হওয়া উচিত, তবে আমি এটি অনুধাবন করেছি যে অন্য কেউ যদি সম্ভবতঃ আমদানি-মডিউল এসকিউএলপিএস প্রয়োজনে খুঁজে না পেল তবে তাদের সহায়তা করা এটির জন্য একটি ভাল দ্রুত সম্পাদনা হবে they নতুন সংস্করণ.
চাদ রেক্সিন

1
অসংখ্য ধন্যবাদ. ছোট সমস্যা যদিও। রবোকপি ফাইলের নামগুলি এখানে উদ্ধৃত করা হয়নি .. আপনি যদি ব্যবহারকারী ব্যবহার করে ডেটাবেসগুলির নাম ফাঁকা দিয়ে তৈরি করেন তবে এটি ঠিক কাজ করে না।
টিম ব্রিগহাম

7

আপনি পরিবর্তিত ডাটাবেস ফাইল বা ডিটাচ / সংযুক্তি পদ্ধতিগুলি ব্যবহার করতে পারেন।

দ্রষ্টব্য: উভয়ের জন্য কিছু ডাউনটাইম প্রয়োজন হবে, তাই রক্ষণাবেক্ষণ উইন্ডোর সময়ও করতে হবে to

এটি ধরে নিয়েছে যে নতুন ড্রাইভে যেমন সি: \ ডেটা। এবং ডি: \ ডেটাতে আপনার একই ডিরেক্টরি কাঠামো রয়েছে।

- পরিবর্তিত পদ্ধতি (পছন্দসই একটি) দিয়ে অল্টার ডাটাবেস ব্যবহার করে

SET NOCOUNT ON

DECLARE @datafile VARCHAR(255)
    ,@logfile VARCHAR(255)
    ,@dbid TINYINT
    ,@SQLText VARCHAR(max)
    ,@dbname VARCHAR(255)
    ,@sqltext1 VARCHAR(max)
    ,@SQLText2 VARCHAR(max)

--2. Prepare for modify
IF EXISTS (
        SELECT 1
        FROM tempdb..sysobjects
        WHERE NAME LIKE '%#filetable%'
        )
BEGIN
    DROP TABLE #filetable
END

CREATE TABLE #filetable (
    mdf VARCHAR(255)
    ,ldf VARCHAR(255)
    ,dbid TINYINT
    ,dbname VARCHAR(100)
    ,fileid TINYINT
    ,logicalname SYSNAME
    )

--
INSERT #filetable (
    mdf
    ,dbid
    ,fileid
    ,logicalname
    )
SELECT physical_name
    ,database_id
    ,data_space_id
    ,NAME
FROM sys.master_files
WHERE data_space_id = 1

INSERT #filetable (
    ldf
    ,dbid
    ,fileid
    ,logicalname
    )
SELECT physical_name
    ,database_id
    ,data_space_id
    ,NAME
FROM sys.master_files
WHERE data_space_id = 0

UPDATE u
SET u.dbname = s.NAME
FROM #filetable u
INNER JOIN master..sysdatabases s ON u.dbid = s.dbid

UPDATE #filetable
SET mdf = replace(mdf, 'C:', 'D:')
    ,ldf = replace(ldf, 'C:', 'D:')
FROM #filetable

SELECT @dbid = min(dbid)
FROM #filetable
WHERE dbid > 4

WHILE @dbid IS NOT NULL
BEGIN
    SELECT @SQLText = 'alter database [' + dbname + '] MODIFY FILE (Name = ' + logicalname + ' , FileName = N''' + ldf + ''');'
    FROM #filetable
    WHERE dbid = convert(VARCHAR, @dbid)
        AND fileid = 0 -- Log file

    PRINT @SQLText

    --Exec(@SQLText)
    SELECT @SQLText2 = 'alter database [' + dbname + '] MODIFY FILE (Name = ' + logicalname + ' , FileName = N''' + mdf + ''');'
    FROM #filetable
    WHERE dbid = convert(VARCHAR, @dbid)
        AND fileid = 1 -- data file

    PRINT @SQLText2

    --Exec(@SQLText)
    SELECT @dbid = min(dbid)
    FROM #filetable
    WHERE dbid > 4
        AND dbid > @dbid
END

--- ওল্ড ডিচাচ / অ্যাটাচ পদ্ধতি ব্যবহার করে (পছন্দসই নয়, তবে এখনও লোকেরা এটি ব্যবহার করে .. দুর্ভাগ্যক্রমে আমি সম্প্রতি এটি একটি NON প্রোড সার্ভারে ব্যবহার করেছি)।

DECLARE @datafile VARCHAR(255)
    ,@logfile VARCHAR(255)
    ,@dbid TINYINT
    ,@SQLText VARCHAR(8000)
    ,@dbname VARCHAR(255)
    ,@SQLText2 VARCHAR(8000)

--2. Detach All Local Databases and prepare for Attach
IF EXISTS (
        SELECT 1
        FROM tempdb..sysobjects
        WHERE NAME LIKE '%#filetable%'
        )
BEGIN
    DROP TABLE #filetable
END

CREATE TABLE #filetable (
    mdf VARCHAR(255)
    ,ldf VARCHAR(255)
    ,dbid TINYINT
    ,dbname VARCHAR(100)
    ,fileid TINYINT
    )

--
INSERT #filetable (
    mdf
    ,dbid
    ,fileid
    )
SELECT physical_name
    ,database_id
    ,data_space_id
FROM sys.master_files
WHERE data_space_id = 1

INSERT #filetable (
    ldf
    ,dbid
    ,fileid
    )
SELECT physical_name
    ,database_id
    ,data_space_id
FROM sys.master_files
WHERE data_space_id = 0

UPDATE u
SET u.dbname = s.NAME
FROM #filetable u
INNER JOIN master..sysdatabases s ON u.dbid = s.dbid

UPDATE #filetable
SET mdf = replace(mdf, 'C:', 'D:')
    ,ldf = replace(ldf, 'C:', 'D:')
FROM #filetable

SELECT @dbid = min(dbid)
FROM #filetable
WHERE dbid > 4

WHILE @dbid IS NOT NULL
BEGIN
    SELECT @SQLText = 'alter database [' + dbname + ']'
    FROM #filetable
    WHERE dbid = convert(VARCHAR, @dbid)

    SELECT @SQLText = @SQLText + CHAR(10) + ' set single_user with rollback immediate;'

    SELECT @SQLText = @SQLText + CHAR(10) + ' exec master..sp_detach_db ' + dbname
    FROM #filetable
    WHERE dbid = convert(VARCHAR, @dbid)

    PRINT @SQLText

    --Exec(@SQLText)
    SELECT @SQLText2 = 'exec master..sp_attach_db ''' + dbname + ''''
    FROM #filetable
    WHERE dbid = @dbid

    SELECT @SQLText2 = @SQLText2 + ',''' + mdf + ''''
    FROM #filetable
    WHERE dbid = @dbid
        AND mdf IS NOT NULL

    SELECT @SQLText2 = @SQLText2 + ',''' + ldf + ''''
    FROM #filetable
    WHERE dbid = @dbid
        AND ldf IS NOT NULL

    PRINT @SQLText2

    --Exec(@SQLText)
    SELECT @dbid = min(dbid)
    FROM #filetable
    WHERE dbid > 4
        AND dbid > @dbid
END

DROP TABLE #filetable

6

আমি একাধিক ডিবি করতে একবারে জানতে পারি যে একাধিক ডিবি'র জন্য একবারে চালনাটি হবে script

ALTER DATABASE database_nameA SET OFFLINE WITH ROLLBACK IMMEDIATE;
ALTER DATABASE database_nameB SET OFFLINE WITH ROLLBACK IMMEDIATE;
ALTER DATABASE database_nameC SET OFFLINE WITH ROLLBACK IMMEDIATE;
-------

এখানে আপনি ফাইলগুলি ম্যানুয়ালি সরাতে পারেন, বা এটি করার জন্য একটি স্ক্রিপ্ট লিখতে পারেন। সম্ভবত এক্সপি_সিএমডি শেল বা কিছু সরঞ্জাম ব্যবহার করা। সম্ভবত হাতে হাতে ফাইলগুলি সরানো সম্ভবত আরও সহজ। এগুলির একটি গোছা চিহ্নিত করুন, তারপরে টানুন এবং ফেলে দিন।

-------
ALTER DATABASE database_nameA MODIFY FILE ( NAME = logical_name, FILENAME = 'new_path\os_file_name' );
ALTER DATABASE database_nameB MODIFY FILE ( NAME = logical_name, FILENAME = 'new_path\os_file_name' );
ALTER DATABASE database_nameC MODIFY FILE ( NAME = logical_name, FILENAME = 'new_path\os_file_name' );

ALTER DATABASE database_nameA SET ONLINE;
ALTER DATABASE database_nameB SET ONLINE;
ALTER DATABASE database_nameC SET ONLINE;

অবশ্যই আপনি যদি ডেটা ফাইল এবং লগ ফাইলটি সরান তবে আপনাকে অবশ্যই নিশ্চিত করতে হবে যে আপনি প্রতিটি অংশের জন্য মোডাইফাই ফাইলটি করছেন।


0
------------------------------
--erezbensimon@gmail.com - July 2016


use master;
go 

SET NOCOUNT ON

print '----------------------------------------------------------------------------------'
print '--Script for Moving Multiple database files to a new drive / ' + CONVERT(varchar(256),getdate() )
print '----------------------------------------------------------------------------------'
print ''


DECLARE @dbname nvarchar(128)
DECLARE @DestPath nvarchar(256)


--Set here the new destination path of the file
set @DestPath =  'T:\Data\'

------------------------------------------------
--Filter: HD Databases
------------------------------------------------
DECLARE DBList_cursor CURSOR FOR 

Select name from sys.databases

--where name like '<FIlter Something>'

----------------------------------------------

OPEN DBList_cursor

FETCH NEXT FROM DBList_cursor 
 INTO @dbname

WHILE @@FETCH_STATUS = 0
BEGIN

  declare @output_script varchar(max) --Output of the generated script
  declare @mdf_orig_path nvarchar(256) --Original datbase file path
  declare @cmdstring nvarchar(256) --Command String
  declare @CursorDeclare varchar(max) --Cursor declaration command
  declare @Originalfilename varchar(max) -- local @CursorDeclare command
  declare @filename varchar(max) -- local @CursorDeclare command
  declare @LogicalFileaame varchar(max) -- Logical FileName

  --Set null into @output script
  set @output_script=''
  --Generate Databse Cursor declaration command
  set @CursorDeclare='DECLARE DBFiles_cursor CURSOR FOR select [filename], [name] from '+ @dbname + '.sys.sysfiles'
  --Cursor Declaration
  execute (@CursorDeclare) 


  OPEN DBFiles_cursor
  FETCH NEXT FROM DBFiles_cursor INTO @filename, @LogicalFileaame

  --For RollBack Option
  select @Originalfilename = @filename

  --Modify Physical FileName
  if (@filename like '%.mdf') begin 
         select @mdf_orig_path = @filename
          IF(CHARINDEX('\', @filename) > 0)
          select @filename = RIGHT(@filename, CHARINDEX('\', REVERSE(@filename)) -1) 

         select @filename = @DestPath + @filename
         select @cmdstring = ' ''copy' + ' ' + '"'+ @mdf_orig_path + '"' + ' ' + '"' + @filename +'"' + ''''
  --Get Logical FileNAme


  end




print CHAR(10)
print '-----------------------------------------'
print  @dbname 
print '-----------------------------------------'
print CHAR(10)
print 'print  ''Start'' + CONVERT(varchar(256), getdate() ) '
print '---Offline Database' + @dbname      
print 'ALTER DATABASE ' + @dbname + ' SET OFFLINE WITH ROLLBACK IMMEDIATE' + CHAR(10) + 'GO'
print 'exec master..xp_cmdshell' + ' ' + @cmdstring + CHAR(10)
print '--For RollBack Use this:ALTER DATABASE ' + @dbname +' MODIFY FILE ( NAME =' + @LogicalFileaame +', FILENAME =' + @Originalfilename + ')' + CHAR(10)
print 'ALTER DATABASE ' + @dbname +' MODIFY FILE ( NAME =' + @LogicalFileaame +', FILENAME =' + '''' + @DestPath + @dbname + '.mdf'' )' +CHAR(10)


print '---ONline Database' + @dbname
print 'ALTER DATABASE ' + @dbname + ' SET ONLINE WITH
ROLLBACK IMMEDIATE
GO' 

  WHILE @@FETCH_STATUS = 0
  BEGIN   
   set @output_script=@output_script+' (FILENAME = '''+ @filename +'''),' 
      FETCH NEXT FROM DBFiles_cursor INTO @filename, @LogicalFileaame
  END

set @output_script=SUBSTRING(@output_script,0,len(@output_script))

CLOSE DBFiles_cursor
DEALLOCATE DBFiles_cursor

FETCH NEXT FROM DBList_cursor 
INTO @dbname

END 


CLOSE DBList_cursor
DEALLOCATE DBList_cursor

আপনার কোডটি (=> dba.stackexchange.com/help/formatting ) ফর্ম্যাট করা উচিত এবং প্রশ্নটি কীভাবে এড়ানো যায় তা ব্যাখ্যা করার জন্য কিছু শব্দ যুক্ত করতে হবে ... (=> dba.stackexchange.com/help/how-to-answer )
জুলিয়েন ভাওয়াসিউর

0

এই স্ক্রিপ্টটি আপনি চালাতে পারেন এমন বিবৃতিগুলির একটি ব্যাচকে ফিরিয়ে দেবে।

SELECT d.name as db, f.name, physical_name, f.state_desc,
'ALTER DATABASE ['+d.name+'] MODIFY FILE (name='''+f.name+''' ,filename='''+replace(physical_name,'C:\database','D:\whatever')+'''); ' as DetachCommand,
'ALTER DATABASE ['+d.name+'] SET ONLINE' as ReattachCommand
from sys.master_files f 
inner join sys.databases d on d.database_id=f.database_id
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.