<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rollback &#187; script</title>
	<atom:link href="http://blog.rollback.hu/tag/script/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.rollback.hu</link>
	<description>SQL, üzemeltetés kicsiknek és nagyoknak.</description>
	<lastBuildDate>Thu, 17 Nov 2011 16:38:59 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SQL objektumok scriptelése Powershellben</title>
		<link>http://blog.rollback.hu/2010/12/sql-objektumok-scriptelese-powershellben/</link>
		<comments>http://blog.rollback.hu/2010/12/sql-objektumok-scriptelese-powershellben/#comments</comments>
		<pubDate>Fri, 10 Dec 2010 01:08:58 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=315</guid>
		<description><![CDATA[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&#124;%{$_.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](
    [...]]]></description>
			<content:encoded><![CDATA[<p>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:</p>
<pre class="brush: sql;">
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]
</pre>
<p>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: ˘</p>
<pre class="brush: powershell;">
%{$_.Indexes}|%{$_.script()}
</pre>
<p>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():</p>
<pre class="brush: powershell;">
PS &gt; gci |%{$_.EnumScript()}
</pre>
<pre class="brush: sql;">
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]
</pre>
<p>Vagyis ő megcsinálja nekünk a rekurziót. Szerintem aranyos kényelmi szolgáltatás.<br />
Ja, a fentiekhez a teljes path a következő volt: <strong>PS SQLSERVER:\SQL\MYCOMPUTER\DENALI\Databases\MyDatabase\Tables&gt; </strong>. Csak a tisztánlátás kedvéért.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/12/sql-objektumok-scriptelese-powershellben/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Az OUTPUT clause</title>
		<link>http://blog.rollback.hu/2010/10/az-output-clause/</link>
		<comments>http://blog.rollback.hu/2010/10/az-output-clause/#comments</comments>
		<pubDate>Wed, 06 Oct 2010 22:32:51 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[konkurrencia]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[sql2008]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[tranzakció]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=284</guid>
		<description><![CDATA[Ideje, hogy valami szakmait is írjak, mert kezd uncsi lenni a blog. Szóval van egy szép hosszú listám arról, hogy mi mindent nem mondtam el a Millenárisban tartott beszédemben, és ebből mazsolázgatok. Kezdjük is el!
Az első egy kicsi, de hasznos apróság: az OUTPUT clause vagy ahogy Serény tanár úr írná, a klóz. Mire jó? Tipikus [...]]]></description>
			<content:encoded><![CDATA[<p>Ideje, hogy valami szakmait is írjak, mert kezd uncsi lenni a blog. Szóval van egy szép hosszú listám arról, hogy mi mindent nem mondtam el a Millenárisban tartott beszédemben, és ebből mazsolázgatok. Kezdjük is el!</p>
<p>Az első egy kicsi, de hasznos apróság: az OUTPUT clause vagy ahogy Serény tanár úr írná, a klóz. Mire jó? Tipikus jelenet, hogy kell update-elnem rekordokat egy OLTP adatbázisban, azaz az adat változik alattam, de szeretném tudni, hogy pontosan melyeket update-eltem meg. Erre a gyenge megoldás a </p>
<pre class="brush: sql;">
select primary_key into #temptabla from tabla
where status = 'NEW'

update tabla where primary_key in (select primary_key from #temptabla)
set status = 'ACTIVE'

drop table #temptabla
</pre>
<p>Ez egy egész jó megközelítés, két feltétel teljesülése esetén:</p>
<ol>
<li>Nulla konkurrencia lehetséges, azaz pl. nem akar egyszerre két alkalmazásszerver dolgozni az adatbáziban, ekkor ugyanis ők lelkesen dolgozzák fel a rekordokat &#8211; egyszerre. Ezt nem részletezném, hogy miért gáz.</li>
<li>2008-at vagy kevesebbet írunk. Azóta ugyanis van OUTPUT clause.</li>
</ol>
<p>A dolog roppant egyszerű: bele van dugva egy belső trigger gyakorlatilag, ami a következőt tudja: ha beletömjük az OUTPUT-ot az INSERT/UPDATE/DELETE utasításba, akkor lesz inserted és/vagy deleted táblánk, és lehet kiszipkázni az adatokat, akár csak kiechózni, akár betenni táblaváltozókba. Az OUTPUT helye a WHERE feltétel előtt van még, erre figyeljetek. Valahogy így:</p>
<pre class="brush: sql;">
UPDATE tabla
SET status = 'ACTIVE'
OUTPUT inserted.primary_key
WHERE status = 'NEW'
</pre>
<p>Valljuk be, hogy jobban néz ki. Ha el akarjuk menteni az outputot későbbi reszeléshez vagy csak nyakonvágni a teljesítményt, akkor pedig a fenti példa így néz ki:</p>
<pre class="brush: sql;">
DECLARE @tablacska table (primary_key int);
UPDATE tabla
SET status = 'ACTIVE'
OUTPUT inserted.primary_key INTO @tablacska
WHERE status = 'NEW';
SELECT primary_key FROM @tablacska;
</pre>
<p>Ez egyébként fokozható, például ha már így előjött a konkurrencia, mint probléma, kiválóan megoldható a sok alkalmazás egy táblát túr probléma ezzel meg egy kis locking hinteléssel:</p>
<pre class="brush: sql;">
UPDATE tabla WITH (READPAST)
SET status = 'ACTIVE'
OUTPUT inserted.*
WHERE status = 'NEW'
</pre>
<p>Így ha több szerver dolgoz fel egy queue-t, hogy szépen mondjam, nem kell nagyon foglalkozniuk a másikkal. Egy konkrét szerver odamegy, kivesz annyi rekordot, amennyit akar (mert lehet TOP-ot is mondani az update-ben), ha valaki más is éppen update-el, akkor az általa lockolt rekordokat átugorja, és keres olyat, ami nincs lockolva. Ez a READPAST ajándéka: átugorja a lockolt rekordokat, így nem akadnak fenn egymáson a párhuzamos processzek.</p>
<p>(disclaimer: épp nincs SQL szerverem, ezért a példákat fejből írtam, ha nem működnek, bocsi, kijavítom :)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/10/az-output-clause/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Új diszkek hozzáadása az SQL clusterhez</title>
		<link>http://blog.rollback.hu/2010/05/uj-diszkek-hozzaadasa-az-sql-clusterhez/</link>
		<comments>http://blog.rollback.hu/2010/05/uj-diszkek-hozzaadasa-az-sql-clusterhez/#comments</comments>
		<pubDate>Mon, 10 May 2010 14:09:56 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[cluster]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=263</guid>
		<description><![CDATA[Diszket kellett bővíteni egy SQL clusterben, a lehető legkevesebb leállással, úgyhogy úgy döntöttem, hogy folytatom, amiben jó kezdek lenni: scriptelek. A cluster diszkek hozzáadása önmagában nem nagy szám (most felhördül legalább 28 ember, akinek már voltak rossz élményei a témában &#8211; nekem is, de a lekapcsolt többi node majdnem mindig dobott a dolgon), a jó [...]]]></description>
			<content:encoded><![CDATA[<p>Diszket kellett bővíteni egy SQL clusterben, a lehető legkevesebb leállással, úgyhogy úgy döntöttem, hogy folytatom, amiben jó kezdek lenni: scriptelek. A cluster diszkek hozzáadása önmagában nem nagy szám (most felhördül legalább 28 ember, akinek már voltak rossz élményei a témában &#8211; nekem is, de a lekapcsolt többi node majdnem mindig dobott a dolgon), a jó rész az, hogy az SQL csak azokat a diszkeket használja, amiken dependál a service, a dependenciát pedig csak leállított helyzetben lehet állítgatni. Itt jön jól a script, hogy ne kelljen klikkelni, míg megöregszem. Ezúttal a cluster.exe volt a műtéti alany, az eredmény pedig alant látható (a sql12clus clustert megtámogatva):</p>
<pre class="brush: plain;">
cluster.exe sql12clus resource &quot;SQL Server&quot; /Offline
cluster.exe sql12clus resource &quot;SQL Server&quot; /AddDependency:&quot;K: BillingData&quot;
cluster.exe sql12clus resource &quot;SQL Server&quot; /AddDependency:&quot;L: BillingLog&quot;
cluster.exe sql12clus resource &quot;SQL Server&quot; /Online
</pre>
<p>Azaz leállít, dependenciát hozzáad, elindít. Egy öröm volt.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/05/uj-diszkek-hozzaadasa-az-sql-clusterhez/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Backup listázás PowerShellben</title>
		<link>http://blog.rollback.hu/2010/04/backup-listazas-powershellben/</link>
		<comments>http://blog.rollback.hu/2010/04/backup-listazas-powershellben/#comments</comments>
		<pubDate>Tue, 27 Apr 2010 08:45:22 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[sqlcmd]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=256</guid>
		<description><![CDATA[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 = [...]]]></description>
			<content:encoded><![CDATA[<p>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:</p>
<pre class="brush: powershell;">
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 &quot;.\mysql&quot; -Query &quot;restore headeronly from disk = '$($file.FullName)'&quot;
  $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
</pre>
<p>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.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/04/backup-listazas-powershellben/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Tárolt eljárások definíciójában keresés</title>
		<link>http://blog.rollback.hu/2010/04/tarolt-eljarasok-definiciojaban-kereses/</link>
		<comments>http://blog.rollback.hu/2010/04/tarolt-eljarasok-definiciojaban-kereses/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 20:22:42 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=239</guid>
		<description><![CDATA[Időről időre visszatérő probléma: melyik tárolt eljárást érinti egy adott tábla módosítása, melyik SP-ben van deprecated (elavult) (NOLOCK) hint, effélék &#8211; szóval keresni kell a definíciókban. Ezt sokféleképpen megtehetjük, a legkényelmesebb a definíciók felolvasása. Régebben az INFORMATION_SCHEMA.ROUTINES ANSI standard metatáblát használtam erre, most már váltottam a meglehetősen nem intuitív nevű sys.sql_modules rendszernézetre. A különbség egyébként [...]]]></description>
			<content:encoded><![CDATA[<p>Időről időre visszatérő probléma: melyik tárolt eljárást érinti egy adott tábla módosítása, melyik SP-ben van deprecated (elavult) (NOLOCK) hint, effélék &#8211; szóval keresni kell a definíciókban. Ezt sokféleképpen megtehetjük, a legkényelmesebb a definíciók felolvasása. Régebben az INFORMATION_SCHEMA.ROUTINES ANSI standard metatáblát használtam erre, most már váltottam a meglehetősen nem intuitív nevű sys.sql_modules rendszernézetre. A különbség egyébként nem nagy &#8211; a standardban csak az első 4000 karakter látszik, a MSSQL-specifikus pedig nvarchar(max), tehát hajszálnyit több fér bele. </p>
<p>Ebből született a tárolt eljárásban stringet kereső tárolt eljárás. Két paramétert vár: a stringet, amire keresni akarunk és az adatbázis nevét, amiben keresni akarunk. Ha az egész szerveren szeretnénk keresni, akkor használhatjuk az undocumented sp_MSforeachdb tárolt eljárást.</p>
<pre class="brush: sql;">
CREATE PROCEDURE dbo.spFindTextInSP
@string nvarchar(1000),
@dbname sysname = ''
AS
if (isnull(@dbname,'') = '')
        set @dbname = db_name()
declare @q nvarchar(2000)
set @q = 'select quotename(object_schema_name(object_id,db_id('''+ @dbname + '''))) + ''.'' + quotename(object_name(object_id,db_id(''' + @dbname +  '''))) AS matching_objects from ' + @dbname + '.sys.sql_modules
where definition like ''%' + @string + '%'''
exec(@q)

GO

-- és két minta felhasználás
exec dbo.spFindTextInSp 'alert'
exec dbo.spFindTextInSp 'alert', 'Customer_archiv'
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/04/tarolt-eljarasok-definiciojaban-kereses/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

