SQL objektumok scriptelése Powershellben

Azt már mindenki tudja, h PS-ben lehet kiválóan scriptet generálni a SQL entitásokról a Script() metódus segítségével. Felvetődött egy kérdés vkiben, hogy hogyan lehet csak DB sémát backupolni, és felvetődött erre a Powershell, meg a get-contentitem|%{$_.Script()}, mint alapgondolat. Ja, ez ezt adja vissza egy új táblámra:

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[KeynoteDaily](
        [day] [date] NOT NULL,
        [site] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
        [measurements] [smallint] NULL,
        [failures] [smallint] NULL,
        [contenterrors] [smallint] NULL,
        [availability_wc] [real] NULL,
        [availability_woc] [real] NULL,
        [errors] [varchar](1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
        [loadtime] [smalldatetime] NULL,
        [comment] [varchar](2000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]

Szóval jól néz ki, nem? Nem. addig néz ki jól, amíg nem jut eszembe, hogy van primary key is a táblán. Meg még további indexek. Amiket persze megint ki lehet scriptelni: ˘

%{$_.Indexes}|%{$_.script()}

Meg még ki tudja, mi marad ki. Na mindegy, tuti megoldást nem tudok, de ez olyan lámának tűnt, hogy elkezdtem nézegetni a metódusokat, és találtam egy olyat, hogy EnumScript():

PS > gci |%{$_.EnumScript()}
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[KeynoteDaily](
        [day] [date] NOT NULL,
        [site] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
        [measurements] [smallint] NULL,
        [failures] [smallint] NULL,
        [contenterrors] [smallint] NULL,
        [availability_wc] [real] NULL,
        [availability_woc] [real] NULL,
        [errors] [varchar](1000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
        [loadtime] [smalldatetime] NULL,
        [comment] [varchar](2000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
 CONSTRAINT [PK_KeynoteDaily] PRIMARY KEY CLUSTERED
(
        [site] ASC,
        [day] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [ix_test] ON [dbo].[KeynoteDaily]
(
        [failures] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON,
ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [ix_test2] ON [dbo].[KeynoteDaily]
(
        [measurements] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON,
ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

Vagyis ő megcsinálja nekünk a rekurziót. Szerintem aranyos kényelmi szolgáltatás.
Ja, a fentiekhez a teljes path a következő volt: PS SQLSERVER:\SQL\MYCOMPUTER\DENALI\Databases\MyDatabase\Tables> . Csak a tisztánlátás kedvéért.

Backup listázás PowerShellben

Az SQL 2008 R2 előadásomon a Lurdy Házban mutattam egy PS scriptet, ami a következő igényt elégíti ki: egy fájlrendszeren lakó könyvtárban lévő backup fájlokból kinyalja a backup információkat. Íme a script:

function List-Backups(
[string] $filename, ##fájl vagy könyvtárnév, dir parancs számára emészthető input kell
$Html, ## HTML fájl output neve, .\ prefix kell neki lokális esetén
$servername = '.' ## az SQL Server, aki lefuttatja a restore headeronly parancsot
) {

## a tulajdonságok, amik kellenek - teljes lista a BOL-ban
$proplist = ('Position', 'DatabaseName','ServerName','BackupFinishDate','DatabaseVersion')
## mint fent, csak a filename mezővel prefixeltem. igénytelen, de gyors megoldás, 
$proplist2 = ('FileName', 'Position', 'DatabaseName','ServerName','BackupFinishDate','DatabaseVersion')

## ez a tömb tárolja a teljes listát
$allbck = @()

foreach ($file in (dir $filename)) ## ezért kellett dir kompatibilis input
  {
  ## lefut a restore headeronly...
  $backups = invoke-sqlcmd -ServerInstance ".\mysql" -Query "restore headeronly from disk = '$($file.FullName)'"
  $bck = @()
  ## a kiválasztott mezoket eltesszük a $bck változóba. 
  ##   Igazából perzisztált scriptben nem illik olyan shortcutokat használni, mint % (foreach) meg ? (where)
  $backups|select $proplist|%{$bck += $_}
  ## hozzáadjuk a fájlnevet is...
  $bck |add-member noteproperty filename $file.FullName
  ## ... és a kibövitett listát eltesszük az összegzett listába
  $allbck += $bck|select $proplist2
  } #foreach $file
## kiírjuk az összegzett listát a standard outputra - ez a függvény kimenete
$allbck
## ha meg lett adva HTML fájlnév, akkor abba is kitoljuk a táblázatot, és meg is nyitjuk. Itt lehetne kezelni a .\ hiányát, de nem tettem, lustaságból
if ($Html) 
  {
  $allbck|ConvertTo-Html|Out-file $Html
  ## itt nyitjuk meg, az alkalmazás a default app a megadott kiterjesztéshez, tehát a böngészőnk htm(l)-nél
  invoke-expression $Html
  } #if $html
}  #function List-Backups

## És nézzünk néhány példát is:

## nézzük meg a D:\SQLData\Backups könyvtár tartalmát, HTML-ben is
List-Backups D:\SQLData\Backups .\lista.html
## nézzünk meg egyetlen fájlt a konzolon 
List-Backups D:\SQLData\Backups\Full.BAK
##keressük meg a Billing adatbázis legfrissebb full backupját tartalmazó fájlt és a backup pozícióját a megadott könyvtárban
List-Backups D:\SQLData\Backups | ?{$_.DatabaseName -eq 'Billing' -and $_.BackupTypeDescription -eq 'DATABASE'} | `
 Sort -prop BackupFinishDate -desc| select Filename, Position -first 1

Az utolsó parancsba beletoltam több mindent is. A ? (where) a szűrést hivatott bemutatni, a -eq és az -and a vicces operátorokat, amit el is rontottam a demóban, a backtick a többsoros parancs sorvégét jelzi, a többi meg magától értetődő, de azért jó látni, hogy a lehetőségek szinte korlátlanok.

Powershell profile-ok

Készülődve a jövő szerdai SQL Server 2008 R2 bejelentésre éppen a Powershelles demómat reszelem-tesztelem, és örömmle tapasztaltam, hogy a PowerShell 2.0-hoz adott ISE, avagy GUI egy másik profile-t használ, mint a mezei parancssor, amiben ez látszik:

PS C:\Users\erik> $profile
C:\Users\erik\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

Ezzel szemben az ISE ezt mondja:

PS C:\Windows\system32> $profile
C:\Users\erik\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1

Biztos van különbség közöttük, gondoltam, majd elhatároztam, hogy csinálok egy symlinket (vagy hogy hívják azt Windowson) a sima profájlra. Aztán belenéztem az internetbe, és bing! máris megtaláltam a különbséget. Az ISE profile-ban gyakorlatilag kibővíthetjük az ISE menürendszerét, egy custom menüpontba betolhatjuk mindazt, amit szeretnénk még a GUI-ban látni, billentyűkombóval meg mindennel. It tvan pl. egy kedves kis minta: http://get-powershell.com/2008/12/29/code-snippets-in-powershell-ise/.

Technet Scripting Games 2010

És végre!!!! A régóta várt esemény újra itt van: Scripting Games a nemzetközi Technet oldalon! Anno ennek segítségével barátkoztam meg a VBscripttel. és még egy Scripto Bubble figurát (a képen látható) is nyertem a sorsoláson. Egy hónap múlva kezdődik, úgyhogy mindenki felszívhatja addig magát kedvenc scriptnyelvéből.

2010 Scripting Games

Kalandra fel!

Log shipping PowerShell scripttel

Egy hónapja ígértem meg Tibornak azt a PowerShelles log shipping megoldást, amit használtunk SQL 2000-2005 migrációra. Az alapgondolat a következő: a 2000-es szerveren csinálunk egy log backup jobot, ami már az új szerverre, UNC-n keresztül teszi le a backup fájlokat. Ez egy sima T-SQL job. A 2005-ös szerveren pedig egy Operating System jobstep lakik, ami egy powershell scriptet futtat. A jobstep maga kb. ennyi: powershell.exe D:\mssql\MigrateMyDB.ps1. Ez most egy bedrótozott verzió, de elég egyszerűen átalakítható paraméterezhetővé, és akkor egy scripttel lehet több adatbázist is tutujgatni.
Continue reading ‘Log shipping PowerShell scripttel’ »