<?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; scripting</title>
	<atom:link href="http://blog.rollback.hu/tag/scripting/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>Az utolsó sikeres DBCC</title>
		<link>http://blog.rollback.hu/2011/07/az-utolso-sikeres-dbcc/</link>
		<comments>http://blog.rollback.hu/2011/07/az-utolso-sikeres-dbcc/#comments</comments>
		<pubDate>Wed, 13 Jul 2011 12:27:31 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[DBCC]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=339</guid>
		<description><![CDATA[Előzőleg elmondtam ,hogy milyen fontos a DBCC CHECKDB futtatása, és erre gondolom mindenki kedvet kapott arra, hogy megnézze, mikor futott ez le az ő kis adatbázisain utoljára sikeresen. Felütötte mindenki a BOL-t, ééés&#8230; nem volt benne. Ja, ez is egyike azon undocumented apróságoknak:

DBCC DBINFO ('master') WITH TABLERESULTS;

Ez visszaad egy recordsetet, és abban select * where [...]]]></description>
			<content:encoded><![CDATA[<p>Előzőleg elmondtam ,hogy milyen fontos a DBCC CHECKDB futtatása, és erre gondolom mindenki kedvet kapott arra, hogy megnézze, mikor futott ez le az ő kis adatbázisain utoljára sikeresen. Felütötte mindenki a BOL-t, ééés&#8230; nem volt benne. Ja, ez is egyike azon undocumented apróságoknak:</p>
<pre class="brush: sql;">
DBCC DBINFO ('master') WITH TABLERESULTS;
</pre>
<p>Ez visszaad egy recordsetet, és abban <strong>select * where field = &#8216;dbi_dbccLastKnownGood&#8217;</strong>. Hát ennyi.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2011/07/az-utolso-sikeres-dbcc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CTE = Common Table Expression</title>
		<link>http://blog.rollback.hu/2011/05/cte-common-table-expression/</link>
		<comments>http://blog.rollback.hu/2011/05/cte-common-table-expression/#comments</comments>
		<pubDate>Sun, 01 May 2011 14:21:48 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[sql2005]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=330</guid>
		<description><![CDATA[Általános jelenség scriptelés közben, hogy valahol felbukkan egy subquery, pl. a &#8220;minden számla, ahol a vevő budapesti&#8221; típusú kérdésre. Ez lehet join vagy subquery, általában mindegy, a query optimizer ugyanazt a végrehajtási tervet produkálja belőlük. 

-- a subquery
SELECT * FROM Szamlak
WHERE
   vevoid in
   (SELECT vevoid FROM Vevo Where varos = 'Budapest')
-- [...]]]></description>
			<content:encoded><![CDATA[<p>Általános jelenség scriptelés közben, hogy valahol felbukkan egy subquery, pl. a &#8220;minden számla, ahol a vevő budapesti&#8221; típusú kérdésre. Ez lehet join vagy subquery, általában mindegy, a query optimizer ugyanazt a végrehajtási tervet produkálja belőlük. </p>
<pre class="brush: sql;">
-- a subquery
SELECT * FROM Szamlak
WHERE
   vevoid in
   (SELECT vevoid FROM Vevo Where varos = 'Budapest')
-- a join
SELECT s.* FROM Szamlak s
   JOIN Vevo v
   ON v.vevoid = s.vevoid
   WHERE v.varos = 'Budapest'
</pre>
<p>És vannak esetek, amikor még ez sem elég, azokra a nehéz napokra ott van a CTE, vagyis Common Table Expression. Mielőtt belemennék, hogy mi is ez, nézzük meg a fenti példát CTE-vel, ami teljesen értelmetlen, de legalább a szintaktikát felismerjük:</p>
<pre class="brush: sql;">
WITH BpVevok (vevoid)
AS (
   SELECT vevoid FROM Vevo Where varos = 'Budapest'
)
SELECT s.* FROM Szamlak s
   JOIN BpVevok
   ON BpVevok.vevoid = s.vevoid
</pre>
<p>Semmivel nem tűnik egyszerűbbnek, nem is gyorsabb, akkor meg mire jó? A CTE nem más, mint tuljadonképpen egy ideiglenes nézet, egy olyan view, amit a query elején a WITH clause-zal definiálunk, aztán a queryben meg felhasználjuk, akár többször is. Ez az egyik előnye, hogy újrahasznosítható, és akkor viszont már egyszerűség meg gyorsaság is felbukkan. Viszont amiért én pénteken hozzányúltam, az valami egészen más tulajdonsága: szereti a rekurziót is, és lehet &#8220;rekurzív nézeteket&#8221; definiálni benne. Ez nagyon jól jön például hierarchikus adatoknál, amikor van egy rekordazonosító meg egy szülőazonosító oszlop. De nézzük inkább, hogy én mire használtam, az talán jobb, mintha értekeznék.</p>
<p>Adott egy tábla, amiben fájlszerverről szóló adatok vannak, többek között: objektumazonosító; fájl, illetve könyvtárnév; projekt; lejárati idő; plusz a szülő könyvtár azonosítója. minta:<br />
<strong>id|fajlnev|projektid|lejarat|szuloid</strong><br />
12234|feladatok.doc|4334|2011-12-31|3654<br />
3654|output|4334|2012-01-31|1111<br />
1111|teszt|4334|2020-01-20|NULL</p>
<p>A teljes feladathoz pedig az egyik részfeladat az, hogy minden fájlnak kell a teljes elérési útvonala is, amit subquerykben/joinokban kell majd használni, tehát pl.<br />
12234|feladatok.doc|\teszt\output\feladatok.doc|4334|2011-12-31|3654</p>
<p>Akár a gyökérelem azonosítóját is hozzáadhatnánk, nem bonyolítjuk a helyzetet. Transact-SQL-ben ez egy érdekes feladat lenne CTE nélkül, írhatnék rekurzív függvényt például, de a CTE sokkal cukibb:</p>
<pre class="brush: sql;">
WITH FileCTE (id, fajlnev,eleresiut,projektid,lejarat,szuloid)
AS (
  SELECT id, fajlnev, '\' + fajlnev AS eleresiut, projektid, lejarat, szuloid
  FROM filetabla
   WHERE szuloid IS NULL
   UNION ALL
   SELECT f.id, f.fajlnev, c.eleresiut + '\' + f.fajlnev AS eleresiut, f.projektid, f.lejarat, f.szuloid
   FROM filetabla f
     JOIN FileCTE c
     ON c.id = f.szuloid
)
-- itt jön az igazi kelérdezés
SELECT f.id, f.projektid
FROM filetabla f
JOIN FileCTE c
ON f.id = c.id
-- join meg egy csomo minden...
WHERE c.eleresiut LIKE '%penzugyi terv%xls'
</pre>
<p>Hát erre jó a CTE. (Meg arra, hogy maga a kveri már átlátható, mert a szörnyű subquery-k ki vannak emelve az elejére&#8230; :)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2011/05/cte-common-table-expression/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<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>ROW_NUMBER, RANK &#8211; T-SQL &#8216;újdonságok&#8217;</title>
		<link>http://blog.rollback.hu/2010/10/row_number-rank-t-sql-ujdonsagok/</link>
		<comments>http://blog.rollback.hu/2010/10/row_number-rank-t-sql-ujdonsagok/#comments</comments>
		<pubDate>Sat, 30 Oct 2010 21:54:34 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=291</guid>
		<description><![CDATA[Időnként meglepve tapasztalom, hogy emberek ignorálják az SQL szerverbe bekerült dolgokat, és nekik az SQL Server pont olyan, mint mikor megismerték. Oké, az Enterprise Manager már nincs meg, de azért más is változott. Múltkor egy fejlesztő az Oracle ROWNUM okosságát hiányolta, mert ablakozó lekérdezést akart csinálni, a fenti virtuális oszlop pedig sorszámozza a visszatérő recordsetet, [...]]]></description>
			<content:encoded><![CDATA[<p>Időnként meglepve tapasztalom, hogy emberek ignorálják az SQL szerverbe bekerült dolgokat, és nekik az SQL Server pont olyan, mint mikor megismerték. Oké, az Enterprise Manager már nincs meg, de azért más is változott. Múltkor egy fejlesztő az Oracle ROWNUM okosságát hiányolta, mert ablakozó lekérdezést akart csinálni, a fenti virtuális oszlop pedig sorszámozza a visszatérő recordsetet, és lehet azt mondani, hogy where rownum < 10.  Mondtam, hogy van ilyen. </p>
<p>Gyártsunk játszós táblát:</p>
<pre class="brush: sql;">
use tempdb

create table rankdemo (
ugyfel int,
uzletkoto int,
datum smalldatetime,
osszeg float
)

insert into rankdemo values
(1001,1,&#8217;2010-01-01&#8242;,1234),
(1002,2,&#8217;2010-01-02&#8242;,1245),
(1003,2,&#8217;2010-01-04&#8242;,6578),
(1004,3,&#8217;2010-01-03&#8242;,765),
(1005,3,&#8217;2010-01-10&#8242;,44236),
(1001,3,&#8217;2010-01-11&#8242;,75),
(1001,1,&#8217;2010-01-10&#8242;,1434),
(1002,4,&#8217;2010-01-01&#8242;,94848),
(1001,1,&#8217;2010-01-02&#8242;,44236),
(1006,1,&#8217;2010-01-31&#8242;,4876),
(1001,4,&#8217;2010-01-09&#8242;,987)
</pre>
<p>Ebben álságos szerződéskötési adatok vannak, csak a minta kedvéért, valós üzleti vállalkozáshoz a sémát nem ajánlom. És most nézzük meg az úgynevezett ranking függvényeket gyorsan:</p>
<p>Először is, a már emlegetett ROW_NUMBER():</p>
<pre class="brush: sql;">
select ugyfel, osszeg, ROW_NUMBER() OVER (order by osszeg desc) as sorszam
FROM rankdemo
</pre>
<p>Egyszerű, mint a szög. A hozzá hasonló RANK() a rendezés alapjául szolgáló érték "helyezését" mondja meg, azaz itt van holtverseny.<br />
<span id="more-291"></span></p>
<pre class="brush: sql;">
select ugyfel, osszeg, ROW_NUMBER() OVER (order by osszeg desc) as sorszam,
RANK() OVER (order by osszeg desc) as helyezes
FROM rankdemo
</pre>
<p>És mi van, ha a negyedik legnagyobb értéket szeretném tudni, az előfordulások számától függetlenül? Pont van egy DENSE_RANK() is.</p>
<pre class="brush: sql;">
select ugyfel, osszeg, ROW_NUMBER() OVER (order by osszeg desc) as sorszam,
RANK() OVER (order by osszeg desc) as helyezes,
DENSE_RANK() OVER (order by osszeg desc) as helyezes2
FROM rankdemo
</pre>
<p>Itt jól látszik, hogy a helyezes2 10-nél ért véget a holtverseny miatt. </p>
<p>A jó, hogy van egy PARTITION BY clause is, amit meg lehet adni. Ez akkor jó, ha halmazon belül akarunk rendezni. Pl. klasszikus feladat a "mondd meg minden üzletkötő legnagyobb értékű bizniszét". Ez a régi világban így nézett ki:</p>
<pre class="brush: sql;">
SELECT a.ugyfel, a.uzletkoto, a.osszeg FROM
rankdemo a
JOIN
(
select MAX(osszeg) mo, uzletkoto from rankdemo
group by uzletkoto) b
on a.osszeg = b.mo
and a.uzletkoto = b.uzletkoto
</pre>
<p>Ezzel szemben ma ezt írhatjuk:</p>
<pre class="brush: sql;">
WITH  abc as(
select ugyfel, uzletkoto, osszeg, ROW_NUMBER() OVER (partition by uzletkoto order by osszeg desc) as sorszam
FROM rankdemo
)
SELECT a.ugyfel, a.uzletkoto, a.osszeg from abc a WHERE sorszam = 1
</pre>
<p>Kicsit egyszerűbb és átláthatóbb. Ha megnézzük, pont ugyanannyi idő alatt fut le mindkettő. Akkor mi a jó az újban? Mondd meg minden üzletkötő <strong>két </strong>legnagyobb értékű üzletét ranking függvények nélkül, aztán majd megmondom... :)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/10/row_number-rank-t-sql-ujdonsagok/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powershell profile-ok</title>
		<link>http://blog.rollback.hu/2010/04/powershell-profile-ok/</link>
		<comments>http://blog.rollback.hu/2010/04/powershell-profile-ok/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 16:42:53 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=242</guid>
		<description><![CDATA[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&#62; $profile
C:\Users\erik\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

Ezzel szemben az ISE ezt mondja:

PS C:\Windows\system32&#62; $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 [...]]]></description>
			<content:encoded><![CDATA[<p>Készülődve a<a href="http://www.microsoft.com/hun/technet/article/?id=bd5d606a-f906-46bb-b5af-ddd0b5ea0bdd"> jövő szerdai SQL Server 2008 R2 bejelentésre </a> é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:</p>
<pre class="brush: plain;">
PS C:\Users\erik&gt; $profile
C:\Users\erik\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
</pre>
<p>Ezzel szemben az ISE ezt mondja:</p>
<pre class="brush: plain;">
PS C:\Windows\system32&gt; $profile
C:\Users\erik\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
</pre>
<p>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: <a href="http://get-powershell.com/2008/12/29/code-snippets-in-powershell-ise/">http://get-powershell.com/2008/12/29/code-snippets-in-powershell-ise/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2010/04/powershell-profile-ok/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

