O tym jak Power Shell utworzył nam bazy z listy w pliku :)

Ostatnio podczas pracy pojawiła się potrzeba utworzenia kilkudziesięciu baz danych na serwerze SQL. Zleceniodawca podesłał nam listę baz w pliku xls.
Pokażę jak łatwo można zautomatyzować tworzenie baz bez konieczności klikania przez cały dzień w kreatorze baz danych.

Najpierw kopiujemy listę baz do pliku testowego C:\TEMP\LISTA.TXT. W przykładzie wpisałem trzy bazy jednak może być ich znacznie więcej.

BAZA_DANYCH_01
BAZA_DANYCH_02
BAZA_DANYCH_03

Do utworzenia skryptu do utworzenia baz użyjemy PowerShell'a.
najpierw zaczytujemy listę do zmiennej $LISTA

$dblist = get-content c:\temp\lista.txt
$dblist

BAZA_DANYCH_01
BAZA_DANYCH_02
BAZA_DANYCH_03

Następnie użyjemy składni foreach. Zaczytuje ona kolejno dane z pliku i wykonuje na nich podane polecenie:

foreach ($dbname in $dblist) {
write-host "ALTER DATABASE [$dbname]"
}

Baza danych: [BAZA_DANYCH_01]
Baza danych: [BAZA_DANYCH_02]
Baza danych: [BAZA_DANYCH_03]

Tworzymy skrypt TSQL do tworzenia bazy danych (przykładowo TESTDB01) :

CREATE DATABASE [TESTDB01]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'TESTDB01', FILENAME = N'C:\SQLData\TESTDB01.mdf' , SIZE = 262144KB , MAXSIZE = 512000KB , FILEGROWTH = 131072KB )
LOG ON
( NAME = N'TESTDB01_log', FILENAME = N'C:\SQLData\TESTDB01_log.ldf' , SIZE = 131072KB , MAXSIZE = 102400KB , FILEGROWTH = 65536KB )
GO

W powyższym skrypcie zmieniamy nazwę bazy na zmienną $DBNAME i wklejamy go do naszego skryptu PowerShell'owego


$dblist = get-content c:\temp\lista.txt
foreach ($dbname in $dblist)
{
write-host "CREATE DATABASE [$dbname]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'$dbname', FILENAME = N'C:\SQLData\$dbname.mdf' , SIZE = 262144KB , MAXSIZE = 512000KB , FILEGROWTH = 131072KB )
LOG ON
( NAME = N'$dbname_log', FILENAME = N'C:\SQLData\$dbname_log.ldf' , SIZE = 131072KB , MAXSIZE = 102400KB , FILEGROWTH = 65536KB )
GO
"
}

Wykonujemy skrypt w wyniku którego otrzymujemy skrypt SQL do utworznia trzech baz

CREATE DATABASE [BAZA_DANYCH_01]
 CONTAINMENT = NONE
 ON  PRIMARY
( NAME = N'BAZA_DANYCH_01', FILENAME = N'C:\SQLData\BAZA_DANYCH_01.mdf' , SIZE = 262144KB , MAXSIZE = 512000KB , FILEGROWTH = 131072KB )
 LOG ON
( NAME = N'', FILENAME = N'C:\SQLData\.ldf' , SIZE = 131072KB , MAXSIZE = 102400KB , FILEGROWTH = 65536KB )
GO

CREATE DATABASE [BAZA_DANYCH_02]
 CONTAINMENT = NONE
 ON  PRIMARY
( NAME = N'BAZA_DANYCH_02', FILENAME = N'C:\SQLData\BAZA_DANYCH_02.mdf' , SIZE = 262144KB , MAXSIZE = 512000KB , FILEGROWTH = 131072KB )
 LOG ON
( NAME = N'', FILENAME = N'C:\SQLData\.ldf' , SIZE = 131072KB , MAXSIZE = 102400KB , FILEGROWTH = 65536KB )
GO

CREATE DATABASE [BAZA_DANYCH_03]
 CONTAINMENT = NONE
 ON  PRIMARY
( NAME = N'BAZA_DANYCH_03', FILENAME = N'C:\SQLData\BAZA_DANYCH_03.mdf' , SIZE = 262144KB , MAXSIZE = 512000KB , FILEGROWTH = 131072KB )
 LOG ON
( NAME = N'', FILENAME = N'C:\SQLData\.ldf' , SIZE = 131072KB , MAXSIZE = 102400KB , FILEGROWTH = 65536KB )
GO

Jest jeszcze druga metoda która wykorzystuje moduł SqlPS. Wykorzystuje ona składnie
set-location SQLSERVER:\SQL
i uruchomienie jej powoduje błąd

set-location : Cannot find drive. A drive with the name 'SQLSERVER' does not exist.
At line:1 char:1
+ set-location SQLSERVER:\SQL
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (SQLSERVER:String) [Set-Location], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.SetLocationCommand

Przy próbie importu modułu również otrzymamy błąd:

Import-Module SQLServer;

Import-Module : File C:\Program Files (x86)\Microsoft SQL Server\150\Tools\PowerShell\Modules\SqlPS\SqlServer.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ Import-Module SqlServer;
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : SecurityError: (:) [Import-Module], PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess,Microsoft.PowerShell.Commands.ImportModuleCommand

W większości przypadków jednak domyślne polisy systemu zabezpieczają przed wykonywaniem skryptów z nich użyciem, ale można to obejść usuwając klucz
ExecutionPolicy = RemoteSigned
z rejestru Komputer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.SqlServer.Management.PowerShell.sqlps150

Przy ponownym uruchomieniu Power Shella nie powinno być już błędu.

Można też skorzystać z polecenia zmieniającego ustawienia

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine

Execution Policy Change
The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose
you to the security risks described in the about_Execution_Policies help topic at
https:/go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "N"): A

Teraz możemy zaimportować moduł i wykonać polecenie Set-Location:

set-location SQLSERVER:\SQL

PS SQLSERVER:\SQL> dir

MachineName
-----------
DELL_MICEK1968

Widać że moduł działa prawidłowo

Wykorzystując polecenie FOREACH tworzymy skrypt:

$dblist = get-content c:\temp\lista.txt
$inst = "localhost"
foreach ($dbname in $dblist) {
set-location SQLSERVER:\SQL\$inst
$db = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Database -ArgumentList $inst, $dbname
$db.Create()
$db.SetOwner("sa")
$db.BrokerEnabled = $false
$db.alter()
set-location D:\
write-host "utworzono bazę danych $dbname"
}

W wyniku jego zostaną utworzone trzy bazy danych zapisane w pliku LISTA.TXT a w power shellu otrzymamy komunikat:

utworzono baz danych BAZA_DANYCH_01
utworzono baz danych BAZA_DANYCH_02
utworzono baz danych BAZA_DANYCH_03
Ten wpis został opublikowany w kategorii Microsoft SQL, SQL PowerShell. Dodaj zakładkę do bezpośredniego odnośnika.

Dodaj komentarz