<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>SQLGeek.pl</title>
	
	<link>http://sqlgeek.pl</link>
	<description>from SQL developer's life</description>
	<lastBuildDate>Mon, 06 Sep 2010 06:50:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Sqlgeek_pl" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="sqlgeek_pl" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>[PL] Skryptowanie w SQL Server 2008 – Klucze obce</title>
		<link>http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/</link>
		<comments>http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/#comments</comments>
		<pubDate>Mon, 06 Sep 2010 06:50:29 +0000</pubDate>
		<dc:creator>Pawel Potasinski</dc:creator>
				<category><![CDATA[Skryptowanie w SQL Server 2008]]></category>
		<category><![CDATA[klucze obce]]></category>
		<category><![CDATA[skryptowanie]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://sqlgeek.pl/?p=345</guid>
		<description><![CDATA[To już trzeci wpis z serii "Skryptowanie w SQL Server 2008". Tym razem przedstawiam sposób na skryptowanie kluczy obcych. Kiedy takie skryptowanie może się przydać? Na przykład wtedy, gdy chcemy usunąć, a następnie odtworzyć owe klucze (typowy scenariusz: import wyczyszczonych i zwalidowanych danych). W podsumowaniu podam, jakie rozwinięcia mojego kodu można zaimplementować, by za pomocą praktycznie tego samego kodu wykonywać inne zadania związane z kluczami obcymi.]]></description>
			<content:encoded><![CDATA[<h4>Intro</h4>
<p>To już trzeci wpis z serii &#8220;Skryptowanie w SQL Server 2008&#8243;. Dwa poprzednie dostępne są tu:</p>
<ul>
<li><a href="http://sqlgeek.pl/2010/08/08/skryptowanie-w-sql-server-2008-obiekty-proceduralne/">[PL] Skryptowanie w SQL Server 2008 – Obiekty proceduralne</a></li>
<li><a href="http://sqlgeek.pl/2010/08/16/skryptowanie-w-sql-server-2008-proste-typy-danych-uzytkownika/">[PL] Skryptowanie w SQL Server 2008 – Proste typy danych użytkownika</a></li>
</ul>
<p>Tym razem przedstawiam sposób na skryptowanie kluczy obcych. Kiedy takie skryptowanie może się przydać? Na przykład wtedy, gdy chcemy usunąć, a następnie odtworzyć owe klucze (typowy scenariusz: import wyczyszczonych i zwalidowanych danych). W podsumowaniu podam, jakie rozwinięcia mojego kodu można zaimplementować, by za pomocą praktycznie tego samego kodu wykonywać inne zadania związane z kluczami obcymi.</p>
<h4>Skryptowanie kluczy obcych</h4>
<p><strong>Zadanie: </strong>zeskryptować wszystkie klucze obce w bazie danych.</p>
<p><strong>Rozwiązanie:</strong></p>
<pre>USE AdventureWorks2008R2;
GO
SET NOCOUNT ON;

-- tu będziemy trzymać generowany kod
DECLARE @SQL TABLE (
  LineId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  Line nvarchar(4000) NOT NULL
);

DECLARE
  @object_name sysname,
  @object_id int,
  @object_schema_name sysname,
  @parent_object_name sysname,
  @parent_object_schema_name sysname,
  @is_not_for_replication bit,
  @delete_referential_action int,
  @update_referential_action int,
  @referenced_object_schema_name sysname,
  @referenced_object_name sysname,
  @column_name sysname,
  @referenced_column_name sysname,
  @columns nvarchar(4000),
  @referenced_columns nvarchar(4000);

-- kursor do wyciągania pojedynczych kluczy obcych
DECLARE CursorFK CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
  SELECT
    name,
    [object_id],
    SCHEMA_NAME([schema_id]),
    OBJECT_SCHEMA_NAME(parent_object_id),
    OBJECT_NAME(parent_object_id),
    OBJECT_SCHEMA_NAME(referenced_object_id),
    OBJECT_NAME(referenced_object_id),
    is_not_for_replication,
    delete_referential_action,
    update_referential_action
  FROM sys.foreign_keys
  WHERE is_ms_shipped = 0;
OPEN CursorFK;
FETCH NEXT FROM CursorFK
INTO @object_name, @object_id, @object_schema_name,
     @parent_object_schema_name, @parent_object_name,
     @referenced_object_schema_name, @referenced_object_name,
     @is_not_for_replication,
     @delete_referential_action, @update_referential_action;

WHILE @@FETCH_STATUS = 0 BEGIN
  SELECT @columns = '', @referenced_columns = '';

  -- generujemy sprawdzenie, czy klucz nie istnieje
  INSERT INTO @SQL (Line)
  SELECT 'IF OBJECT_ID(N''' +
        REPLACE(
          QUOTENAME(@object_schema_name) + '.' +
          QUOTENAME(@object_name), '''', ''''''
        ) + ''', N''F'') IS NULL';

  -- generujemy polecenie ALTER TABLE ... ADD CONSTRAINT
  INSERT INTO @SQL (Line)
  SELECT '  ALTER TABLE ' +
    QUOTENAME(@parent_object_schema_name) + '.' +
    QUOTENAME(@parent_object_name);
  INSERT INTO @SQL (Line)
  SELECT '  ADD CONSTRAINT ' + QUOTENAME(@object_name);

  -- kursor do wyciągania kolejnych kolumn klucza obcego
  DECLARE CursorFKColumns CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
  FOR
    SELECT
      pc.name,
      rc.name
    FROM sys.foreign_key_columns AS f
    INNER JOIN sys.columns AS pc
    ON f.parent_object_id = pc.[object_id]
    AND f.parent_column_id = pc.column_id
    INNER JOIN sys.columns AS rc
    ON f.referenced_object_id = rc.[object_id]
    AND f.referenced_column_id = rc.column_id
    WHERE f.constraint_object_id = @object_id
    ORDER BY f.constraint_column_id
  OPEN CursorFKColumns;
  FETCH NEXT FROM CursorFKColumns
  INTO
    @column_name,
    @referenced_column_name;
  WHILE @@FETCH_STATUS = 0 BEGIN
    -- doklejamy do zestawów kolumn
    SET @columns = @columns + ', ' + QUOTENAME(@column_name);
    SET @referenced_columns = @referenced_columns + ', ' + QUOTENAME(@referenced_column_name);

    FETCH NEXT FROM CursorFKColumns
    INTO
      @column_name,
      @referenced_column_name;
  END;
  CLOSE CursorFKColumns;
  DEALLOCATE CursorFKColumns;

  -- generujemy kod z listami kolumn
  INSERT INTO @SQL (Line)
  SELECT '  FOREIGN KEY (' + STUFF(@columns, 1, 2, '') + ')';
  INSERT INTO @SQL (Line)
  SELECT '  REFERENCES ' +
    QUOTENAME(@referenced_object_schema_name) + '.' +
    QUOTENAME(@referenced_object_name) + '(' +
    STUFF(@referenced_columns, 1, 2, '') + ')';

  -- akcje klucza przy usuwaniu wierszy
  IF @delete_referential_action &lt;&gt; 0 BEGIN
    INSERT INTO @SQL (Line)
    SELECT '  ON DELETE ' +
      CASE @delete_referential_action
        WHEN 1 THEN 'CASCADE'
        WHEN 2 THEN 'SET NULL'
        WHEN 3 THEN 'SET DEFAULT'
      END;
  END;

  -- akcje klucza przy modyfikacji wierszy
  IF @update_referential_action &lt;&gt; 0 BEGIN
    INSERT INTO @SQL (Line)
    SELECT '  ON UPDATE ' +
      CASE @update_referential_action
        WHEN 1 THEN 'CASCADE'
        WHEN 2 THEN 'SET NULL'
        WHEN 3 THEN 'SET DEFAULT'
      END;
  END;

  -- czy wymuszamy regułę klucza w replikacjach
  IF @is_not_for_replication = 1
    INSERT INTO @SQL (Line)
    SELECT '  NOT FOR REPLICATION';

  UPDATE @SQL
  SET Line = Line + ';'
  WHERE LineId = SCOPE_IDENTITY();

  INSERT INTO @SQL (Line) SELECT 'GO';

  FETCH NEXT FROM CursorFK
  INTO @object_name, @object_id, @object_schema_name,
     @parent_object_schema_name, @parent_object_name,
     @referenced_object_schema_name, @referenced_object_name,
     @is_not_for_replication,
     @delete_referential_action, @update_referential_action;
END;
CLOSE CursorFK;
DEALLOCATE CursorFK;
SELECT Line AS ' ' FROM @SQL ORDER BY LineId;
GO</pre>
<p><strong>Fragment wyniku:</strong></p>
<p><strong><a href="http://sqlgeek.pl/wp-content/uploads/2010/08/2010-08-19-22-22-50.png"></a></strong></p>
<p><a href="http://sqlgeek.pl/wp-content/uploads/2010/08/image4.png"></a></p>
<p><strong><a href="http://sqlgeek.pl/wp-content/uploads/2010/08/2010-08-19-22-22-501.png"><img class="alignnone size-full wp-image-421" title="2010-08-19 22-22-50" src="http://sqlgeek.pl/wp-content/uploads/2010/08/2010-08-19-22-22-501.png" alt="" width="687" height="266" /></a></strong></p>
<p><strong>Uwagi: </strong>w Management Studio ustaw <em>Results to Text</em>, sugeruję też zwiększenie maksymalnej długości tekstu w jednej kolumnie zwracanej w wynikach zapytań (w menu głównym kliknij <em>Tools – Options – Query Results – SQL Server – Results to Text</em> i w polu <em>Maximum number of characters displayed in each column</em><strong> </strong>wpisz 8192, a następnie uruchom ponownie Management Studio).</p>
<p><strong>Komentarz do kodu:</strong></p>
<ul>
<li>metadane kluczy obcych zwracają widoki <em>sys.foreign_keys</em> (metadane tabeli, w której tworzymy klucz, opcje dla poleceń DELETE / UPDATE, opcja wyłączenia klucza dla replikacji) oraz <em>sys.foreign_key_columns</em> (metadane kolumn oraz tabeli, do której odwołuje się klucz obcy),</li>
<li>funkcja QUOTENAME jak zwykle służy mi do otaczania identyfikatorów nawiasami kwadratowymi i apostrofami,</li>
<li>fragmenty generowanego skryptu T-SQL są dodawane w kursorze (iteracja = definicja jednego obiektu) do zmiennej tabelarycznej @SQL (linie są numerowane autonumeracją w kolumnie LineId, zakładam maksymalną długość jednej linii kodu w obiekcie na 4000 znaków),</li>
<li>rozwiązanie oparłem o dwa kursory: CursorFK – do iterowania po kluczach obcych oraz zagnieżdżony CursorFKColumns – do iterowania po kolumnach bieżącego klucza,</li>
<li>ponieważ nie jestem zwolennikiem wyłączania więzów, moje rozwiązanie nie uwzględnia kolumny <em>is_disabled</em> z widoku <em>sys.foreign_keys</em> (nie generuję klauzuli WITH NOCHECK nawet, gdy klucz jest wyłączony).</li>
</ul>
<h4>Słowo podsumowania</h4>
<p>Powyższy kod można rozwinąć:</p>
<ul>
<li>można dołożyć filtrowanie po tabelach (czy to tabeli, w której klucz jest utworzony, czy po tabeli, do której klucz się odwołuje),</li>
<li>można generować tylko składnie ALTER TABLE … DROP CONSTRAINT, jeżeli zależy nam tylko na usunięciu wybranych kluczy,</li>
<li>można wykorzystać kolumnę <em>is_system_named</em> z widoku <em>sys.foreign_keys</em>, jeżeli chcemy odnaleźć te klucze, które otrzymały nazwy wygenerowane systemowo (jeżeli nie chcemy mieć w bazie danych obiektów nazywanych dość przypadkowo).</li>
</ul>
<p>Na koniec informacja – w <a href="http://sqlgeek.pl/code-library/">repozytorium kodu</a> umieściłem kod pseudo-systemowej procedury <a href="http://sqlgeek.pl/Download/Scripts/20090620_sp_dropforeignkeys.txt">sp_dropforeignkeys</a>, która może posłużyć do wygenerowania kodu usuwającego klucze obce wskazujące na wybraną tabelę. W procedurze tej wykorzystałem te same obiekty systemowe, co w powyższym kodzie, więc komentarz do niej wydaje mi się zbędny. Po stworzeniu w bazie master i oznaczeniu jako obiekt systemowy procedura powinna działać w kontekście dowolnej bazy danych.</p>
<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
<li class="shr-comfeed">
			<a href="http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
<li class="shr-twitter">
			<a href="http://twitter.com/home?status=%5BPL%5D+Skryptowanie+w+SQL+Server+2008+%E2%80%93+Klucze+obce+-+http://b2l.me/apqmjh&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/&amp;t=%5BPL%5D+Skryptowanie+w+SQL+Server+2008+%E2%80%93+Klucze+obce" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/&amp;title=%5BPL%5D+Skryptowanie+w+SQL+Server+2008+%E2%80%93+Klucze+obce&amp;summary=To%20ju%C5%BC%20trzeci%20wpis%20z%20serii%20%22Skryptowanie%20w%20SQL%20Server%202008%22.%20Tym%20razem%20przedstawiam%20spos%C3%B3b%20na%20skryptowanie%20kluczy%20obcych.%20Kiedy%20takie%20skryptowanie%20mo%C5%BCe%20si%C4%99%20przyda%C4%87%3F%20Na%20przyk%C5%82ad%20wtedy%2C%20gdy%20chcemy%20usun%C4%85%C4%87%2C%20a%20nast%C4%99pnie%20odtworzy%C4%87%20owe%20klucze%20%28typowy%20scenariusz%3A%20import%20wyczyszczonych%20i%20zwalidowanych%20danych%29.%20W%20podsumowaniu%20podam%2C%20jakie%20rozwini%C4%99cia%20mojego%20kodu%20mo%C5%BCna%20zaimplementowa%C4%87%2C%20by%20za%20pomoc%C4%85%20praktycznie%20tego%20samego%20kodu%20wykonywa%C4%87%20inne%20zadania%20zwi%C4%85zane%20z%20kluczami%20obcymi.&amp;source=SQLGeek.pl" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/&amp;title=%5BPL%5D+Skryptowanie+w+SQL+Server+2008+%E2%80%93+Klucze+obce" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/&amp;title=%5BPL%5D+Skryptowanie+w+SQL+Server+2008+%E2%80%93+Klucze+obce" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/&amp;title=%5BPL%5D+Skryptowanie+w+SQL+Server+2008+%E2%80%93+Klucze+obce&amp;srcUrl=http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/&amp;srcTitle=%5BPL%5D+Skryptowanie+w+SQL+Server+2008+%E2%80%93+Klucze+obce&amp;snippet=To%20ju%C5%BC%20trzeci%20wpis%20z%20serii%20%22Skryptowanie%20w%20SQL%20Server%202008%22.%20Tym%20razem%20przedstawiam%20spos%C3%B3b%20na%20skryptowanie%20kluczy%20obcych.%20Kiedy%20takie%20skryptowanie%20mo%C5%BCe%20si%C4%99%20przyda%C4%87%3F%20Na%20przyk%C5%82ad%20wtedy%2C%20gdy%20chcemy%20usun%C4%85%C4%87%2C%20a%20nast%C4%99pnie%20odtworzy%C4%87%20owe%20klucze%20%28typowy%20scenariusz%3A%20import%20wyczyszczonych%20i%20zwalidowanych%20danych%29.%20W%20podsumowaniu%20podam%2C%20jakie%20rozwini%C4%99cia%20mojego%20kodu%20mo%C5%BCna%20zaimplementowa%C4%87%2C%20by%20za%20pomoc%C4%85%20praktycznie%20tego%20samego%20kodu%20wykonywa%C4%87%20inne%20zadania%20zwi%C4%85zane%20z%20kluczami%20obcymi." rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
<li class="shr-gmail">
			<a href="https://mail.google.com/mail/?ui=2&amp;view=cm&amp;fs=1&amp;tf=1&amp;su=%5BPL%5D+Skryptowanie+w+SQL+Server+2008+%E2%80%93+Klucze+obce&amp;body=Link: http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A To%20ju%C5%BC%20trzeci%20wpis%20z%20serii%20%22Skryptowanie%20w%20SQL%20Server%202008%22.%20Tym%20razem%20przedstawiam%20spos%C3%B3b%20na%20skryptowanie%20kluczy%20obcych.%20Kiedy%20takie%20skryptowanie%20mo%C5%BCe%20si%C4%99%20przyda%C4%87%3F%20Na%20przyk%C5%82ad%20wtedy%2C%20gdy%20chcemy%20usun%C4%85%C4%87%2C%20a%20nast%C4%99pnie%20odtworzy%C4%87%20owe%20klucze%20%28typowy%20scenariusz%3A%20import%20wyczyszczonych%20i%20zwalidowanych%20danych%29.%20W%20podsumowaniu%20podam%2C%20jakie%20rozwini%C4%99cia%20mojego%20kodu%20mo%C5%BCna%20zaimplementowa%C4%87%2C%20by%20za%20pomoc%C4%85%20praktycznie%20tego%20samego%20kodu%20wykonywa%C4%87%20inne%20zadania%20zwi%C4%85zane%20z%20kluczami%20obcymi." rel="nofollow" class="external" title="Email this via Gmail">Email this via Gmail</a>
		</li>
<li class="shr-googlebookmarks">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/&amp;title=%5BPL%5D+Skryptowanie+w+SQL+Server+2008+%E2%80%93+Klucze+obce" rel="nofollow" class="external" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
<li class="shr-hotmail">
			<a href="http://mail.live.com/?rru=compose?subject=%5BPL%5D+Skryptowanie+w+SQL+Server+2008+%E2%80%93+Klucze+obce&amp;body=Link: http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A To%20ju%C5%BC%20trzeci%20wpis%20z%20serii%20%22Skryptowanie%20w%20SQL%20Server%202008%22.%20Tym%20razem%20przedstawiam%20spos%C3%B3b%20na%20skryptowanie%20kluczy%20obcych.%20Kiedy%20takie%20skryptowanie%20mo%C5%BCe%20si%C4%99%20przyda%C4%87%3F%20Na%20przyk%C5%82ad%20wtedy%2C%20gdy%20chcemy%20usun%C4%85%C4%87%2C%20a%20nast%C4%99pnie%20odtworzy%C4%87%20owe%20klucze%20%28typowy%20scenariusz%3A%20import%20wyczyszczonych%20i%20zwalidowanych%20danych%29.%20W%20podsumowaniu%20podam%2C%20jakie%20rozwini%C4%99cia%20mojego%20kodu%20mo%C5%BCna%20zaimplementowa%C4%87%2C%20by%20za%20pomoc%C4%85%20praktycznie%20tego%20samego%20kodu%20wykonywa%C4%87%20inne%20zadania%20zwi%C4%85zane%20z%20kluczami%20obcymi." rel="nofollow" class="external" title="Email this via Hotmail">Email this via Hotmail</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sqlgeek.pl/2010/09/06/pl-skryptowanie-w-sql-server-2008-klucze-obce/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[PL] SQL Server – Baza danych z danymi geograficznymi Polski</title>
		<link>http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/</link>
		<comments>http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/#comments</comments>
		<pubDate>Sat, 04 Sep 2010 13:02:22 +0000</pubDate>
		<dc:creator>Pawel Potasinski</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[baza danych]]></category>
		<category><![CDATA[dane geograficzne]]></category>
		<category><![CDATA[spatials]]></category>

		<guid isPermaLink="false">http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/</guid>
		<description><![CDATA[Jeżeli chcesz pobawić się trochę danymi geograficznymi i raportami pokazującymi mapy w SQL Server 2008 R2, ten wpis jest specjalnie dla Ciebie. Kiedyś musiałem przygotować prezentację na temat danych przestrzennych i z tamtej prezentacji została mi baza danych Spatials, która w dwóch tabelach przechowuje kształty Polski (tabela dbo.Country) i województw (dbo.Province). Backup daje się odtworzyć na SQL Server 2008 R2 (jest skompresowany i zajmuje około 1 MB).]]></description>
			<content:encoded><![CDATA[<p>Jeżeli chcesz pobawić się trochę danymi geograficznymi i raportami pokazującymi mapy w SQL Server 2008 R2, ten wpis jest specjalnie dla Ciebie. Kiedyś musiałem przygotować prezentację na temat danych przestrzennych i z tamtej prezentacji została mi baza danych Spatials, która w dwóch tabelach przechowuje kształty Polski (tabela dbo.Country) i województw (dbo.Province). Backup daje się odtworzyć na SQL Server 2008 R2 (jest skompresowany i zajmuje około 1 MB). Poniżej przykładowy raport, jaki możesz zbudować w oparciu o dane z tej bazy.</p>
<p><a href="http://sqlgeek.pl/wp-content/uploads/2010/09/image.png"><img style="display: inline; border: 0px;" title="image" src="http://sqlgeek.pl/wp-content/uploads/2010/09/image_thumb.png" border="0" alt="image" width="640" height="405" /></a></p>
<p>Przyjemnej zabawy z danymi geograficznymi :-)</p>
<p><a href="http://sqlgeek.pl/Download/Spatials.bak"><strong>Pobierz kopię zapasową bazy Spatials (1 MB)</strong></a></p>
<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
<li class="shr-comfeed">
			<a href="http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
<li class="shr-twitter">
			<a href="http://twitter.com/home?status=%5BPL%5D+SQL+Server+%26ndash%3B+Baza+danych+z+danymi+geograficznymi+Polski+-+http://b2l.me/apchqy&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/&amp;t=%5BPL%5D+SQL+Server+%26ndash%3B+Baza+danych+z+danymi+geograficznymi+Polski" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+Baza+danych+z+danymi+geograficznymi+Polski&amp;summary=Je%C5%BCeli%20chcesz%20pobawi%C4%87%20si%C4%99%20troch%C4%99%20danymi%20geograficznymi%20i%20raportami%20pokazuj%C4%85cymi%20mapy%20w%20SQL%20Server%202008%20R2%2C%20ten%20wpis%20jest%20specjalnie%20dla%20Ciebie.%20Kiedy%C5%9B%20musia%C5%82em%20przygotowa%C4%87%20prezentacj%C4%99%20na%20temat%20danych%20przestrzennych%20i%20z%20tamtej%20prezentacji%20zosta%C5%82a%20mi%20baza%20danych%20Spatials%2C%20kt%C3%B3ra%20w%20dw%C3%B3ch%20tabelach%20przechowuje%20kszta%C5%82ty%20Polski%20%28tabela%20dbo.Country%29%20i%20wojew%C3%B3dztw%20%28dbo.Province%29.%20Backup%20daje%20si%C4%99%20odtworzy%C4%87%20na%20SQL%20Server%202008%20R2%20%28jest%20skompresowany%20i%20zajmuje%20oko%C5%82o%201%20MB%29.&amp;source=SQLGeek.pl" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+Baza+danych+z+danymi+geograficznymi+Polski" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+Baza+danych+z+danymi+geograficznymi+Polski" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+Baza+danych+z+danymi+geograficznymi+Polski&amp;srcUrl=http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/&amp;srcTitle=%5BPL%5D+SQL+Server+%26ndash%3B+Baza+danych+z+danymi+geograficznymi+Polski&amp;snippet=Je%C5%BCeli%20chcesz%20pobawi%C4%87%20si%C4%99%20troch%C4%99%20danymi%20geograficznymi%20i%20raportami%20pokazuj%C4%85cymi%20mapy%20w%20SQL%20Server%202008%20R2%2C%20ten%20wpis%20jest%20specjalnie%20dla%20Ciebie.%20Kiedy%C5%9B%20musia%C5%82em%20przygotowa%C4%87%20prezentacj%C4%99%20na%20temat%20danych%20przestrzennych%20i%20z%20tamtej%20prezentacji%20zosta%C5%82a%20mi%20baza%20danych%20Spatials%2C%20kt%C3%B3ra%20w%20dw%C3%B3ch%20tabelach%20przechowuje%20kszta%C5%82ty%20Polski%20%28tabela%20dbo.Country%29%20i%20wojew%C3%B3dztw%20%28dbo.Province%29.%20Backup%20daje%20si%C4%99%20odtworzy%C4%87%20na%20SQL%20Server%202008%20R2%20%28jest%20skompresowany%20i%20zajmuje%20oko%C5%82o%201%20MB%29." rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
<li class="shr-gmail">
			<a href="https://mail.google.com/mail/?ui=2&amp;view=cm&amp;fs=1&amp;tf=1&amp;su=%5BPL%5D+SQL+Server+%26ndash%3B+Baza+danych+z+danymi+geograficznymi+Polski&amp;body=Link: http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Je%C5%BCeli%20chcesz%20pobawi%C4%87%20si%C4%99%20troch%C4%99%20danymi%20geograficznymi%20i%20raportami%20pokazuj%C4%85cymi%20mapy%20w%20SQL%20Server%202008%20R2%2C%20ten%20wpis%20jest%20specjalnie%20dla%20Ciebie.%20Kiedy%C5%9B%20musia%C5%82em%20przygotowa%C4%87%20prezentacj%C4%99%20na%20temat%20danych%20przestrzennych%20i%20z%20tamtej%20prezentacji%20zosta%C5%82a%20mi%20baza%20danych%20Spatials%2C%20kt%C3%B3ra%20w%20dw%C3%B3ch%20tabelach%20przechowuje%20kszta%C5%82ty%20Polski%20%28tabela%20dbo.Country%29%20i%20wojew%C3%B3dztw%20%28dbo.Province%29.%20Backup%20daje%20si%C4%99%20odtworzy%C4%87%20na%20SQL%20Server%202008%20R2%20%28jest%20skompresowany%20i%20zajmuje%20oko%C5%82o%201%20MB%29." rel="nofollow" class="external" title="Email this via Gmail">Email this via Gmail</a>
		</li>
<li class="shr-googlebookmarks">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+Baza+danych+z+danymi+geograficznymi+Polski" rel="nofollow" class="external" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
<li class="shr-hotmail">
			<a href="http://mail.live.com/?rru=compose?subject=%5BPL%5D+SQL+Server+%26ndash%3B+Baza+danych+z+danymi+geograficznymi+Polski&amp;body=Link: http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Je%C5%BCeli%20chcesz%20pobawi%C4%87%20si%C4%99%20troch%C4%99%20danymi%20geograficznymi%20i%20raportami%20pokazuj%C4%85cymi%20mapy%20w%20SQL%20Server%202008%20R2%2C%20ten%20wpis%20jest%20specjalnie%20dla%20Ciebie.%20Kiedy%C5%9B%20musia%C5%82em%20przygotowa%C4%87%20prezentacj%C4%99%20na%20temat%20danych%20przestrzennych%20i%20z%20tamtej%20prezentacji%20zosta%C5%82a%20mi%20baza%20danych%20Spatials%2C%20kt%C3%B3ra%20w%20dw%C3%B3ch%20tabelach%20przechowuje%20kszta%C5%82ty%20Polski%20%28tabela%20dbo.Country%29%20i%20wojew%C3%B3dztw%20%28dbo.Province%29.%20Backup%20daje%20si%C4%99%20odtworzy%C4%87%20na%20SQL%20Server%202008%20R2%20%28jest%20skompresowany%20i%20zajmuje%20oko%C5%82o%201%20MB%29." rel="nofollow" class="external" title="Email this via Hotmail">Email this via Hotmail</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sqlgeek.pl/2010/09/04/pl-sql-server-baza-danych-z-danymi-geograficznymi-polski/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[PL] Wywiad – nasi na TSQL Challenges</title>
		<link>http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/</link>
		<comments>http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 05:51:59 +0000</pubDate>
		<dc:creator>Pawel Potasinski</dc:creator>
				<category><![CDATA[Communities]]></category>
		<category><![CDATA[BeyondRelational]]></category>
		<category><![CDATA[konkurs]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[TSQL Challenges]]></category>

		<guid isPermaLink="false">http://sqlgeek.pl/?p=510</guid>
		<description><![CDATA[ Jakiś czas temu wysłałem rozwiązanie jednej z zagadek Itzika Ben-Gana z serii “T-SQL Puzzle” (zagadki były publikowane na witrynie SQL Server Magazine). Wtedy pomyślałem, że byłoby fajnie, gdyby takie zagadki / konkursy, w których uczestnicy mogliby poćwiczyć szare komórki i rozwijać umiejętności programowania w T-SQL, były organizowane częściej. I oto, za jakiś czas trafiłem [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://sqlgeek.pl/wp-content/uploads/2010/09/tc.png"><img style="margin: 0px 0px 10px 10px; display: inline; border: 0px;" title="image" src="http://sqlgeek.pl/wp-content/uploads/2010/09/tc.png" border="0" alt="image" align="right" /></a> Jakiś czas temu wysłałem rozwiązanie jednej z zagadek <a href="http://www.sql.co.il/">Itzika Ben-Gana</a> z serii “T-SQL Puzzle” (zagadki były publikowane na witrynie <a href="http://www.sqlmag.com">SQL Server Magazine</a>). Wtedy pomyślałem, że byłoby fajnie, gdyby takie zagadki / konkursy, w których uczestnicy mogliby poćwiczyć szare komórki i rozwijać umiejętności programowania w T-SQL, były organizowane częściej. I oto, za jakiś czas trafiłem na witrynę <a href="http://beyondrelational.com/">ByeondRelational.com</a> prowadzoną przez <a href="http://beyondrelational.com/blogs/jacob/default.aspx">Jacoba Sebastiana</a> (SQL Server MVP) i kilku innych SQL-owych zapaleńców.</p>
<p>Jednym z działów BeyondRelational.com (oprócz licznych blogów i forum) jest dział <a href="http://beyondrelational.com/tc"><strong>TSQL Challenges</strong></a>. Czym są TSQL Challenges (dalej używam skrótu <strong>TC</strong>)? Są to konkursy polegające na rozwiązywaniu problemów za pomocą zapytań w języku T-SQL (nowe zadanie jest ogłaszane raz na dwa tygodnie). Udział może wziąć każdy, kto ma na to ochotę (i zarejestruje się na portalu BeyondRelational.com). Zazwyczaj zadania wymagają rozwiązania postawionego problemu jednym zapytaniem SELECT (choć na ogół dopuszczalne jest używanie podzapytań i CTE), bez użycia tabel tymczasowych i dynamicznego kodu T-SQL. Zwycięża ten uczestnik, który podeśle rozwiązanie generujące poprawny wynik, spełniające podane wymagania i o najlepszych statystykach (liczy się nie tylko czas wykonania, ale także zużycie CPU oraz ilość odczytów i zapisów). Więcej o samych TSQL Challenges i o możliwości nadsyłania własnych propozycji zadań konkursowych czytaj tu: <a href="http://beyondrelational.com/blogs/tc/pages/submit-a-tsql-challenge-idea.aspx">Submit a TSQL Challenge Idea</a>.</p>
<p>Zabawa jest przednia. Sam spróbowałem. Wysłałem nawet ze trzy rozwiązania zadań, ale z uwagi na to, że jak dotąd nie dałem się wciągnąć na dobre w zabawę (co by to było, jakbym jeszcze w TC dał się wciągnąć :-P), moje próby kończą się w przedbiegach po wysłaniu pierwszego rozwiązania, które uznam za “good enough” (a to jest zdecydowanie za mało na takich zawodników, jacy wysyłają swoje rozwiązania na TC) :-) Co lepsi zawodnicy nadsyłają po kilka rozwiązań wymyślając takie rozwiązania, z których można się uczyć wszystkiego, co potrzebne programiście SQL Servera: od algorytmów, przez optymalizację, aż po wymyślne chwyty do zastosowania w kodzie T-SQL. Co ciekawe, jest też wersja “light” konkursu przeznaczona dla początkujących adeptów sztuki programowania w T-SQL – <a href="http://beyondrelational.com/blogs/tcb/">TSQL Beginners Challenges</a>.</p>
<p>Wśród najlepszych uczestników zabawy w “dorosłe” TC znaleźć można kilku Polaków. Dwóch z nich zaprosiłem do rozmowy o TC. Zgodzili się (dzięki, chłopaki!), a zapis wywiadu znajdziesz poniżej.</p>
<p>&#8211;</p>
<p>Moimi rozmówcami są <strong>Leszek Gniadkowski</strong> (w wywiadzie jako LG) oraz <strong>Marek Powichrowski</strong> (w wywiadzie jako MP).</p>
<p>Leszek zawodowo pracuje jako członek zespołu administrującego dosyć dużą domeną Active Directory. Specjalizuje się w systemach opartych na MS Windows, choć ma do czynienia również z innymi OS przy okazji integracji AD z usługami opartymi na *NIX/Linux.</p>
<p>Marek zawodowo pracuje jako programista i konsultant systemów ERP. Specjalizuje się w projektowaniu baz danych, głównie SQL Server. Pisze aplikacje w .NET, nie unika ASP.NET. Lubi projektować sałatki śledziowe i piec chleb na własnym zakwasie.</p>
<p>&#8211;</p>
<p><strong>PP: Witajcie. Na początek gratulacje na okazję Waszych sukcesów w konkursach TSQL Challenges!</strong></p>
<p>LG: <em>Witam, dziękujemy, szczęśliwie trwa passa </em>(przyp. PP – Leszek jest ex aequo pierwszy w rankingu TC!) <em>, największym sukcesem jest jednak sama wiedza nabyta przy udziale w TC.</em></p>
<p>MP: <em>Dzięki, to miłe. Na razie mam 13 SQL Stars i mogę już sobie zrobić T-Shirt’a z logo „TSQL Challenges Winner” :-) A i jeszcze mogę sobie wydrukować certyfikat potwierdzający ten fakt. To takie drobiazgi, ale miłe.</em></p>
<p><strong>PP: Skąd dowiedzieliście się o konkursach TSQL Challenges i witrynie beyondrelational.com? </strong></p>
<p>LG: <em>W moim przypadku z forum portalu </em><a href="http://wss.pl/Default.aspx"><em>WSS</em></a><em>. Dokładniej </em><a href="http://wss.pl/frmThread.aspx?id=436139"><em>stąd</em></a><em>. Od czasu umieszczenia tego wątku (trwał wtedy TC20), rozpocząłem naukę TSQL i próbowałem sił w następnych TC.</em></p>
<p>MP: <em>W moim przypadku było dokładnie tak samo. Tamto zadanie zelektryzowało całe forum SQL Server na WSS.pl. Interesujące było to, że trzeba to rozwiązać w jednym zapytaniu. Pamiętam, że podobny problem rzucił kiedyś Maciej Pilecki. Piękne wyzwanie. Wysłałem swoje rozwiązanie i niejakim szokiem było to, że trzeba długo czekać na wyniki rywalizacji. Ale przeszedłem wszystkie fazy (basic test, tricky data i load test) i ostatecznie byłem sklasyfikowany poza pierwszą 10-tką, ale jak na początek to i tak było coś. Potem była przerwa i Leszek odezwał się do mnie przy zadaniu TC28, które miało bardzo mało zgłoszonych rozwiązań. Mi poszło gładko i przeszło dwie pierwsze fazy testów i kiedy już byłem w „ogródku i już witałem się z gąską” przepadłem w load test. To sparzenie się nakazuje mi teraz przyglądać się baczniej wydajności. Ale co ciekawe, Leszek który wygrał tę odsłonę był tym kompletnie zaskoczony bo wstępne porównania statystyk na naszych danych testowych dawały mi przewagę. Ale dane do load test odwróciły tę relację. Także emocje są do samego końca. Od zadania TC28 wciągnąłem się. Wykonałem jeszcze dwa zadania w tył i byłem wśród zwycięzców i od tej pory nie odpuszczam żadnego zadania.</em></p>
<p><strong>PP: Co takiego jest w TSQL Challenges, że poświęcacie czas na podejmowanie kolejnych „wyzwań”?</strong></p>
<p>MP: <em>To głód tego pięknego momentu olśnienia, gdy znajduje się rozwiązanie proste, z pięknymi statystykami. To głód tych endorfin, które zalewają człowieka powodując, że wszystko wokoło nagle staje się piękne i nic nie jest w stanie tego zakłócić. A poza tym to świetne zajęcie dla umysłu aby przypadkiem nie zachciałoby mu się spuścić z tonu.</em></p>
<p>LG: <em>Dobra rozrywka umysłowa, sprawdzanie się, rywalizacja. TC w pewnym stopniu uzależniają. Mix samego języka TSQL i zakręconych zadań to mieszanka gwarantująca intelektualną ucztę. Co do samego czasu, jego większość nie jest spędzona bezpośrednio przy komputerze. Nad zadaniem często myślę przy okazji, w czasie wykonywania dowolnej czynności: jazdy samochodem, posiłku, przed snem itd. Samo kodowanie zajmuje już zwykle mniej czasu.</em></p>
<p><strong>PP: Jak dużo czasu poświęcacie średnio na stworzenie rozwiązania gotowego do zgłoszenia w konkursie i czy zdarza się, że wysyłacie więcej niż jedno rozwiązanie?</strong></p>
<p>LG: <em>Różnie, od 30 minut do dwóch tygodni na stworzenie rozwiązania, które „działa”. Najczęściej parę godzin. Później pracuje się nad ulepszeniem bądź innym podejściem do problemu podkręcającym statystyki. Zdarzało się, że były TC, do których z braku czasu podchodziłem w ostatni dzień przed terminem zakończenia, poświęcając niedzielę. Czasami wysyłam jedną wersję rozwiązania, czasami dwie i więcej. Natomiast prawie zawsze wysyłam poprawione rozwiązania spamując trochę upload.</em></p>
<p>MP: <em>Różnie z tym bywa. Niektóre pozornie trudne rozwiązują się błyskawicznie w kilku wersjach. Inne kosztują sporo czasu. Jeżeli mam kilka rozwiązań to oczywiście je wysyłam. Trzeba pamiętać, że każde rozwiązanie zadania przechodzi przez trzy fazy weryfikacji: basic test – czyli weryfikacja rozwiązania danymi podanymi przy zadaniu, tricky data – weryfikacja danymi „pokręconymi” w celu testowania odporności rozwiązania na zakłócenia no i na koniec load test, który może wyeliminować z gry. Więc każda dodatkowa wersja rozwiązania to szansa na „przyżycie” w turnieju.</em></p>
<p><strong>PP: Który TSQLChallenge z dotychczasowych najbardziej przypadł Wam do gustu i dlaczego?</strong></p>
<p>MP: <em>Bezwzględnie <a href="http://beyondrelational.com/blogs/tc/archive/2010/08/23/tsql-challenge-37-calculate-the-downtime-and-duration-of-servers-based-on-the-monitoring-log.aspx">TC37</a>! To zadanie najbardziej mnie zmęczyło ale też dało najwięcej radości gdy się wykluło wreszcie z poszukiwań mego umysłu. W samo rozwiązanie mogę się gapić i podziwiać jakie sprytne i szybkie rzeczy można robić w T-SQL-u (nawet bez użycia indeksów). Mam porównanie bo moja pierwsza wersja rozwiązania tego zadania była tragiczna pod względem wydajnościowym i to o kilka rzędów wielkości. Obserwując rozwiązania konkursowe widać, jaki power ma T-SQL, jak bardzo elastycznym jest językiem. </em></p>
<p>LG: <em>Trudno wybrać, ale wybrałbym </em><a href="http://beyondrelational.com/blogs/tc/archive/2010/04/19/tsql-challenge-28-select-top-n-articles-from-each-category-from-a-sql-server-2000-database.aspx"><em>TC28</em></a><em> </em>(przyp. PP – Leszek wygrał ten TC!)<em>. Za kompletną pustkę w głowie po zapoznaniu się z zadaniem i wiele prób wypełnienia tej pustki kierunkiem zmierzającym do utworzenia sensownej solucji.</em></p>
<p><strong>PP: Wspominaliście mi, że wzajemnie się „nakręcacie” w czasie konkursów. W jaki sposób?</strong></p>
<p>LG: <em>Wymieniamy się statystykami, uwagami na temat TC, możliwymi „tricky data”. Jeżeli wiem, że Marek zadanie zrobił z lepszymi statystykami niż uzyskałem, mam powód do szukania innego rozwiązania. Korzystamy też z forum, jako źródła statystyk, jak i wielu dodatkowych uwag, czy omawiania samych założeń do TC.</em></p>
<p>MP: <em>Tak to prawda. Wymieniamy się ze sobą statystykami i powoduje to sportową żyłkę rywalizacyjna między nami. A poza tym przez te kilka miesięcy kontaktów mogliśmy się lepiej poznać nie tylko na polu T-SQL’a ale również zainteresowań w innych technologiach, na przykład w robieniu własnego chleba na własnym zakwasie, piwa, jogurtu, przyrządzaniu sałatek ze śledzi. I to jest ta wartość dodana uczestnictwa w tych zawodach.</em></p>
<p><strong>PP: Gdybyście mieli mnie zachęcić do udziału w konkursach TSQLChallenge, co byście mi powiedzieli?</strong></p>
<p>MP: <em>Poza zdobywaniem doświadczenia w trudnych wyzwaniach oraz podglądaniem i uczeniem się efektownych technik innych uczestników nie mniej istotna jest żyłka sportowa towarzysząca turniejowi. Co prawda same emocje są rozłożone w czasie tak bardzo, że można je porównać do emocji towarzyszących turniejowi szachowemu, ale jeżeli masz żyłkę sportową, która drga w Tobie, to niewątpliwie Twoje miejsce jest na TC!</em></p>
<p>LG: <em>TC to dobre miejsce do nauki i rozwijania umiejętności w kodowaniu TSQL. W odróżnieniu od kursów i książek, które często przekazują wiedzę w sposób nudny, schematyczny, TC ukazują problem do rozwiązania, nie podają wiedzy na tacy, tylko zmuszają do samodzielnego jej poszukiwania, intensyfikują proces myślenia i umożliwiają dużo szybsze wchłanianie wiedzy. TC są również znakomitym workiem treningowym dla szarych komórek (ostatni raz ten specyficzny poziom endorfin uzyskałem w szkole średniej rozwiązując trudniejsze całki ;-) ).</em></p>
<p><strong>PP: Dziękuję za wywiad i powodzenia w kolejnych „wyzwaniach”!</strong></p>
<p>LG: <em>A ja dziękuję za zaproszenie, miłą rozmowę i poparcie w dalszych zmaganiach z tsql’owym puzzle.</em></p>
<p>MP: <em>Dzięki i do zobaczenia przy okazji kolejnych wyzwań T-SQL z również Twoim udziałem.</em></p>
<p>&#8211;</p>
<p>A zatem, jeżeli kręci Cię zdrowe współzawodnictwo, chcesz poćwiczyć szare komórki i przy okazji potrenować pisanie kodu T-SQL, spróbuj swoich sił w TSQL Challenges. Obserwując Marka i Leszka muszę Cię jedynie ostrzec, że to wciąga jak diabli :-) Ale jeśli jeszcze nie masz swojego ulubionego uzależnienia… ;-)</p>
<p>I na koniec – chcę wyrazić szacunek dla osób prowadzących portal BeyondRelational.com i konkursy TC. Publikować co dwa tygodnie nowe zadanie, czuwać nad rozwojem sytuacji w każdym konkursie, robić testy nadesłanych rozwiązań i panować nad tym wszystkim, to naprawdę duże wyzwanie dla organizatorów. I jak na razie im się to udaje! Stworzyli atmosferę zdrowej rywalizacji i swego rodzaju społeczność uczestników zabawy. Brawo za ideę i jej realizację.</p>
<p>&#8211;</p>
<p>PS. A już zupełnie na koniec pragnę nadmienić, że ten wywiad jest swego rodzaju zapowiedzią mojego własnego, jednorazowego konkursu a la TC, który zorganizuję na blogu. Szczegóły w drugiej połowie września. Stay tuned!</p>
<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
<li class="shr-comfeed">
			<a href="http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
<li class="shr-twitter">
			<a href="http://twitter.com/home?status=%5BPL%5D+Wywiad+-+nasi+na+TSQL+Challenges+-+http://b2l.me/annzwm&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/&amp;t=%5BPL%5D+Wywiad+-+nasi+na+TSQL+Challenges" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/&amp;title=%5BPL%5D+Wywiad+-+nasi+na+TSQL+Challenges&amp;summary=%20Jaki%C5%9B%20czas%20temu%20wys%C5%82a%C5%82em%20rozwi%C4%85zanie%20jednej%20z%20zagadek%20Itzika%20Ben-Gana%20z%20serii%20%E2%80%9CT-SQL%20Puzzle%E2%80%9D%20%28zagadki%20by%C5%82y%20publikowane%20na%20witrynie%20SQL%20Server%20Magazine%29.%20Wtedy%20pomy%C5%9Bla%C5%82em%2C%20%C5%BCe%20by%C5%82oby%20fajnie%2C%20gdyby%20takie%20zagadki%20%2F%20konkursy%2C%20w%20kt%C3%B3rych%20uczestnicy%20mogliby%20po%C4%87wiczy%C4%87%20szare%20kom%C3%B3rki%20i%20rozwij&amp;source=SQLGeek.pl" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/&amp;title=%5BPL%5D+Wywiad+-+nasi+na+TSQL+Challenges" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/&amp;title=%5BPL%5D+Wywiad+-+nasi+na+TSQL+Challenges" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/&amp;title=%5BPL%5D+Wywiad+-+nasi+na+TSQL+Challenges&amp;srcUrl=http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/&amp;srcTitle=%5BPL%5D+Wywiad+-+nasi+na+TSQL+Challenges&amp;snippet=%20Jaki%C5%9B%20czas%20temu%20wys%C5%82a%C5%82em%20rozwi%C4%85zanie%20jednej%20z%20zagadek%20Itzika%20Ben-Gana%20z%20serii%20%E2%80%9CT-SQL%20Puzzle%E2%80%9D%20%28zagadki%20by%C5%82y%20publikowane%20na%20witrynie%20SQL%20Server%20Magazine%29.%20Wtedy%20pomy%C5%9Bla%C5%82em%2C%20%C5%BCe%20by%C5%82oby%20fajnie%2C%20gdyby%20takie%20zagadki%20%2F%20konkursy%2C%20w%20kt%C3%B3rych%20uczestnicy%20mogliby%20po%C4%87wiczy%C4%87%20szare%20kom%C3%B3rki%20i%20rozwij" rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
<li class="shr-gmail">
			<a href="https://mail.google.com/mail/?ui=2&amp;view=cm&amp;fs=1&amp;tf=1&amp;su=%5BPL%5D+Wywiad+-+nasi+na+TSQL+Challenges&amp;body=Link: http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A %20Jaki%C5%9B%20czas%20temu%20wys%C5%82a%C5%82em%20rozwi%C4%85zanie%20jednej%20z%20zagadek%20Itzika%20Ben-Gana%20z%20serii%20%E2%80%9CT-SQL%20Puzzle%E2%80%9D%20%28zagadki%20by%C5%82y%20publikowane%20na%20witrynie%20SQL%20Server%20Magazine%29.%20Wtedy%20pomy%C5%9Bla%C5%82em%2C%20%C5%BCe%20by%C5%82oby%20fajnie%2C%20gdyby%20takie%20zagadki%20%2F%20konkursy%2C%20w%20kt%C3%B3rych%20uczestnicy%20mogliby%20po%C4%87wiczy%C4%87%20szare%20kom%C3%B3rki%20i%20rozwij" rel="nofollow" class="external" title="Email this via Gmail">Email this via Gmail</a>
		</li>
<li class="shr-googlebookmarks">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/&amp;title=%5BPL%5D+Wywiad+-+nasi+na+TSQL+Challenges" rel="nofollow" class="external" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
<li class="shr-hotmail">
			<a href="http://mail.live.com/?rru=compose?subject=%5BPL%5D+Wywiad+-+nasi+na+TSQL+Challenges&amp;body=Link: http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A %20Jaki%C5%9B%20czas%20temu%20wys%C5%82a%C5%82em%20rozwi%C4%85zanie%20jednej%20z%20zagadek%20Itzika%20Ben-Gana%20z%20serii%20%E2%80%9CT-SQL%20Puzzle%E2%80%9D%20%28zagadki%20by%C5%82y%20publikowane%20na%20witrynie%20SQL%20Server%20Magazine%29.%20Wtedy%20pomy%C5%9Bla%C5%82em%2C%20%C5%BCe%20by%C5%82oby%20fajnie%2C%20gdyby%20takie%20zagadki%20%2F%20konkursy%2C%20w%20kt%C3%B3rych%20uczestnicy%20mogliby%20po%C4%87wiczy%C4%87%20szare%20kom%C3%B3rki%20i%20rozwij" rel="nofollow" class="external" title="Email this via Hotmail">Email this via Hotmail</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sqlgeek.pl/2010/09/01/pl-wywiad-nasi-na-tsql-challenges/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>[PL] SQL Server – FOR XML EXPLICIT (nie) dla opornych</title>
		<link>http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/</link>
		<comments>http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 04:38:47 +0000</pubDate>
		<dc:creator>Pawel Potasinski</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[FOR XML EXPLICIT]]></category>
		<category><![CDATA[T-SQL]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://sqlgeek.pl/?p=491</guid>
		<description><![CDATA[Klauzula FOR XML EXPLICIT jest bodaj najrzadziej używaną z klauzul FOR XML. O wiele częściej decydujemy się na użycie FOR XML PATH (od SQL Server 2005) lub FOR XML AUTO (SQL Server 2000), ponieważ obie klauzule wydają się prostsze w użyciu niż FOR XML EXPLICIT. Ale mało kto bierze pod uwagę, że FOR XML EXPLICIT daje – jako jedna z dwóch klauzul FOR XML na SQL Server 2005 i nowszych oraz jako jedyna klauzula na SQL Server 2000 – możliwość zwracania dokumentów XML, w których znajdą się zarówno elementy, jak i atrybuty. A już prawie nikt nie wie, że jedynie FOR XML EXPLICIT umożliwia generowanie dokumentów XML zawierających sekcje CDATA. I to właśnie owo niedocenianie i unikanie klauzuli FOR XML EXPLICIT skłoniło mnie do napisania tego tekstu.]]></description>
			<content:encoded><![CDATA[<h4>Wstęp</h4>
<p>Klauzula FOR XML EXPLICIT jest bodaj najrzadziej używaną z klauzul FOR XML. O wiele częściej decydujemy się na użycie FOR XML PATH (od SQL Server 2005) lub FOR XML AUTO (SQL Server 2000), ponieważ obie klauzule wydają się prostsze w użyciu niż FOR XML EXPLICIT (jak to okreslił jeden z moich kolegów &#8211; &#8220;FOR XML EXPLICIT przy FOR XML PATH wygląda jak neanderltalczyk przy homo sapiens&#8221;). Ale mało kto bierze pod uwagę, że FOR XML EXPLICIT daje – jako jedna z dwóch klauzul FOR XML na SQL Server 2005 i nowszych oraz jako jedyna klauzula na SQL Server 2000 – możliwość zwracania dokumentów XML, w których znajdą się zarówno elementy, jak i atrybuty. A już prawie nikt nie wie, że jedynie FOR XML EXPLICIT umożliwia generowanie dokumentów XML zawierających sekcje CDATA. I to właśnie owo niedocenianie i unikanie klauzuli FOR XML EXPLICIT skłoniło mnie do napisania tego tekstu.</p>
<table style="background-color: #ffffcc; border: black 1px solid;" cellspacing="0" cellpadding="10" width="100%">
<tbody>
<tr>
<td width="100%" valign="top">W tym miejscu robię delikatne założenie – zakładam mianowicie, że wiesz, czym jest XML, co to znaczy, że dokument XML jest “well-formed”, czym się różni element od atrybutu. Jeżeli te pojęcia są Ci obce, dalsza część tego wpisu nie jest dla Ciebie (najpierw poczytaj o podstawach XML-a, a dopiero potem baw się XML-em w SQL Serverze).</td>
</tr>
</tbody>
</table>
<h4>Generujemy poligon</h4>
<p>Załóżmy, że mamy dwie, uproszczone do granic możliwości, powiązane ze sobą logicznie tabele – #Faktury i #Pozycje. Tabela #Faktury zawiera typowe dane nagłówkowe faktur – numer faktury, datę wystawienia i nazwę kontrahenta. Tabela #Pozycje zawiera pozycje (linijki) faktury, w których znajdują się: numer faktury (aby było łatwo powiązać pozycje z fakturami), numer pozycji na fakturze (takie typowe Lp), nazwę produktu, cenę (dla uproszczenia bez rozgraniczenia na netto i brutto oraz z pominięciem VAT-u) oraz ilość towaru. Kod do utworzenia tabel i wypełnienia ich danymi dwóch przykładowych faktur:</p>
<pre class="csharpcode"><span class="kwrd">IF</span> OBJECT_ID(N<span class="str">'tempdb.dbo.#Faktury'</span>) <span class="kwrd">IS</span> <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>
  <span class="kwrd">DROP</span> <span class="kwrd">TABLE</span> #Faktury;
<span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> #Faktury (
  NrFaktury <span class="kwrd">varchar</span>(10),
  DataWystawienia datetime,
  Kontrahent <span class="kwrd">varchar</span>(100)
);

<span class="kwrd">IF</span> OBJECT_ID(N<span class="str">'tempdb.dbo.#Pozycje'</span>) <span class="kwrd">IS</span> <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>
  <span class="kwrd">DROP</span> <span class="kwrd">TABLE</span> #Pozycje;
<span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> #Pozycje (
  NrFaktury <span class="kwrd">varchar</span>(10),
  NrPozycji <span class="kwrd">int</span>,
  Produkt <span class="kwrd">varchar</span>(50),
  Ilosc <span class="kwrd">int</span>,
  Cena money
);

INSERT <span class="kwrd">INTO</span> #Faktury (NrFaktury, DataWystawienia, Kontrahent)
<span class="kwrd">SELECT</span> <span class="str">'04/07/2010'</span>,<span class="str">'20100716'</span>,<span class="str">'FirmaA'</span>
<span class="kwrd">UNION</span> <span class="kwrd">ALL</span>
<span class="kwrd">SELECT</span> <span class="str">'05/07/2010'</span>,<span class="str">'20100716'</span>,<span class="str">'FirmaB'</span>;

INSERT <span class="kwrd">INTO</span> #Pozycje (NrFaktury, NrPozycji, Produkt, Ilosc, Cena)
<span class="kwrd">SELECT</span> <span class="str">'04/07/2010'</span>,1,<span class="str">'Produkt1'</span>,10,100.00
<span class="kwrd">UNION</span> <span class="kwrd">ALL</span>
<span class="kwrd">SELECT</span> <span class="str">'04/07/2010'</span>,2,<span class="str">'Produkt2'</span>,2,10.00
<span class="kwrd">UNION</span> <span class="kwrd">ALL</span>
<span class="kwrd">SELECT</span> <span class="str">'04/07/2010'</span>,3,<span class="str">'Produkt3'</span>,1,10.50
<span class="kwrd">UNION</span> <span class="kwrd">ALL</span>
<span class="kwrd">SELECT</span> <span class="str">'05/07/2010'</span>,1,<span class="str">'Produkt1'</span>,5,10.00
<span class="kwrd">UNION</span> <span class="kwrd">ALL</span>
<span class="kwrd">SELECT</span> <span class="str">'05/07/2010'</span>,2,<span class="str">'Produkt3'</span>,1,10.50;</pre>
<h4>FOR XML EXPLICIT krok po kroku</h4>
<p>Postawmy sobie pierwsze zadanie.</p>
<p><strong>Zadanie:</strong> użyć klauzuli FOR XML EXPLICIT w zapytaniu odwołującym się do powyższych dwóch tabel, by uzyskać w wyniku dokument XML o następującej postaci:</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">Faktura</span> <span class="attr">Numer</span><span class="kwrd">="04/07/2010"</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">DataWystawienia</span><span class="kwrd">&gt;</span>2010-07-16T00:00:00<span class="kwrd">&lt;/</span><span class="html">DataWystawienia</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">Kontrahent</span><span class="kwrd">&gt;</span>FirmaA<span class="kwrd">&lt;/</span><span class="html">Kontrahent</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">Pozycja</span> <span class="attr">NrPozycji</span><span class="kwrd">="1"</span> <span class="attr">Produkt</span><span class="kwrd">="Produkt1"</span> <span class="attr">Cena</span><span class="kwrd">="100.0000"</span> <span class="attr">Ilosc</span><span class="kwrd">="10"</span> <span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">Pozycja</span> <span class="attr">NrPozycji</span><span class="kwrd">="2"</span> <span class="attr">Produkt</span><span class="kwrd">="Produkt2"</span> <span class="attr">Cena</span><span class="kwrd">="10.0000"</span> <span class="attr">Ilosc</span><span class="kwrd">="2"</span> <span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">Pozycja</span> <span class="attr">NrPozycji</span><span class="kwrd">="3"</span> <span class="attr">Produkt</span><span class="kwrd">="Produkt3"</span> <span class="attr">Cena</span><span class="kwrd">="10.5000"</span> <span class="attr">Ilosc</span><span class="kwrd">="1"</span> <span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">Faktura</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">Faktura</span> <span class="attr">Numer</span><span class="kwrd">="05/07/2010"</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">DataWystawienia</span><span class="kwrd">&gt;</span>2010-07-16T00:00:00<span class="kwrd">&lt;/</span><span class="html">DataWystawienia</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">Kontrahent</span><span class="kwrd">&gt;</span>FirmaB<span class="kwrd">&lt;/</span><span class="html">Kontrahent</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">Pozycja</span> <span class="attr">NrPozycji</span><span class="kwrd">="1"</span> <span class="attr">Produkt</span><span class="kwrd">="Produkt1"</span> <span class="attr">Cena</span><span class="kwrd">="10.0000"</span> <span class="attr">Ilosc</span><span class="kwrd">="5"</span> <span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">Pozycja</span> <span class="attr">NrPozycji</span><span class="kwrd">="2"</span> <span class="attr">Produkt</span><span class="kwrd">="Produkt3"</span> <span class="attr">Cena</span><span class="kwrd">="10.5000"</span> <span class="attr">Ilosc</span><span class="kwrd">="1"</span> <span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">Faktura</span><span class="kwrd">&gt;</span></pre>
<p><strong>Rozwiązanie:</strong></p>
<pre class="csharpcode"><span class="kwrd">SELECT</span>
  1 <span class="kwrd">AS</span> Tag,
  <span class="kwrd">NULL</span> <span class="kwrd">AS</span> Parent,
  F.NrFaktury AS [Faktura!1!Numer],
  F.DataWystawienia AS [Faktura!1!DataWystawienia!ELEMENT],
  F.Kontrahent AS [Faktura!1!Kontrahent!ELEMENT],
  <span class="kwrd">NULL AS</span> [Pozycja!2!NrPozycji],
  <span class="kwrd">NULL AS</span> [Pozycja!2!Produkt],
  <span class="kwrd">NULL AS</span> [Pozycja!2!Cena],
  <span class="kwrd">NULL AS</span> [Pozycja!2!Ilosc]
<span class="kwrd">FROM</span> #Faktury F
<span class="kwrd">UNION</span> <span class="kwrd">ALL</span>
<span class="kwrd">SELECT</span>
  2,
  1,
  P.NrFaktury,
  <span class="kwrd">NULL</span>,
  <span class="kwrd">NULL</span>,
  P.NrPozycji,
  P.Produkt,
  P.Cena,
  P.Ilosc
<span class="kwrd">FROM</span> #Pozycje P
<span class="kwrd">ORDER</span> <span class="kwrd">BY</span> [Faktura!1!Numer], Tag, [Pozycja!2!NrPozycji]
<span class="kwrd">FOR</span> XML EXPLICIT;</pre>
<p><strong>Komentarz (krok po kroku):</strong></p>
<p>Aby zrozumieć, jak działa FOR XML EXPLICIT, uruchom najpierw kod powyższego zapytania bez klauzuli FOR XML EXPLICIT. Wynik powinien wyglądać następująco:</p>
<p><a href="http://sqlgeek.pl/wp-content/uploads/2010/08/image8.png"><img style="display: inline; border-width: 0px;" title="image" src="http://sqlgeek.pl/wp-content/uploads/2010/08/image_thumb8.png" border="0" alt="image" width="640" height="120" /></a></p>
<p>Kolorami żółtym i zielonym zaznaczyłem obie faktury i ich pozycje (wiersze zawierające dane nagłówkowe są oznaczone ciemniejszymi odcieniami).</p>
<p>Zwróć uwagę na kolejność wierszy. Nieprzypadkowo wiersze pozycji znajdują się tuż za wierszem nagłówka odpowiadającej pozycjom faktury.<strong> Sortowanie jest kluczem do sukcesu w zapytaniach z FOR XML EXPLICIT</strong>. W tym przypadku dane zostały posortowane względem kolejno: numeru faktury (tu bardzo ważna uwaga – zauważ, że <strong>w drugim zapytaniu SELECT wybierającym pozycje faktur także wybieram numer faktury – zapewniam w ten sposób wspólną kolumnę dla wszystkich wierszy wynikowych zapytania</strong>), kolumny Tag (o której za chwilę, a dzięki której wiersze nagłówków znajdują się w wyniku przed wierszami pozycji) oraz numeru pozycji (dzięki temu w dokumencie XML pozycje dla każdej faktury będą umieszczone zgodnie z kolejnością na fakturze). To uporządkowanie rekordów jest ważne, ponieważ FOR XML EXPLICIT najpierw buduje taką tabelę, a następnie działa na niej niczym kursor – buduje dokument XML doklejając odpowiednio spreparowane dane z kolejnych wierszy ujęte w elementy i atrybuty. To od kolejności wierszy zależy postać wynikowego dokumentu XML.</p>
<p>Zapytanie składa się z dwóch zapytań SELECT połączonych operatorem UNION ALL. W każdym z dwóch zapytań liczba kolumn jest taka sama (to oczywiste, bo takie są wymagania operatora UNION). Pierwsze dwie kolumny – <strong>Tag</strong> i <strong>Parent </strong>- są kolumnami specjalnymi umożliwiającymi poprawne działanie klauzuli FOR XML EXPLICIT. Każde zapytanie otrzymuje swój numer (Tag, wcale nie musi być unikalny) oraz numer “rodzica” (Parent, jeżeli jest NULL, rodzica nie ma). Numery te decydują, gdzie w strukturze wynikowego dokumentu XML zostaną umieszczone dane z poszczególnych wierszy.</p>
<p>Prześledźmy na podstawie dwóch pierwszych wierszy pokazanych poniżej, jak budowany jest wynikowy dokument XML.</p>
<p><a href="http://sqlgeek.pl/wp-content/uploads/2010/08/image9.png"><img style="display: inline; border-width: 0px;" title="image" src="http://sqlgeek.pl/wp-content/uploads/2010/08/image_thumb9.png" border="0" alt="image" width="640" height="45" /></a></p>
<p>Na początek brany jest pierwszy rekord. Dla niego w kolumnie Tag widnieje wartość 1. SQL Server szuka w tym wierszu, gdzie znajdują się wartości w kolumnach, które mają znacznik 1 w nazwie (np. Faktura!1!Numer). Nazwy kolumn decydują o tym, do którego Tag-a zalicza się wartość oraz jak będą nazywały się elementy / atrybuty. Jeżeli na końcu nazwy kolumny pojawi się słowo ELEMENT, wartość będzie umieszczona w elemencie (inaczej znajdzie się w atrybucie). Dla pierwszego wiersza SQL Server buduje więc coś takiego:</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">Faktura</span> <span class="attr">Numer</span><span class="kwrd">="04/07/2010"</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">DataWystawienia</span><span class="kwrd">&gt;</span>2010-07-16T00:00:00<span class="kwrd">&lt;/</span><span class="html">DataWystawienia</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">Kontrahent</span><span class="kwrd">&gt;</span>FirmaA<span class="kwrd">&lt;/</span><span class="html">Kontrahent</span><span class="kwrd">&gt;</span></pre>
<p>Nazwy kolumn zdecydowały, że elementem nadrzędnym jest &lt;Faktura&gt;, numer faktury znalazł się w atrybucie Numer, data wystawienia faktury w elemencie &lt;DataWystawienia&gt;, a nazwa kontrahenta w elemencie &lt;Kontrahent&gt;.</p>
<p>Następnie brany jest drugi wiersz. W nim w kolumnie Tag SQL Server znajduje wartość 2, zatem uwzględnia w tym wierszu tylko te kolumny, w których nazwach występuje znacznik 2 (np, Pozycja!2!NrPozycji). Ponieważ w kolumnie Parent znajduje się wartość 1, a poprzedni wiersz miał Tag równy 1 (patrz czerwona strzałka na rysunku obrazującym wiersze), SQL Server wie, że XML powstały z bieżącego wiersza należy zagnieździć w XML-u powstałym z poprzedniego wiersza. Dzięki temu dokument zbudowany z dwóch wierszy wygląda tak:</p>
<pre class="csharpcode">&lt;Faktura Numer="04/07/2010"&gt;
  &lt;DataWystawienia&gt;2010-07-16T00:00:00&lt;/DataWystawienia&gt;
  &lt;Kontrahent&gt;FirmaA&lt;/Kontrahent&gt;
<span style="color: #ff0000;">  &lt;Pozycja NrPozycji="1" Produkt="Produkt1" Cena="100.0000" Ilosc="10" /&gt;</span></pre>
<p>I tak kolejne pozycje będą doklejane wewnątrz znacznika &lt;Faktura&gt;, aż zostanie napotkany wiersz, w którym w kolumnie Tag będzie znajdowała się wartość 1 (będzie to początek następnej faktury). Wówczas element &lt;Faktura&gt; otwarty przy tworzeniu XML-a z pierwszego wiersza zostanie zamknięty, czyli pojawi sie koniec elementu &#8211; &lt;/Faktura&gt;.</p>
<h4>FOR XML EXPLICIT – tips &amp; tricks</h4>
<p>A teraz spróbujmy zmodyfikować nieco zadanie.</p>
<p><strong>Zadanie:</strong> użyć klauzuli FOR XML EXPLICIT w zapytaniu odwołującym się do tabel #Faktury i #Pozycje, by uzyskać w wyniku dokument XML o następującej postaci:</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">Faktura</span> <span class="attr">Numer</span><span class="kwrd">="04/07/2010"</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">DataWystawienia</span><span class="kwrd">&gt;</span>2010-07-16T00:00:00<span class="kwrd">&lt;/</span><span class="html">DataWystawienia</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">Kontrahent</span><span class="kwrd">&gt;</span>FirmaA<span class="kwrd">&lt;/</span><span class="html">Kontrahent</span><span class="kwrd">&gt;</span>
<span style="color: #ff0000;">  <span class="kwrd">&lt;</span><span class="html">Pozycje</span><span class="kwrd">&gt;</span></span>
    <span class="kwrd">&lt;</span><span class="html">Pozycja</span> <span class="attr">NrPozycji</span><span class="kwrd">="1"</span> <span class="attr">Produkt</span><span class="kwrd">="Produkt1"</span> <span class="attr">Cena</span><span class="kwrd">="100.0000"</span> <span class="attr">Ilosc</span><span class="kwrd">="10"</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">Pozycja</span> <span class="attr">NrPozycji</span><span class="kwrd">="2"</span> <span class="attr">Produkt</span><span class="kwrd">="Produkt2"</span> <span class="attr">Cena</span><span class="kwrd">="10.0000"</span> <span class="attr">Ilosc</span><span class="kwrd">="2"</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">Pozycja</span> <span class="attr">NrPozycji</span><span class="kwrd">="3"</span> <span class="attr">Produkt</span><span class="kwrd">="Produkt3"</span> <span class="attr">Cena</span><span class="kwrd">="10.5000"</span> <span class="attr">Ilosc</span><span class="kwrd">="1"</span> <span class="kwrd">/&gt;</span>
<span style="color: #ff0000;">  <span class="kwrd">&lt;/</span><span class="html">Pozycje</span><span class="kwrd">&gt;</span>
</span><span class="kwrd">&lt;/</span><span class="html">Faktura</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">Faktura</span> <span class="attr">Numer</span><span class="kwrd">="05/07/2010"</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">DataWystawienia</span><span class="kwrd">&gt;</span>2010-07-16T00:00:00<span class="kwrd">&lt;/</span><span class="html">DataWystawienia</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">Kontrahent</span><span class="kwrd">&gt;</span>FirmaB<span class="kwrd">&lt;/</span><span class="html">Kontrahent</span><span class="kwrd">&gt;</span>
 <span style="color: #ff0000;"> <span class="kwrd">&lt;</span><span class="html">Pozycje</span><span class="kwrd">&gt;</span></span>
    <span class="kwrd">&lt;</span><span class="html">Pozycja</span> <span class="attr">NrPozycji</span><span class="kwrd">="1"</span> <span class="attr">Produkt</span><span class="kwrd">="Produkt1"</span> <span class="attr">Cena</span><span class="kwrd">="10.0000"</span> <span class="attr">Ilosc</span><span class="kwrd">="5"</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">Pozycja</span> <span class="attr">NrPozycji</span><span class="kwrd">="2"</span> <span class="attr">Produkt</span><span class="kwrd">="Produkt3"</span> <span class="attr">Cena</span><span class="kwrd">="10.5000"</span> <span class="attr">Ilosc</span><span class="kwrd">="1"</span> <span class="kwrd">/&gt;</span>
  <span style="color: #ff0000;"><span class="kwrd">&lt;/</span><span class="html">Pozycje</span><span class="kwrd">&gt;</span></span>
<span class="kwrd">&lt;/</span><span class="html">Faktura</span><span class="kwrd">&gt;</span></pre>
<p>Różnica w stosunku do poprzedniego zadania polega na tym, że teraz chcemy pozycje mieć otoczone znacznikami &lt;Pozycje&gt; i &lt;/Pozycje&gt;.</p>
<p><strong>Rozwiązanie:</strong></p>
<pre class="csharpcode"><span class="kwrd">SELECT</span>
  1 <span class="kwrd">AS</span> Tag,
  <span class="kwrd">NULL</span> <span class="kwrd">AS</span> Parent,
  F.NrFaktury <span class="kwrd">AS</span> [Faktura!1!Numer],
  F.DataWystawienia <span class="kwrd">AS</span> [Faktura!1!DataWystawienia!ELEMENT],
  F.Kontrahent <span class="kwrd">AS</span> [Faktura!1!Kontrahent!ELEMENT],
  <span class="kwrd">NULL</span> <span class="kwrd">AS</span> [Pozycje!2],
  <span class="kwrd">NULL</span> <span class="kwrd">AS</span> [Pozycja!3!NrPozycji],
  <span class="kwrd">NULL</span> <span class="kwrd">AS</span> [Pozycja!3!Produkt],
  <span class="kwrd">NULL</span> <span class="kwrd">AS</span> [Pozycja!3!Cena],
  <span class="kwrd">NULL</span> <span class="kwrd">AS</span> [Pozycja!3!Ilosc]
<span class="kwrd">FROM</span> #Faktury F
<span class="kwrd">UNION</span> <span class="kwrd">ALL</span>
<span class="kwrd">SELECT</span>
  2,
  1,
  F.NrFaktury,
  <span class="kwrd">NULL</span>,
  <span class="kwrd">NULL</span>,
  <span class="kwrd">NULL</span>,
  <span class="kwrd">NULL</span>,
  <span class="kwrd">NULL</span>,
  <span class="kwrd">NULL</span>,
  <span class="kwrd">NULL</span>
<span class="kwrd">FROM</span> #Faktury F
<span class="kwrd">UNION</span> <span class="kwrd">ALL</span>
<span class="kwrd">SELECT</span>
  3,
  2,
  P.NrFaktury,
  <span class="kwrd">NULL</span>,
  <span class="kwrd">NULL</span>,
  <span class="kwrd">NULL</span>,
  P.NrPozycji,
  P.Produkt,
  P.Cena,
  P.Ilosc
<span class="kwrd">FROM</span> #Pozycje P
<span class="kwrd">ORDER</span> <span class="kwrd">BY</span> [Faktura!1!Numer], Tag, [Pozycja!3!NrPozycji]
<span class="kwrd">FOR</span> XML EXPLICIT;</pre>
<p>I teraz zadanie dla Ciebie – spróbuj prześledzić działanie FOR XML EXPLICIT w powyższym kodzie (kieruj się wskazówkami podanymi przeze mnie w pierwszym zadaniu – zakomentuj na przykład klauzulę FOR XML EXPLICIT i uruchom zapytanie ponownie, by zobaczyć, jak układają się wiersze). Powyższy trick możesz stosować wszędzie tam, gdzie chodzi o wygenerowanie dodatkowego elementu, w którym zostaną osadzone elementy z danymi (tak, to jest metoda na wygenerowanie elementu ROOT na SQL Server 2000!).</p>
<h4>Podsumowanie</h4>
<p>Wszystkich tych, którzy dotąd omijali FOR XML EXPLICIT szerokim łukiem, zachęcam do poeksperymentowania. Sugeruję obejrzeć różne warianty, oglądać, jak zmienia się wynikowy XML w zależności od sortowania i wartości w kolumnach Tag i Parent. Zabawę polecam zwłaszcza osobom, którym przychodzi w pracy generować XML-a na SQL Server 2000. Tam klauzula FOR XML EXPLICIT może być niekiedy jedynym sensownym ratunkiem w sytuacji, gdy mamy wygenerować dokument XML o z góry narzuconej strukturze.</p>
<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
<li class="shr-comfeed">
			<a href="http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
<li class="shr-twitter">
			<a href="http://twitter.com/home?status=%5BPL%5D+SQL+Server+%26ndash%3B+FOR+XML+EXPLICIT+%28nie%29+dla+opornych+-+http://b2l.me/am3qhX&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/&amp;t=%5BPL%5D+SQL+Server+%26ndash%3B+FOR+XML+EXPLICIT+%28nie%29+dla+opornych" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+FOR+XML+EXPLICIT+%28nie%29+dla+opornych&amp;summary=Klauzula%20FOR%20XML%20EXPLICIT%20jest%20bodaj%20najrzadziej%20u%C5%BCywan%C4%85%20z%20klauzul%20FOR%20XML.%20O%20wiele%20cz%C4%99%C5%9Bciej%20decydujemy%20si%C4%99%20na%20u%C5%BCycie%20FOR%20XML%20PATH%20%28od%20SQL%20Server%202005%29%20lub%20FOR%20XML%20AUTO%20%28SQL%20Server%202000%29%2C%20poniewa%C5%BC%20obie%20klauzule%20wydaj%C4%85%20si%C4%99%20prostsze%20w%20u%C5%BCyciu%20ni%C5%BC%20FOR%20XML%20EXPLICIT.%20Ale%20ma%C5%82o%20kto%20bierze%20pod%20uwag%C4%99%2C%20%C5%BCe%20FOR%20XML%20EXPLICIT%20daje%20%E2%80%93%20jako%20jedna%20z%20dw%C3%B3ch%20klauzul%20FOR%20XML%20na%20SQL%20Server%202005%20i%20nowszych%20oraz%20jako%20jedyna%20klauzula%20na%20SQL%20Server%202000%20%E2%80%93%20mo%C5%BCliwo%C5%9B%C4%87%20zwracania%20dokument%C3%B3w%20XML%2C%20w%20kt%C3%B3rych%20znajd%C4%85%20si%C4%99%20zar%C3%B3wno%20elementy%2C%20jak%20i%20atrybuty.%20A%20ju%C5%BC%20prawie%20nikt%20nie%20wie%2C%20%C5%BCe%20jedynie%20FOR%20XML%20EXPLICIT%20umo%C5%BCliwia%20generowanie%20dokument%C3%B3w%20XML%20zawieraj%C4%85cych%20sekcje%20CDATA.%20I%20to%20w%C5%82a%C5%9Bnie%20owo%20niedocenianie%20i%20unikanie%20klauzuli%20FOR%20XML%20EXPLICIT%20sk%C5%82oni%C5%82o%20mnie%20do%20napisania%20tego%20tekstu.&amp;source=SQLGeek.pl" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+FOR+XML+EXPLICIT+%28nie%29+dla+opornych" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+FOR+XML+EXPLICIT+%28nie%29+dla+opornych" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+FOR+XML+EXPLICIT+%28nie%29+dla+opornych&amp;srcUrl=http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/&amp;srcTitle=%5BPL%5D+SQL+Server+%26ndash%3B+FOR+XML+EXPLICIT+%28nie%29+dla+opornych&amp;snippet=Klauzula%20FOR%20XML%20EXPLICIT%20jest%20bodaj%20najrzadziej%20u%C5%BCywan%C4%85%20z%20klauzul%20FOR%20XML.%20O%20wiele%20cz%C4%99%C5%9Bciej%20decydujemy%20si%C4%99%20na%20u%C5%BCycie%20FOR%20XML%20PATH%20%28od%20SQL%20Server%202005%29%20lub%20FOR%20XML%20AUTO%20%28SQL%20Server%202000%29%2C%20poniewa%C5%BC%20obie%20klauzule%20wydaj%C4%85%20si%C4%99%20prostsze%20w%20u%C5%BCyciu%20ni%C5%BC%20FOR%20XML%20EXPLICIT.%20Ale%20ma%C5%82o%20kto%20bierze%20pod%20uwag%C4%99%2C%20%C5%BCe%20FOR%20XML%20EXPLICIT%20daje%20%E2%80%93%20jako%20jedna%20z%20dw%C3%B3ch%20klauzul%20FOR%20XML%20na%20SQL%20Server%202005%20i%20nowszych%20oraz%20jako%20jedyna%20klauzula%20na%20SQL%20Server%202000%20%E2%80%93%20mo%C5%BCliwo%C5%9B%C4%87%20zwracania%20dokument%C3%B3w%20XML%2C%20w%20kt%C3%B3rych%20znajd%C4%85%20si%C4%99%20zar%C3%B3wno%20elementy%2C%20jak%20i%20atrybuty.%20A%20ju%C5%BC%20prawie%20nikt%20nie%20wie%2C%20%C5%BCe%20jedynie%20FOR%20XML%20EXPLICIT%20umo%C5%BCliwia%20generowanie%20dokument%C3%B3w%20XML%20zawieraj%C4%85cych%20sekcje%20CDATA.%20I%20to%20w%C5%82a%C5%9Bnie%20owo%20niedocenianie%20i%20unikanie%20klauzuli%20FOR%20XML%20EXPLICIT%20sk%C5%82oni%C5%82o%20mnie%20do%20napisania%20tego%20tekstu." rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
<li class="shr-gmail">
			<a href="https://mail.google.com/mail/?ui=2&amp;view=cm&amp;fs=1&amp;tf=1&amp;su=%5BPL%5D+SQL+Server+%26ndash%3B+FOR+XML+EXPLICIT+%28nie%29+dla+opornych&amp;body=Link: http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Klauzula%20FOR%20XML%20EXPLICIT%20jest%20bodaj%20najrzadziej%20u%C5%BCywan%C4%85%20z%20klauzul%20FOR%20XML.%20O%20wiele%20cz%C4%99%C5%9Bciej%20decydujemy%20si%C4%99%20na%20u%C5%BCycie%20FOR%20XML%20PATH%20%28od%20SQL%20Server%202005%29%20lub%20FOR%20XML%20AUTO%20%28SQL%20Server%202000%29%2C%20poniewa%C5%BC%20obie%20klauzule%20wydaj%C4%85%20si%C4%99%20prostsze%20w%20u%C5%BCyciu%20ni%C5%BC%20FOR%20XML%20EXPLICIT.%20Ale%20ma%C5%82o%20kto%20bierze%20pod%20uwag%C4%99%2C%20%C5%BCe%20FOR%20XML%20EXPLICIT%20daje%20%E2%80%93%20jako%20jedna%20z%20dw%C3%B3ch%20klauzul%20FOR%20XML%20na%20SQL%20Server%202005%20i%20nowszych%20oraz%20jako%20jedyna%20klauzula%20na%20SQL%20Server%202000%20%E2%80%93%20mo%C5%BCliwo%C5%9B%C4%87%20zwracania%20dokument%C3%B3w%20XML%2C%20w%20kt%C3%B3rych%20znajd%C4%85%20si%C4%99%20zar%C3%B3wno%20elementy%2C%20jak%20i%20atrybuty.%20A%20ju%C5%BC%20prawie%20nikt%20nie%20wie%2C%20%C5%BCe%20jedynie%20FOR%20XML%20EXPLICIT%20umo%C5%BCliwia%20generowanie%20dokument%C3%B3w%20XML%20zawieraj%C4%85cych%20sekcje%20CDATA.%20I%20to%20w%C5%82a%C5%9Bnie%20owo%20niedocenianie%20i%20unikanie%20klauzuli%20FOR%20XML%20EXPLICIT%20sk%C5%82oni%C5%82o%20mnie%20do%20napisania%20tego%20tekstu." rel="nofollow" class="external" title="Email this via Gmail">Email this via Gmail</a>
		</li>
<li class="shr-googlebookmarks">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+FOR+XML+EXPLICIT+%28nie%29+dla+opornych" rel="nofollow" class="external" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
<li class="shr-hotmail">
			<a href="http://mail.live.com/?rru=compose?subject=%5BPL%5D+SQL+Server+%26ndash%3B+FOR+XML+EXPLICIT+%28nie%29+dla+opornych&amp;body=Link: http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Klauzula%20FOR%20XML%20EXPLICIT%20jest%20bodaj%20najrzadziej%20u%C5%BCywan%C4%85%20z%20klauzul%20FOR%20XML.%20O%20wiele%20cz%C4%99%C5%9Bciej%20decydujemy%20si%C4%99%20na%20u%C5%BCycie%20FOR%20XML%20PATH%20%28od%20SQL%20Server%202005%29%20lub%20FOR%20XML%20AUTO%20%28SQL%20Server%202000%29%2C%20poniewa%C5%BC%20obie%20klauzule%20wydaj%C4%85%20si%C4%99%20prostsze%20w%20u%C5%BCyciu%20ni%C5%BC%20FOR%20XML%20EXPLICIT.%20Ale%20ma%C5%82o%20kto%20bierze%20pod%20uwag%C4%99%2C%20%C5%BCe%20FOR%20XML%20EXPLICIT%20daje%20%E2%80%93%20jako%20jedna%20z%20dw%C3%B3ch%20klauzul%20FOR%20XML%20na%20SQL%20Server%202005%20i%20nowszych%20oraz%20jako%20jedyna%20klauzula%20na%20SQL%20Server%202000%20%E2%80%93%20mo%C5%BCliwo%C5%9B%C4%87%20zwracania%20dokument%C3%B3w%20XML%2C%20w%20kt%C3%B3rych%20znajd%C4%85%20si%C4%99%20zar%C3%B3wno%20elementy%2C%20jak%20i%20atrybuty.%20A%20ju%C5%BC%20prawie%20nikt%20nie%20wie%2C%20%C5%BCe%20jedynie%20FOR%20XML%20EXPLICIT%20umo%C5%BCliwia%20generowanie%20dokument%C3%B3w%20XML%20zawieraj%C4%85cych%20sekcje%20CDATA.%20I%20to%20w%C5%82a%C5%9Bnie%20owo%20niedocenianie%20i%20unikanie%20klauzuli%20FOR%20XML%20EXPLICIT%20sk%C5%82oni%C5%82o%20mnie%20do%20napisania%20tego%20tekstu." rel="nofollow" class="external" title="Email this via Hotmail">Email this via Hotmail</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sqlgeek.pl/2010/08/30/pl-sql-server-for-xml-explicit-nie-dla-opornych/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>[PL] Ewolucja SQLGeek.pl – wyniki ankiety i decyzje</title>
		<link>http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/</link>
		<comments>http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/#comments</comments>
		<pubDate>Sat, 28 Aug 2010 20:17:15 +0000</pubDate>
		<dc:creator>Pawel Potasinski</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[feedback]]></category>
		<category><![CDATA[SQLGeek]]></category>

		<guid isPermaLink="false">http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/</guid>
		<description><![CDATA[Niedawno poprosiłem czytelników mojego bloga o pomoc w podjęciu decyzji dotyczącej wyświetlania wpisów na stronie głównej. Rozchodziło się o to, czy powinny tam widnieć całe wpisy, czy też może jedynie ich streszczenia. Wyniki ankiety, jaka pojawiała się na blogu przez kilkanaście ostatnich dni wyglądają następująco:

Dziękuję wszystkim, którzy poświęcili swój czas i zagłosowali. Dało mi to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/">Niedawno</a> poprosiłem czytelników mojego bloga o pomoc w podjęciu decyzji dotyczącej wyświetlania wpisów na stronie głównej. Rozchodziło się o to, czy powinny tam widnieć całe wpisy, czy też może jedynie ich streszczenia. Wyniki ankiety, jaka pojawiała się na blogu przez kilkanaście ostatnich dni wyglądają następująco:</p>
<p><a href="http://sqlgeek.pl/wp-content/uploads/2010/08/image10.png"><img style="display: inline; border: 0px;" title="image" src="http://sqlgeek.pl/wp-content/uploads/2010/08/image_thumb10.png" border="0" alt="image" width="223" height="282" /></a></p>
<p>Dziękuję wszystkim, którzy poświęcili swój czas i zagłosowali. Dało mi to przegląd sytuacji. Decyzja, jaką podejmuję, jest podyktowana pragmatyzmem. A zatem… Tada!</p>
<p><strong>Posty na SQLGeek.pl będą wyświetlane w całości</strong>.</p>
<p>Dlaczego?</p>
<ul>
<li>Bo w razie czego jest <a href="http://sqlgeek.pl/archives/">archiwum</a>, w którym tytuły wszystkich wpisów są wypisane wg miesiąca publikacji.</li>
<li>Bo nie trzeba nigdzie klikać, by czytać najnowsze posty.</li>
<li>Bo nie muszę edytować postów historycznych i wstawiać w nie sekcji Read More.</li>
<li>Bo sekcja Read More jest kompletnie “niekastomizowalna” w skórce Mystique (a nie chcę dogrywać kolejnego plugina WordPressa).</li>
<li>Bo &#8220;wielcy bloggerzy SQL-owi&#8221; też tak mają ;-)</li>
<li>Bo ci, co głosowali na opcję pełnej treści wpisów, głosowali najgłośniej (komentowali żywo wpis ogłaszający ankietę).</li>
<li>Bo ci, co głosowali na opcję “pół na pół” w zasadzie po części też głosowali za pełną treścią wpisów na głównej stronie bloga :-)</li>
</ul>
<p>Jeszcze raz dzięki za pomoc w podjęciu decyzji i miłego czytania!</p>
<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
<li class="shr-comfeed">
			<a href="http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
<li class="shr-twitter">
			<a href="http://twitter.com/home?status=%5BPL%5D+Ewolucja+SQLGeek.pl+%26ndash%3B+wyniki+ankiety+i+decyzje+-+http://b2l.me/amr6cb&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/&amp;t=%5BPL%5D+Ewolucja+SQLGeek.pl+%26ndash%3B+wyniki+ankiety+i+decyzje" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/&amp;title=%5BPL%5D+Ewolucja+SQLGeek.pl+%26ndash%3B+wyniki+ankiety+i+decyzje&amp;summary=Niedawno%20poprosi%C5%82em%20czytelnik%C3%B3w%20mojego%20bloga%20o%20pomoc%20w%20podj%C4%99ciu%20decyzji%20dotycz%C4%85cej%20wy%C5%9Bwietlania%20wpis%C3%B3w%20na%20stronie%20g%C5%82%C3%B3wnej.%20Rozchodzi%C5%82o%20si%C4%99%20o%20to%2C%20czy%20powinny%20tam%20widnie%C4%87%20ca%C5%82e%20wpisy%2C%20czy%20te%C5%BC%20mo%C5%BCe%20jedynie%20ich%20streszczenia.%20Wyniki%20ankiety%2C%20jaka%20pojawia%C5%82a%20si%C4%99%20na%20blogu%20przez%20kilkana%C5%9Bcie%20o&amp;source=SQLGeek.pl" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/&amp;title=%5BPL%5D+Ewolucja+SQLGeek.pl+%26ndash%3B+wyniki+ankiety+i+decyzje" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/&amp;title=%5BPL%5D+Ewolucja+SQLGeek.pl+%26ndash%3B+wyniki+ankiety+i+decyzje" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/&amp;title=%5BPL%5D+Ewolucja+SQLGeek.pl+%26ndash%3B+wyniki+ankiety+i+decyzje&amp;srcUrl=http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/&amp;srcTitle=%5BPL%5D+Ewolucja+SQLGeek.pl+%26ndash%3B+wyniki+ankiety+i+decyzje&amp;snippet=Niedawno%20poprosi%C5%82em%20czytelnik%C3%B3w%20mojego%20bloga%20o%20pomoc%20w%20podj%C4%99ciu%20decyzji%20dotycz%C4%85cej%20wy%C5%9Bwietlania%20wpis%C3%B3w%20na%20stronie%20g%C5%82%C3%B3wnej.%20Rozchodzi%C5%82o%20si%C4%99%20o%20to%2C%20czy%20powinny%20tam%20widnie%C4%87%20ca%C5%82e%20wpisy%2C%20czy%20te%C5%BC%20mo%C5%BCe%20jedynie%20ich%20streszczenia.%20Wyniki%20ankiety%2C%20jaka%20pojawia%C5%82a%20si%C4%99%20na%20blogu%20przez%20kilkana%C5%9Bcie%20o" rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
<li class="shr-gmail">
			<a href="https://mail.google.com/mail/?ui=2&amp;view=cm&amp;fs=1&amp;tf=1&amp;su=%5BPL%5D+Ewolucja+SQLGeek.pl+%26ndash%3B+wyniki+ankiety+i+decyzje&amp;body=Link: http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Niedawno%20poprosi%C5%82em%20czytelnik%C3%B3w%20mojego%20bloga%20o%20pomoc%20w%20podj%C4%99ciu%20decyzji%20dotycz%C4%85cej%20wy%C5%9Bwietlania%20wpis%C3%B3w%20na%20stronie%20g%C5%82%C3%B3wnej.%20Rozchodzi%C5%82o%20si%C4%99%20o%20to%2C%20czy%20powinny%20tam%20widnie%C4%87%20ca%C5%82e%20wpisy%2C%20czy%20te%C5%BC%20mo%C5%BCe%20jedynie%20ich%20streszczenia.%20Wyniki%20ankiety%2C%20jaka%20pojawia%C5%82a%20si%C4%99%20na%20blogu%20przez%20kilkana%C5%9Bcie%20o" rel="nofollow" class="external" title="Email this via Gmail">Email this via Gmail</a>
		</li>
<li class="shr-googlebookmarks">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/&amp;title=%5BPL%5D+Ewolucja+SQLGeek.pl+%26ndash%3B+wyniki+ankiety+i+decyzje" rel="nofollow" class="external" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
<li class="shr-hotmail">
			<a href="http://mail.live.com/?rru=compose?subject=%5BPL%5D+Ewolucja+SQLGeek.pl+%26ndash%3B+wyniki+ankiety+i+decyzje&amp;body=Link: http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Niedawno%20poprosi%C5%82em%20czytelnik%C3%B3w%20mojego%20bloga%20o%20pomoc%20w%20podj%C4%99ciu%20decyzji%20dotycz%C4%85cej%20wy%C5%9Bwietlania%20wpis%C3%B3w%20na%20stronie%20g%C5%82%C3%B3wnej.%20Rozchodzi%C5%82o%20si%C4%99%20o%20to%2C%20czy%20powinny%20tam%20widnie%C4%87%20ca%C5%82e%20wpisy%2C%20czy%20te%C5%BC%20mo%C5%BCe%20jedynie%20ich%20streszczenia.%20Wyniki%20ankiety%2C%20jaka%20pojawia%C5%82a%20si%C4%99%20na%20blogu%20przez%20kilkana%C5%9Bcie%20o" rel="nofollow" class="external" title="Email this via Hotmail">Email this via Hotmail</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sqlgeek.pl/2010/08/28/pl-ewolucja-sqlgeek-pl-wyniki-ankiety-i-decyzje/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[PL] SQL Server – Monitorowanie logowania a logon triggery</title>
		<link>http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/</link>
		<comments>http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/#comments</comments>
		<pubDate>Thu, 26 Aug 2010 21:46:14 +0000</pubDate>
		<dc:creator>Pawel Potasinski</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[logon trigger]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/</guid>
		<description><![CDATA[Dzisiaj na forum WSS.pl wśród wielu ciekawych wątków o tematyce wokół SQL Servera, znalazł się wątek poświęcony monitorowaniu logowań do instancji SQL Servera loginów o uprawnieniach sysadmina. Autor wątku próbował zaatakować temat używając mechanizmu audytów dostępnego od SQL Server 2008, ale poległ na braku możliwości filtrowania logowań. Doradziłem dwa rozwiązania – logon trigger i Extended Events. Czy jednak moja porada była słuszna?]]></description>
			<content:encoded><![CDATA[<p>Dzisiaj na forum WSS.pl wśród wielu ciekawych wątków o tematyce wokół SQL Servera, znalazł się <a href="http://wss.pl/frmThread.aspx?tid=97930">wątek</a> poświęcony monitorowaniu logowań do instancji SQL Servera loginów o uprawnieniach sysadmina. Autor wątku próbował zaatakować temat używając mechanizmu audytów dostępnego od SQL Server 2008, ale poległ na braku możliwości filtrowania logowań. Doradziłem dwa rozwiązania – logon trigger i Extended Events. Taki przykładowy logon trigger mógłby wyglądać tak:    </p>
<pre class="csharpcode"><span class="kwrd">CREATE</span> <span class="kwrd">TRIGGER</span> trg_LogSysadminLogon
<span class="kwrd">ON</span> <span class="kwrd">ALL</span> SERVER
<span class="kwrd">FOR</span> LOGON
<span class="kwrd">AS</span>
<span class="kwrd">BEGIN</span>
<span class="kwrd">SET</span> NOCOUNT <span class="kwrd">ON</span>
<span class="kwrd">IF</span> IS_SRVROLEMEMBER(<span class="str">'sysadmin'</span>) = 1
  INSERT <span class="kwrd">INTO</span> master.dbo.SysadminLogon (Sysadmin, LogonDate)
  <span class="kwrd">SELECT</span> <span class="kwrd">SUSER_SNAME()</span>, GETDATE()
<span class="kwrd">END</span>
GO</pre>
<p>Komentarz do kodu: logon trigger dość prosty, używając funkcji IS_SRVROLEMEMBER sprawdzamy, czy bieżący login (ten, który próbuje się logować), jest sysadminem i jeżeli jest, zapisujemy jeden wiersz (nazwę logina i datę logowania) w tabeli dbo.SysadminLogon w bazie master.</p>
<p>Już po fakcie zacząłem się jednak zastanawiać, czy nie pospieszyłem się ze swoją poradą i doradzaniem logon triggera. Swego czasu napisałem wspólnie z <strong>Markiem Adamczukiem</strong> <a href="http://www.microsoft.com/poland/technet/article/art0060_01.mspx">artykuł o logon triggerach</a> dla polskiej strony Technet. W artykule tym wyraźnie zaznaczyliśmy, że istnieje co najmniej kilka przyczyn, z których działanie logon triggera może skutecznie uniemożliwić zalogowanie się użytkownika do serwera baz danych. I tu mnie tknęło. Chcemy mieć mechanizm monitorowania. Coś, co nie ingeruje w sam proces logowania, a jedynie zapisuje informację o tym, że jakiś sysadmin się zalogował. A skoro logon trigger przez swą naturę może skutecznie uniemożliwić owe logowanie (albo na przykład opóźnić je na skutek problemów wydajnościowych operacji w nim zapisanych), niespecjalnie nadaje się na mechanizm bezpiecznego (bezinwazyjnego, jak bym to nazwał) logowania. Wystarczy jeden błąd, jeden brak uprawnień, jeden wykonany w ciele triggera SELECT “w powietrze” (tak, tak, wykonanie zapytania SELECT w logon triggerze też powoduje błąd logowania!) i użytkownik zobaczy komunikat nieciekawej treści:</p>
<div><span style="font-family: courier new">Logon failed for login ‘jkowalsk’ due to trigger execution.<br />
    <br /></span><span style="font-family: courier new">Changed database context to &#8216;master&#8217;.<br />
    <br /><span style="font-family: courier new"><span style="font-family: courier new">Changed language setting to us_english. (Microsoft SQL Server, Error: 17892)</span></span> </p>
<p>Powiało grozą :-)</span></div>
<p>I tu Extended Events (w skrócie XE) są jednak mechanizmem o wiele bezpieczniejszym i już wiem, o czym będzie jeden z następnych wpisów na moim blogu. Cierpliwości, XE nadchodzą :-)</p>
<p><strong>[EDYCJA: 2010-09-03]</strong></p>
<p>A jednak wygląda na to, że Extended Events nie nadają się do śledzenia logowania (nie udało mi się znaleźć zdarzenia XE, które dałoby możliwość takiego śledzenia). Słuszną opcją za to wydaje się użycie Event Notifications, które oferują asynchroniczność i brak ingerencji w sam proces logowania.</p>
<p><strong>[/EDYCJA]</strong></p>
<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
<li class="shr-comfeed">
			<a href="http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
<li class="shr-twitter">
			<a href="http://twitter.com/home?status=%5BPL%5D+SQL+Server+%26ndash%3B+Monitorowanie+logowania+a+logon+triggery+-+http://b2l.me/ak92hn&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/&amp;t=%5BPL%5D+SQL+Server+%26ndash%3B+Monitorowanie+logowania+a+logon+triggery" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+Monitorowanie+logowania+a+logon+triggery&amp;summary=Dzisiaj%20na%20forum%20WSS.pl%20w%C5%9Br%C3%B3d%20wielu%20ciekawych%20w%C4%85tk%C3%B3w%20o%20tematyce%20wok%C3%B3%C5%82%20SQL%20Servera%2C%20znalaz%C5%82%20si%C4%99%20w%C4%85tek%20po%C5%9Bwi%C4%99cony%20monitorowaniu%20logowa%C5%84%20do%20instancji%20SQL%20Servera%20login%C3%B3w%20o%20uprawnieniach%20sysadmina.%20Autor%20w%C4%85tku%20pr%C3%B3bowa%C5%82%20zaatakowa%C4%87%20temat%20u%C5%BCywaj%C4%85c%20mechanizmu%20audyt%C3%B3w%20dost%C4%99pnego%20od%20SQL%20Server%202008%2C%20ale%20poleg%C5%82%20na%20braku%20mo%C5%BCliwo%C5%9Bci%20filtrowania%20logowa%C5%84.%20Doradzi%C5%82em%20dwa%20rozwi%C4%85zania%20%E2%80%93%20logon%20trigger%20i%20Extended%20Events.%20Czy%20jednak%20moja%20porada%20by%C5%82a%20s%C5%82uszna%3F&amp;source=SQLGeek.pl" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+Monitorowanie+logowania+a+logon+triggery" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+Monitorowanie+logowania+a+logon+triggery" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+Monitorowanie+logowania+a+logon+triggery&amp;srcUrl=http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/&amp;srcTitle=%5BPL%5D+SQL+Server+%26ndash%3B+Monitorowanie+logowania+a+logon+triggery&amp;snippet=Dzisiaj%20na%20forum%20WSS.pl%20w%C5%9Br%C3%B3d%20wielu%20ciekawych%20w%C4%85tk%C3%B3w%20o%20tematyce%20wok%C3%B3%C5%82%20SQL%20Servera%2C%20znalaz%C5%82%20si%C4%99%20w%C4%85tek%20po%C5%9Bwi%C4%99cony%20monitorowaniu%20logowa%C5%84%20do%20instancji%20SQL%20Servera%20login%C3%B3w%20o%20uprawnieniach%20sysadmina.%20Autor%20w%C4%85tku%20pr%C3%B3bowa%C5%82%20zaatakowa%C4%87%20temat%20u%C5%BCywaj%C4%85c%20mechanizmu%20audyt%C3%B3w%20dost%C4%99pnego%20od%20SQL%20Server%202008%2C%20ale%20poleg%C5%82%20na%20braku%20mo%C5%BCliwo%C5%9Bci%20filtrowania%20logowa%C5%84.%20Doradzi%C5%82em%20dwa%20rozwi%C4%85zania%20%E2%80%93%20logon%20trigger%20i%20Extended%20Events.%20Czy%20jednak%20moja%20porada%20by%C5%82a%20s%C5%82uszna%3F" rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
<li class="shr-gmail">
			<a href="https://mail.google.com/mail/?ui=2&amp;view=cm&amp;fs=1&amp;tf=1&amp;su=%5BPL%5D+SQL+Server+%26ndash%3B+Monitorowanie+logowania+a+logon+triggery&amp;body=Link: http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Dzisiaj%20na%20forum%20WSS.pl%20w%C5%9Br%C3%B3d%20wielu%20ciekawych%20w%C4%85tk%C3%B3w%20o%20tematyce%20wok%C3%B3%C5%82%20SQL%20Servera%2C%20znalaz%C5%82%20si%C4%99%20w%C4%85tek%20po%C5%9Bwi%C4%99cony%20monitorowaniu%20logowa%C5%84%20do%20instancji%20SQL%20Servera%20login%C3%B3w%20o%20uprawnieniach%20sysadmina.%20Autor%20w%C4%85tku%20pr%C3%B3bowa%C5%82%20zaatakowa%C4%87%20temat%20u%C5%BCywaj%C4%85c%20mechanizmu%20audyt%C3%B3w%20dost%C4%99pnego%20od%20SQL%20Server%202008%2C%20ale%20poleg%C5%82%20na%20braku%20mo%C5%BCliwo%C5%9Bci%20filtrowania%20logowa%C5%84.%20Doradzi%C5%82em%20dwa%20rozwi%C4%85zania%20%E2%80%93%20logon%20trigger%20i%20Extended%20Events.%20Czy%20jednak%20moja%20porada%20by%C5%82a%20s%C5%82uszna%3F" rel="nofollow" class="external" title="Email this via Gmail">Email this via Gmail</a>
		</li>
<li class="shr-googlebookmarks">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/&amp;title=%5BPL%5D+SQL+Server+%26ndash%3B+Monitorowanie+logowania+a+logon+triggery" rel="nofollow" class="external" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
<li class="shr-hotmail">
			<a href="http://mail.live.com/?rru=compose?subject=%5BPL%5D+SQL+Server+%26ndash%3B+Monitorowanie+logowania+a+logon+triggery&amp;body=Link: http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Dzisiaj%20na%20forum%20WSS.pl%20w%C5%9Br%C3%B3d%20wielu%20ciekawych%20w%C4%85tk%C3%B3w%20o%20tematyce%20wok%C3%B3%C5%82%20SQL%20Servera%2C%20znalaz%C5%82%20si%C4%99%20w%C4%85tek%20po%C5%9Bwi%C4%99cony%20monitorowaniu%20logowa%C5%84%20do%20instancji%20SQL%20Servera%20login%C3%B3w%20o%20uprawnieniach%20sysadmina.%20Autor%20w%C4%85tku%20pr%C3%B3bowa%C5%82%20zaatakowa%C4%87%20temat%20u%C5%BCywaj%C4%85c%20mechanizmu%20audyt%C3%B3w%20dost%C4%99pnego%20od%20SQL%20Server%202008%2C%20ale%20poleg%C5%82%20na%20braku%20mo%C5%BCliwo%C5%9Bci%20filtrowania%20logowa%C5%84.%20Doradzi%C5%82em%20dwa%20rozwi%C4%85zania%20%E2%80%93%20logon%20trigger%20i%20Extended%20Events.%20Czy%20jednak%20moja%20porada%20by%C5%82a%20s%C5%82uszna%3F" rel="nofollow" class="external" title="Email this via Hotmail">Email this via Hotmail</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sqlgeek.pl/2010/08/26/pl-sql-server-monitorowanie-logowania-a-logon-triggery/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[PL] SQL Server – Limity w SQL Server 2008 R2 Express Edition</title>
		<link>http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/</link>
		<comments>http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/#comments</comments>
		<pubDate>Mon, 23 Aug 2010 21:55:27 +0000</pubDate>
		<dc:creator>Pawel Potasinski</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[buffer cache]]></category>
		<category><![CDATA[Express Edition]]></category>
		<category><![CDATA[limity]]></category>

		<guid isPermaLink="false">http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/</guid>
		<description><![CDATA[Na forum WSS.pl użytkownik zapytał o limit pamięci RAM w SQL Server 2008 R2 Express Edition. Udzieliliśmy z Krzyśkiem Stachyrą standardowej odpowiedzi wyczytanej na oficjalnej stronie produktu SQL Server 2008, że limit pamięci wynosi 1GB dla bufora danych. Kolega sprawdzał na wiele sposobów, ale zawsze wychodziło mu blisko 1,4GB, a to jednak trochę więcej niż rzekome 1GB… Jaka jest zatem szara rzeczywistość?]]></description>
			<content:encoded><![CDATA[<h4>Zajawka nie na temat</h4>
<p>Dzień 23 sierpnia 2010 roku &#8211; ależ to był poniedziałek! Najpierw z samego rana awaria bloga. Przez chwilę myślałem, że to jakiś atak DDOS albo serwer nie wytrzymał naporu czytelników (czy to możliwe, żeby blog <a href="http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/">po jednym wpisie</a> stał się aż tak popularny?). Ale kolega z firmy hostującej bloga wyjaśnił mi, że to nie był czynnik ludzki. Grunt, ze blog odżył i duskusja pod najbardziej obleganym wpisem na moim blogu trwała w najlepsze :-) </p>
<h4>Zajawka na temat – użytkownik zasiewa niepewność</h4>
<p>Najlepsze jednak nadeszło po południu. Na <a href="http://wss.pl/frmThread.aspx?tid=97781">forum WSS.pl</a> użytkownik <a href="http://wss.pl/User/Profile/47305.aspx">lechuCC</a> zapytał o limit pamięci RAM w SQL Server 2008 R2 Express Edition. Udzieliliśmy z Krzyśkiem Stachyrą standardowej odpowiedzi wyczytanej na oficjalnej stronie produktu SQL Server 2008 (ale nie na stronie SQL Server 2008 R2! tam nic na ten temat nie ma, ale przed udzieleniem odpowiedzi koledze nawet nie szukałem…), że limit pamięci wynosi 1GB dla bufora danych. Kolega sprawdzał na wiele sposobów, ale zawsze wychodziło mu blisko 1,4GB, a to jednak trochę więcej niż rzekome 1GB… </p>
<p>Postanowiłem się przekonać, jaka jest szara rzeczywistość :-) Opis wykonanych czynności przedstawiam poniżej. </p>
<h4>Test szarej rzeczywistości</h4>
<p>Na instancji SQL Server 2008 R2 Express Edition, w której wynik zapytania: </p>
<pre class="csharpcode"><span class="kwrd">SELECT</span> @@VERSION;</pre>
<p>wyglądał tak: </p>
<div><span style="font-family: Courier New;">Microsoft SQL Server 2008 R2 (RTM) &#8211; 10.50.1600.1 (X64)</span></div>
<div><span style="font-family: Courier New;">    Apr  2 2010 15:48:46    Copyright (c) Microsoft Corporation</span></div>
<div><span style="font-family: Courier New;"> </span><span style="font-family: Courier New;"><span style="font-family: Courier New;">   Express Edition (64-bit) on Windows NT 6.1 &lt;X64&gt; (Build 7600: )</span></span></div>
<div><span style="font-family: Courier New;"><span style="font-family: Courier New;"> </span></span></div>
<p>założyłem sobie bazę danych o nazwie Test. Powiększyłem plik danych tej bazy do 2GB i plik dziennika transakcji do 100MB (asekuracyjnie). W tejże bazie puściłem w ruch taki kawałek kodu: </p>
<pre class="csharpcode"><span class="kwrd">USE</span> Test;
<span class="kwrd">GO</span>
<span class="kwrd">IF</span> OBJECT_ID(N<span class="str">'dbo.t'</span>, N<span class="str">'U'</span>) <span class="kwrd">IS</span> <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>
  <span class="kwrd">DROP</span> <span class="kwrd">TABLE</span> dbo.t;
<span class="kwrd">GO</span>
<span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> dbo.t (a <span class="kwrd">char</span>(8000));
<span class="kwrd">GO</span>
INSERT <span class="kwrd">INTO</span> dbo.t (a)
<span class="kwrd">SELECT</span> REPLICATE(<span class="str">'a'</span>, 8000)
<span class="kwrd">FROM</span> sys.all_objects <span class="kwrd">WHERE</span> is_ms_shipped = 1; <span class="rem">-- 1981 wierszy</span>
<span class="kwrd">CHECKPOINT</span>;
<span class="kwrd">GO</span> 100</pre>
<p>Po 100 wykonaniach wsadu z poleceniem INSERT mam sporą tabelę – z liczbą wierszy równą 198100, a każdy wiersz rezyduje na osobnej stronie danych (bo wstawiłem tyle danych w jeden wiersz, że drugi już na tych samych 8 kilobajtach się nie zmieści). </p>
<p>Teraz opróżniam cały bufor danych: </p>
<pre class="csharpcode"><span class="kwrd">DBCC</span> DROPCLEANBUFFERS;
GO</pre>
<p>I wykonuję zapytanie, którego celem jest wrzucenie do bufora danych wszystkich danych z tabeli dbo.t: </p>
<pre class="csharpcode"><span class="kwrd">SELECT</span> <span class="kwrd">COUNT</span>(*) <span class="kwrd">FROM</span> dbo.t; -- wynik: 198100, wykonany został skan tabeli</pre>
<p>Zaglądam do bufora zapytaniami, które <a href="http://sqlgeek.pl/2010/07/19/sql-server-ile-czego-w-buforze-danych/">już prezentowałem na blogu</a>. Na początek informacja, która baza ile megabajtów zajmuje w buforze: </p>
<pre class="csharpcode"><span class="kwrd">SELECT</span>
  <span class="kwrd">CASE</span>
    <span class="kwrd">WHEN</span> database_id = 32767 <span class="kwrd">THEN</span> <span class="str">'mssqlsystemresource'</span>
    <span class="kwrd">ELSE</span> DB_NAME(database_id)
  <span class="kwrd">END</span> <span class="kwrd">AS</span> [<span class="kwrd">Database</span>],
  <span class="kwrd">CONVERT</span>(<span class="kwrd">numeric</span>(38,2),(8.0 / 1024) * <span class="kwrd">COUNT</span>(*)) <span class="kwrd">AS</span> [<span class="kwrd">In</span> buffer cache (MB)]
<span class="kwrd">FROM</span> sys.dm_os_buffer_descriptors
<span class="kwrd">GROUP</span> <span class="kwrd">BY</span> database_id
<span class="kwrd">ORDER</span> <span class="kwrd">BY</span> 2 <span class="kwrd">DESC</span>;
GO</pre>
<p>Wynik: </p>
<pre class="csharpcode">Database            In buffer cache (MB)
------------------- --------------------
Test                1383.83
tempdb              0.24
mssqlsystemresource 0.19
master              0.06</pre>
<p>Czyli że baza Test zajmuje blisko 1,4GB… </p>
<p>Skoro tak, to przekonajmy się, który obiekt tyle miejsca zajął spośród obiektów z bazy Test: </p>
<pre class="csharpcode"><span class="kwrd">USE</span> Test;
<span class="kwrd">GO</span>
<span class="kwrd">SELECT</span>
  QUOTENAME(OBJECT_SCHEMA_NAME(p.object_id)) + <span class="str">'.'</span> +
  QUOTENAME(OBJECT_NAME(p.object_id)) <span class="kwrd">AS</span> <span class="kwrd">Object</span>,
  <span class="kwrd">CONVERT</span>(<span class="kwrd">numeric</span>(38,2),(8.0 / 1024) * <span class="kwrd">COUNT</span>(*)) <span class="kwrd">AS</span> [<span class="kwrd">In</span> buffer cache (MB)]
<span class="kwrd">FROM</span> sys.dm_os_buffer_descriptors <span class="kwrd">AS</span> d
<span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> sys.allocation_units <span class="kwrd">AS</span> u
<span class="kwrd">ON</span> d.allocation_unit_id = u.allocation_unit_id
<span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> sys.partitions <span class="kwrd">AS</span> p
<span class="kwrd">ON</span> (u.type <span class="kwrd">IN</span> (1,3) <span class="kwrd">AND</span> u.container_id = p.hobt_id)
<span class="kwrd">OR</span> (u.type = 2 <span class="kwrd">AND</span> u.container_id = p.partition_id)
<span class="kwrd">WHERE</span> d.database_id = DB_ID()
<span class="kwrd">GROUP</span> <span class="kwrd">BY</span> QUOTENAME(OBJECT_SCHEMA_NAME(p.object_id)) + <span class="str">'.'</span> +
  QUOTENAME(OBJECT_NAME(p.object_id))
<span class="kwrd">ORDER</span> <span class="kwrd">BY</span> 2 <span class="kwrd">DESC</span>;
GO</pre>
<p>Wynik: </p>
<pre class="csharpcode">Object                   In buffer cache (MB)
------------------------ --------------------
[dbo].[t]                1382.40
[sys].[sysobjvalues]     0.12
[sys].[syscolpars]       0.07
[sys].[sysschobjs]       0.02
[sys].[syssingleobjrefs] 0.02
[sys].[sysiscols]        0.02
[sys].[sysallocunits]    0.01
[sys].[sysrowsets]       0.01
[sys].[sysidxstats]      0.01</pre>
<p>I proszę. Jedna duża tabela zajmuje w buforze rzeczone blisko 1,4GB. </p>
<p>Niespodzianka? Pomyślałem, że może moje zapytania są błędnie napisane. Zatem pora zajrzeć do liczników monitora wydajności (perfmona): </p>
<pre class="csharpcode"><span class="kwrd">SELECT</span>
  object_name,
  counter_name,
  cntr_value / 1024 <span class="kwrd">AS</span> cntr_value_MB
<span class="kwrd">FROM</span> sys.dm_os_performance_counters
<span class="kwrd">WHERE</span> object_name <span class="kwrd">LIKE</span> '<span class="str">%Memory Manager%'</span>
<span class="kwrd">AND</span> counter_name <span class="kwrd">IN</span> (<span class="str">'Total Server Memory (KB)'</span>, <span class="str">'Target Server Memory (KB)'</span>);
<span class="kwrd">GO</span></pre>
<p>Wynik: </p>
<pre class="csharpcode">object_name                           counter_name              cntr_value_MB
------------------------------------- ------------------------- -------------
MSSQL$SQL2008R2EXPRESS:Memory Manager Target Server Memory (KB) 1410
MSSQL$SQL2008R2EXPRESS:Memory Manager Total Server Memory (KB)  1410</pre>
<p>Zatem Perfmon mówi, że instancja zajęła 1410 megabajtów na bufor danych i – co ciekawe &#8211; tyle właśnie zamierzała… </p>
<p>Dla pewności jeszcze: </p>
<pre class="csharpcode"><span class="kwrd">DBCC</span> MEMORYSTATUS;
GO</pre>
<p>Gdzie w wyniku znalazłem między innymi: </p>
<pre class="csharpcode">Buffer Pool Value
----------- -----------
Committed   180480
Target      180480</pre>
<p>Kalkulator (T-SQL) w ręce i liczymy ile wychodzi z pomnożenia 180480 przez 8 (tyle kilobajtów ma strona danych) i podzielenia wyniku przez 1024 (żeby wynik wyszedł w megabajtach): </p>
<pre class="csharpcode"><span class="kwrd">SELECT</span> 8 * 180480 / 1024 <span class="kwrd">AS</span> [Buffer pool <span class="kwrd">in</span> MB]; -- 1410</pre>
<p>I w tym momencie już nie mam wątpliwości, że ta instancja wzięła 1,4GB pamięci RAM na bufor danych! A napisano, że miała wziąć nie więcej niż 1GB… </p>
<h4>Jak jedno się nie zgadza…</h4>
<p>… to trzeba sprawdzić, czy inny limit opisany w reklamowych folderach jest prawdziwy (do osiągnięcia i nie do przekroczenia). Tym limitem jest 10GB na pliki danych w pojedynczej bazie danych w SQL Server 2008 R2 Express Edition. </p>
<p>Pierwszy ruch – spróbujmy zwiększyć wielkość pliku do 1MB powyżej owych 10GB: </p>
<pre class="csharpcode"><span class="kwrd">USE</span> master;
<span class="kwrd">GO</span>
<span class="kwrd">ALTER</span> <span class="kwrd">DATABASE</span> Test
<span class="kwrd">MODIFY</span> <span class="kwrd">FILE</span> (
  NAME = N<span class="str">'Test'</span>,
  <span class="kwrd">SIZE</span> = 10486784KB
);
GO</pre>
<p>Odpowiedź serwera: </p>
<div><span style="font-family: Courier New;">Msg 1827, Level 16, State 2, Line 1</span></div>
<div><span style="font-family: Courier New;">CREATE DATABASE or ALTER DATABASE failed because the resulting cumulative database size would exceed your licensed limit of 10240 MB per database.</span></div>
<div><span style="font-family: Courier New;"> </span> </div>
<p>Ok, tak się nie da :-) </p>
<p>Test kolejny – co będzie, jak wstawimy tyle danych, że plik sam będzie zmuszony urosnąć ponad wymienione 10240MB. Tu po prostu wielokrotnie kopiuję moją dużą tabelę dbo.t z testu bufora danych: </p>
<pre class="csharpcode"><span class="kwrd">SELECT</span> * <span class="kwrd">INTO</span> dbo.t1 <span class="kwrd">FROM</span> dbo.t; <span class="rem">-- tu jedynie zmieniam numerki na kolejne</span>
GO</pre>
<p>W końcu serwer odpowiada: </p>
<div><span style="font-family: Courier New;">Msg 1101, Level 17, State 12, Line 1</span></div>
<div><span style="font-family: Courier New;">Could not allocate a new page for database &#8216;Test&#8217; because of insufficient disk space in filegroup &#8216;PRIMARY&#8217;. Create the necessary space by dropping objects in the filegroup, adding additional files to the filegroup, or setting autogrowth on for existing files in the filegroup.</span></div>
<div><span style="font-family: Courier New;"> </span></div>
<p>Z tego wynika, że 10GB jest prawdziwym ograniczeniem rozmiaru danych w pojedynczej bazie danych w SQL Server 2008 R2 Express Edition. </p>
<h4>To jak to w końcu jest?</h4>
<p>Jest tak, że jak sami nie sprawdzimy, to może się okazać, że informacje przekazywane drogą poczty pantoflowej mają się nijak do szarej rzeczywistości (i ja przyłożyłem w tym przypadku rękę do powielania, jak się okazuje niekoniecznie prawdziwej, informacji). Jest też tak, że nawet sam Microsoft nie zna ograniczeń swojego produktu, bo ludzie z Redmond proszeni o komentarze do zademonstrowanego tu testu nie bardzo wiedzą, jak sensownie to wytłumaczyć (próbują wymyślać wersje zeznań mówiące, że niby jakieś tam systemowe obiekty i tajemnicze pule systemowe zajmują dodatkowe megabajty w buforze), ale obstają przy wersji, że limit dla bufora nadal wynosi 1GB! Może by nie było o co robić szumu, ale… Ale w edycji Express liczy się każdy megabajt, a tu najpewniej mamy nieścisłość rzędu 40% :-) A to już podstawa do zadania sobie pytania – czy mogę wykorzystać te oddane do dyspozycji “za darmo” 400MB bufora? Skoro w Microsoft o nich nie wiedzą, to pewnie mogę, bo skąd będą wiedzieli, że wykorzystuję coś, o istnieniu czego nie wiedzą ;-) </p>
<p>Acha, i ciekawostka na koniec – dla SQL Server 2008 R2 Express Edition można śmiało ustawić &#8216;max server memory (MB)&#8217; na 2048 ;-) Ani SQL Server, ani Management Studio ani pisną, choć taki limit jest bez sensu, bo instancja nie użyje więcej niż 1GB… tfu, wróć… 1,4GB pamięci na bufor danych :-) </p>
<p>PS. Za chwilę instaluję SQL Server 2008 Express Edition i powtarzam test. Dopiszę obserwacje do tego wpisu. Kto wie, może i na poprzedniej wersji rzeczony limit nie wynosi 1GB ;-) </p>
<p><strong>[EDYCJA: 2010-08-24] </strong> </p>
<p>Ponieważ <a href="http://powerpivot.info.pl/">Łukasz Grala</a> już zrobił test na SQL Server 2005 Express Edition (patrz jego komentarz do tego wpisu) i wygląda na to, że sytuacja jest analogiczna, nie będę testował, jak to jest na SQL Server 2008 Express Edition. </p>
<p><strong>[/EDYCJA]</strong></p>
<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
<li class="shr-comfeed">
			<a href="http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
<li class="shr-twitter">
			<a href="http://twitter.com/home?status=%5BPL%5D+SQL+Server+-+Limity+w+SQL+Server+2008+R2+Express+Edition+-+http://b2l.me/akgt73&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/&amp;t=%5BPL%5D+SQL+Server+-+Limity+w+SQL+Server+2008+R2+Express+Edition" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/&amp;title=%5BPL%5D+SQL+Server+-+Limity+w+SQL+Server+2008+R2+Express+Edition&amp;summary=Na%20forum%20WSS.pl%20u%C5%BCytkownik%20zapyta%C5%82%20o%20limit%20pami%C4%99ci%20RAM%20w%20SQL%20Server%202008%20R2%20Express%20Edition.%20Udzielili%C5%9Bmy%20z%20Krzy%C5%9Bkiem%20Stachyr%C4%85%20standardowej%20odpowiedzi%20wyczytanej%20na%20oficjalnej%20stronie%20produktu%20SQL%20Server%202008%2C%20%C5%BCe%20limit%20pami%C4%99ci%20wynosi%201GB%20dla%20bufora%20danych.%20Kolega%20sprawdza%C5%82%20na%20wiele%20sposob%C3%B3w%2C%20ale%20zawsze%20wychodzi%C5%82o%20mu%20blisko%201%2C4GB%2C%20a%20to%20jednak%20troch%C4%99%20wi%C4%99cej%20ni%C5%BC%20rzekome%201GB%E2%80%A6%20Jaka%20jest%20zatem%20szara%20rzeczywisto%C5%9B%C4%87%3F&amp;source=SQLGeek.pl" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/&amp;title=%5BPL%5D+SQL+Server+-+Limity+w+SQL+Server+2008+R2+Express+Edition" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/&amp;title=%5BPL%5D+SQL+Server+-+Limity+w+SQL+Server+2008+R2+Express+Edition" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/&amp;title=%5BPL%5D+SQL+Server+-+Limity+w+SQL+Server+2008+R2+Express+Edition&amp;srcUrl=http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/&amp;srcTitle=%5BPL%5D+SQL+Server+-+Limity+w+SQL+Server+2008+R2+Express+Edition&amp;snippet=Na%20forum%20WSS.pl%20u%C5%BCytkownik%20zapyta%C5%82%20o%20limit%20pami%C4%99ci%20RAM%20w%20SQL%20Server%202008%20R2%20Express%20Edition.%20Udzielili%C5%9Bmy%20z%20Krzy%C5%9Bkiem%20Stachyr%C4%85%20standardowej%20odpowiedzi%20wyczytanej%20na%20oficjalnej%20stronie%20produktu%20SQL%20Server%202008%2C%20%C5%BCe%20limit%20pami%C4%99ci%20wynosi%201GB%20dla%20bufora%20danych.%20Kolega%20sprawdza%C5%82%20na%20wiele%20sposob%C3%B3w%2C%20ale%20zawsze%20wychodzi%C5%82o%20mu%20blisko%201%2C4GB%2C%20a%20to%20jednak%20troch%C4%99%20wi%C4%99cej%20ni%C5%BC%20rzekome%201GB%E2%80%A6%20Jaka%20jest%20zatem%20szara%20rzeczywisto%C5%9B%C4%87%3F" rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
<li class="shr-gmail">
			<a href="https://mail.google.com/mail/?ui=2&amp;view=cm&amp;fs=1&amp;tf=1&amp;su=%5BPL%5D+SQL+Server+-+Limity+w+SQL+Server+2008+R2+Express+Edition&amp;body=Link: http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Na%20forum%20WSS.pl%20u%C5%BCytkownik%20zapyta%C5%82%20o%20limit%20pami%C4%99ci%20RAM%20w%20SQL%20Server%202008%20R2%20Express%20Edition.%20Udzielili%C5%9Bmy%20z%20Krzy%C5%9Bkiem%20Stachyr%C4%85%20standardowej%20odpowiedzi%20wyczytanej%20na%20oficjalnej%20stronie%20produktu%20SQL%20Server%202008%2C%20%C5%BCe%20limit%20pami%C4%99ci%20wynosi%201GB%20dla%20bufora%20danych.%20Kolega%20sprawdza%C5%82%20na%20wiele%20sposob%C3%B3w%2C%20ale%20zawsze%20wychodzi%C5%82o%20mu%20blisko%201%2C4GB%2C%20a%20to%20jednak%20troch%C4%99%20wi%C4%99cej%20ni%C5%BC%20rzekome%201GB%E2%80%A6%20Jaka%20jest%20zatem%20szara%20rzeczywisto%C5%9B%C4%87%3F" rel="nofollow" class="external" title="Email this via Gmail">Email this via Gmail</a>
		</li>
<li class="shr-googlebookmarks">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/&amp;title=%5BPL%5D+SQL+Server+-+Limity+w+SQL+Server+2008+R2+Express+Edition" rel="nofollow" class="external" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
<li class="shr-hotmail">
			<a href="http://mail.live.com/?rru=compose?subject=%5BPL%5D+SQL+Server+-+Limity+w+SQL+Server+2008+R2+Express+Edition&amp;body=Link: http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Na%20forum%20WSS.pl%20u%C5%BCytkownik%20zapyta%C5%82%20o%20limit%20pami%C4%99ci%20RAM%20w%20SQL%20Server%202008%20R2%20Express%20Edition.%20Udzielili%C5%9Bmy%20z%20Krzy%C5%9Bkiem%20Stachyr%C4%85%20standardowej%20odpowiedzi%20wyczytanej%20na%20oficjalnej%20stronie%20produktu%20SQL%20Server%202008%2C%20%C5%BCe%20limit%20pami%C4%99ci%20wynosi%201GB%20dla%20bufora%20danych.%20Kolega%20sprawdza%C5%82%20na%20wiele%20sposob%C3%B3w%2C%20ale%20zawsze%20wychodzi%C5%82o%20mu%20blisko%201%2C4GB%2C%20a%20to%20jednak%20troch%C4%99%20wi%C4%99cej%20ni%C5%BC%20rzekome%201GB%E2%80%A6%20Jaka%20jest%20zatem%20szara%20rzeczywisto%C5%9B%C4%87%3F" rel="nofollow" class="external" title="Email this via Hotmail">Email this via Hotmail</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sqlgeek.pl/2010/08/23/pl-sql-server-limity-w-sql-server-2008-r2-express-edition/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>[PL] SQL Server – Czy optymalizator może policzyć wiersze w zmiennej tabelarycznej?</title>
		<link>http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/</link>
		<comments>http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/#comments</comments>
		<pubDate>Mon, 23 Aug 2010 10:50:36 +0000</pubDate>
		<dc:creator>Pawel Potasinski</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[optymalizacja]]></category>
		<category><![CDATA[plany wykonania]]></category>
		<category><![CDATA[zmienne tabelaryczne]]></category>

		<guid isPermaLink="false">http://sqlgeek.pl/?p=263</guid>
		<description><![CDATA[Przyjęło się i przekazywane jest w środowisku stwierdzenie, że w przypadku, gdy w zapytaniu użyta jest zmienna tabelaryczna (zwana przez niektórych “tabelą małpkową”), optymalizator zawsze zakłada/widzi w zmiennej tabelarycznej dokładnie jeden wiersz. Z tego powodu często plany wykonania są dalekie od oczekiwanych, przez co musimy sterować planami (np. jawnie określając kolejność tabel w złączeniach). Jednak czy to zawsze jest prawda?]]></description>
			<content:encoded><![CDATA[<p>Przyjęło się i przekazywane jest w środowisku stwierdzenie, że w przypadku, gdy w zapytaniu użyta jest zmienna tabelaryczna (zwana przez niektórych “tabelą małpkową”), optymalizator zawsze zakłada/widzi w zmiennej tabelarycznej dokładnie jeden wiersz. Z tego powodu plany wykonania są dalekie od oczekiwanych, przez co musimy sterować planami (np. jawnie określając kolejność tabel w złączeniach).</p>
<p>Postanowiłem troche poszperać w temacie.</p>
<p>Spróbujmy uruchomić taki kawałek kodu T-SQL:</p>
<pre>DECLARE @t TABLE (c1 int PRIMARY KEY);
DECLARE @x TABLE (c2 int PRIMARY KEY);
INSERT INTO @t SELECT DISTINCT number FROM master.dbo.spt_values;
INSERT INTO @x SELECT TOP 1 number FROM master.dbo.spt_values;
SELECT * FROM @t t INNER JOIN @x x ON t.c1 = x.c2 OPTION (RECOMPILE); --(1)
SELECT * FROM @t t INNER JOIN @x x ON t.c1 = x.c2;                    --(2)</pre>
<p>Zapytania (1) i (2) są złączeniami dwóch zmiennych tabelarycznych &#8211; @x – zawierającej 1 wiersz oraz @t – zawierającej ponad 2000 wierszy.</p>
<p>Dla zapytań (1) i (2) oglądamy dwa różne plany wykonania (ale nie plany estymowane, a plany rzeczywiste) o tym samym koszcie:</p>
<p><a href="http://sqlgeek.pl/wp-content/uploads/2010/08/image.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto; border: 0px;" title="image" src="http://sqlgeek.pl/wp-content/uploads/2010/08/image_thumb.png" border="0" alt="image" width="626" height="450" /></a>Pierwsza obserwacja - w obu przypadkach kolejność zmiennych tabelarycznych w złączeniu była różna (w przypadku zapytania (1) z opcją RECOMPILE kolejność była &#8220;prawidłowa&#8221; – skanowanie zmiennej zawierającej mniejszą ilość wierszy i wyszukanie rekordów w zmiennej “większej”).</p>
<p>Zobaczmy w planach wykonania szczegóły operatorów użytych w stosunku do zmiennej @t.</p>
<p><a href="http://sqlgeek.pl/wp-content/uploads/2010/08/image1.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto; border: 0px;" title="image" src="http://sqlgeek.pl/wp-content/uploads/2010/08/image_thumb1.png" border="0" alt="image" width="682" height="455" /></a></p>
<p>W zapytaniu (2) w operatorze Clustered Index Scan liczba przy pozycji Actual Number of Rows (rzeczywista liczba wierszy)  zgadza się z rzeczywistością (2164), zaś w przypadku zapytania (1) używającego opcji RECOMPILE (“rekompiluj zapytanie i nie używaj planu z cache’u”) w operatorze Clustered Index Seek liczba obok Acutal Number of Rows wynosi 1. Skąd w drugim planie wzięła się poprawna informacja o rzeczywistej liczbie wierszy? Odpowiedź przychodzi, gdy spojrzymy na całość planu wykonania. W takich sytuacjach liczba wierszy z tabeli &#8220;zewnętrznej&#8221; (Outer) jest równa ilości iteracji pętli Nested Loops &#8211; 2164 to właśnie ilość &#8220;obrotów pętli&#8221;.  Nadal jednak estymowana ilość wierszy dla tych zmiennych wynosi 1 (słownie: jeden). A z tego wynika, że &#8211; z klauzulą OPTION (RECOMPILE) czy bez niej &#8211; <strong>optymalizator zakłada, że w zmiennej tabelarycznej jest zawsze 1 rekord</strong>. Swego rodzaju ciekawostką są różne plany wykonania obu przedstawionych zapytań, ale równie dobrze może to być przypadek lub bug (dość powtarzalny).</p>
<p>W tym miejscu przyznaję, że gdyby nie <strong>Maciek Pilecki</strong>, chodząca księga wiedzy o zagadnieniach optymalizacji SQL Servera, nie wpadłbym na oczywistą pomyłkę, którą popełniłem pisząc ten wpis w jego pierwotnej postaci. Co się mianowicie stało? Ano, jakimś cudem pomyliłem plany wykonania obu zapytań i tak się tym zasugerowałem, że pomyślałem, iż klauzula OPTION (RECOMPILE) umożliwia dokładne policzenie rekordów w zmiennej tabelarycznej SQL Serverowi. Oczywiście mój błąd. Dobrze, że Maciek był na posterunku i mogłem dzięki niemu poprawić ten wpis oraz swój krzywy światopogląd, a przy okazji jeszcze czegoś się nauczyć (dzięki, Maćku).</p>
<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
<li class="shr-comfeed">
			<a href="http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
<li class="shr-twitter">
			<a href="http://twitter.com/home?status=%5BPL%5D+SQL+Server+%E2%80%93+Czy+optymalizator+mo%C5%BCe+policzy%C4%87+wiersze+w+zmiennej+tabelar%5B..%5D+-+http://b2l.me/akc62b&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/&amp;t=%5BPL%5D+SQL+Server+%E2%80%93+Czy+optymalizator+mo%C5%BCe+policzy%C4%87+wiersze+w+zmiennej+tabelarycznej%3F" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/&amp;title=%5BPL%5D+SQL+Server+%E2%80%93+Czy+optymalizator+mo%C5%BCe+policzy%C4%87+wiersze+w+zmiennej+tabelarycznej%3F&amp;summary=Przyj%C4%99%C5%82o%20si%C4%99%20i%20przekazywane%20jest%20w%20%C5%9Brodowisku%20stwierdzenie%2C%20%C5%BCe%20w%20przypadku%2C%20gdy%20w%20zapytaniu%20u%C5%BCyta%20jest%20zmienna%20tabelaryczna%20%28zwana%20przez%20niekt%C3%B3rych%20%E2%80%9Ctabel%C4%85%20ma%C5%82pkow%C4%85%E2%80%9D%29%2C%20optymalizator%20zawsze%20zak%C5%82ada%2Fwidzi%20w%20zmiennej%20tabelarycznej%20dok%C5%82adnie%20jeden%20wiersz.%20Z%20tego%20powodu%20cz%C4%99sto%20plany%20wykonania%20s%C4%85%20dalekie%20od%20oczekiwanych%2C%20przez%20co%20musimy%20sterowa%C4%87%20planami%20%28np.%20jawnie%20okre%C5%9Blaj%C4%85c%20kolejno%C5%9B%C4%87%20tabel%20w%20z%C5%82%C4%85czeniach%29.%20Jednak%20czy%20to%20zawsze%20jest%20prawda%3F&amp;source=SQLGeek.pl" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/&amp;title=%5BPL%5D+SQL+Server+%E2%80%93+Czy+optymalizator+mo%C5%BCe+policzy%C4%87+wiersze+w+zmiennej+tabelarycznej%3F" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/&amp;title=%5BPL%5D+SQL+Server+%E2%80%93+Czy+optymalizator+mo%C5%BCe+policzy%C4%87+wiersze+w+zmiennej+tabelarycznej%3F" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/&amp;title=%5BPL%5D+SQL+Server+%E2%80%93+Czy+optymalizator+mo%C5%BCe+policzy%C4%87+wiersze+w+zmiennej+tabelarycznej%3F&amp;srcUrl=http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/&amp;srcTitle=%5BPL%5D+SQL+Server+%E2%80%93+Czy+optymalizator+mo%C5%BCe+policzy%C4%87+wiersze+w+zmiennej+tabelarycznej%3F&amp;snippet=Przyj%C4%99%C5%82o%20si%C4%99%20i%20przekazywane%20jest%20w%20%C5%9Brodowisku%20stwierdzenie%2C%20%C5%BCe%20w%20przypadku%2C%20gdy%20w%20zapytaniu%20u%C5%BCyta%20jest%20zmienna%20tabelaryczna%20%28zwana%20przez%20niekt%C3%B3rych%20%E2%80%9Ctabel%C4%85%20ma%C5%82pkow%C4%85%E2%80%9D%29%2C%20optymalizator%20zawsze%20zak%C5%82ada%2Fwidzi%20w%20zmiennej%20tabelarycznej%20dok%C5%82adnie%20jeden%20wiersz.%20Z%20tego%20powodu%20cz%C4%99sto%20plany%20wykonania%20s%C4%85%20dalekie%20od%20oczekiwanych%2C%20przez%20co%20musimy%20sterowa%C4%87%20planami%20%28np.%20jawnie%20okre%C5%9Blaj%C4%85c%20kolejno%C5%9B%C4%87%20tabel%20w%20z%C5%82%C4%85czeniach%29.%20Jednak%20czy%20to%20zawsze%20jest%20prawda%3F" rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
<li class="shr-gmail">
			<a href="https://mail.google.com/mail/?ui=2&amp;view=cm&amp;fs=1&amp;tf=1&amp;su=%5BPL%5D+SQL+Server+%E2%80%93+Czy+optymalizator+mo%C5%BCe+policzy%C4%87+wiersze+w+zmiennej+tabelarycznej%3F&amp;body=Link: http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Przyj%C4%99%C5%82o%20si%C4%99%20i%20przekazywane%20jest%20w%20%C5%9Brodowisku%20stwierdzenie%2C%20%C5%BCe%20w%20przypadku%2C%20gdy%20w%20zapytaniu%20u%C5%BCyta%20jest%20zmienna%20tabelaryczna%20%28zwana%20przez%20niekt%C3%B3rych%20%E2%80%9Ctabel%C4%85%20ma%C5%82pkow%C4%85%E2%80%9D%29%2C%20optymalizator%20zawsze%20zak%C5%82ada%2Fwidzi%20w%20zmiennej%20tabelarycznej%20dok%C5%82adnie%20jeden%20wiersz.%20Z%20tego%20powodu%20cz%C4%99sto%20plany%20wykonania%20s%C4%85%20dalekie%20od%20oczekiwanych%2C%20przez%20co%20musimy%20sterowa%C4%87%20planami%20%28np.%20jawnie%20okre%C5%9Blaj%C4%85c%20kolejno%C5%9B%C4%87%20tabel%20w%20z%C5%82%C4%85czeniach%29.%20Jednak%20czy%20to%20zawsze%20jest%20prawda%3F" rel="nofollow" class="external" title="Email this via Gmail">Email this via Gmail</a>
		</li>
<li class="shr-googlebookmarks">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/&amp;title=%5BPL%5D+SQL+Server+%E2%80%93+Czy+optymalizator+mo%C5%BCe+policzy%C4%87+wiersze+w+zmiennej+tabelarycznej%3F" rel="nofollow" class="external" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
<li class="shr-hotmail">
			<a href="http://mail.live.com/?rru=compose?subject=%5BPL%5D+SQL+Server+%E2%80%93+Czy+optymalizator+mo%C5%BCe+policzy%C4%87+wiersze+w+zmiennej+tabelarycznej%3F&amp;body=Link: http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Przyj%C4%99%C5%82o%20si%C4%99%20i%20przekazywane%20jest%20w%20%C5%9Brodowisku%20stwierdzenie%2C%20%C5%BCe%20w%20przypadku%2C%20gdy%20w%20zapytaniu%20u%C5%BCyta%20jest%20zmienna%20tabelaryczna%20%28zwana%20przez%20niekt%C3%B3rych%20%E2%80%9Ctabel%C4%85%20ma%C5%82pkow%C4%85%E2%80%9D%29%2C%20optymalizator%20zawsze%20zak%C5%82ada%2Fwidzi%20w%20zmiennej%20tabelarycznej%20dok%C5%82adnie%20jeden%20wiersz.%20Z%20tego%20powodu%20cz%C4%99sto%20plany%20wykonania%20s%C4%85%20dalekie%20od%20oczekiwanych%2C%20przez%20co%20musimy%20sterowa%C4%87%20planami%20%28np.%20jawnie%20okre%C5%9Blaj%C4%85c%20kolejno%C5%9B%C4%87%20tabel%20w%20z%C5%82%C4%85czeniach%29.%20Jednak%20czy%20to%20zawsze%20jest%20prawda%3F" rel="nofollow" class="external" title="Email this via Hotmail">Email this via Hotmail</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sqlgeek.pl/2010/08/23/pl-sql-server-czy-optymalizator-moze-policzyc-wiersze-w-zmiennej-tabelarycznej/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[PL] Jak odnaleźć się w branży IT i mieć z pracy coś więcej niż tylko pieniądze?</title>
		<link>http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/</link>
		<comments>http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/#comments</comments>
		<pubDate>Sat, 21 Aug 2010 18:11:04 +0000</pubDate>
		<dc:creator>Pawel Potasinski</dc:creator>
				<category><![CDATA[Offtopic]]></category>
		<category><![CDATA[CV]]></category>
		<category><![CDATA[praca]]></category>
		<category><![CDATA[specjalizacja]]></category>

		<guid isPermaLink="false">http://sqlgeek.pl/?p=438</guid>
		<description><![CDATA[Po lekturze wielu wpisów na wielu blogach (m.in. na blogach Mariusza Kędziory i Maćka Aniserowicza) na temat pracy w branży IT, specjalizacji, planowania kariery i podobnych spraw postanowiłem, że i ja dorzucę do tego zestawu coś od siebie. Okazja nadarza się niezła, jako że w tym roku minęło 10 lat odkąd pracuję w branży IT.]]></description>
			<content:encoded><![CDATA[<h4>Wejście smoka</h4>
<p>Po lekturze wielu wpisów na wielu blogach (m.in. na blogach <a href="http://blogs.technet.com/b/mkedziora/archive/2010/08/20/specjalizacja-a-bycie-na-czasie.aspx">Mariusza Kędziory</a> i <a href="http://www.maciejaniserowicz.com/post/2009/06/15/Zawod-programista-Rozmowa-kwalifikacyjna.aspx">Maćka Aniserowicza</a>) na temat pracy w branży IT, specjalizacji, planowania kariery i podobnych spraw postanowiłem, że i ja dorzucę do tego zestawu coś od siebie. Okazja nadarza się niezła, jako że w tym roku minęło 10 lat odkąd pracuję w branży IT (mało to i dużo – mało, bo znam osoby, które ponad 10 lat pracują w jednej firmie, a dużo – bo można w tym czasie przejść długą drogę po drabince kompetencji), a poza tym jestem właśnie na etapie zmiany pracodawcy. Być może to, co napiszę wyda Ci się stekiem bzdur, kolekcją banałów, z których nic nie wynika lub zestawem kompletnie bezużytecznych “złotych myśli”. Ale jeśli znajdzie się choć jedna osoba, której moje wynurzenia się przydadzą w życiu, będzie to mój sukces.</p>
<h4>Autorytet?</h4>
<p>Pierwsze pytanie – kim jestem, że uzurpuję sobie prawo do pisania tego wpisu? Obecnie jestem starszym programistą w dużej korporacji oferującej wachlarz aplikacji wspierających pracę firm. Wcześniej byłem trenerem, administratorem, kierownikiem grupy konsultantów i trenerów. Rekrutowałem ludzi i byłem rekrutowany. Widziałem wiele rozmów kwalifikacyjnych (także w języku angielskim oraz wywiadów telefonicznych), byłem świadkiem licznych wpadek HR i kandydatów na różne stanowiska pracy. Obserwowałem rozwój kilku firm i korporacji, w których dane mi było pracować, poznałem smak prowadzenia własnej działalności gospodarczej oraz uroki pracy dla korporacji. Stąd mój tupet w tym wpisie :-)</p>
<h4>Do dzieła!</h4>
<p>A zatem, poniżej prezentuję zbiór moich przemyśleń na temat pracy, kariery, rozwoju i wszystkiego tego, co związane z zarabianiem pieniędzy w IT. Podkreślam, że mogą to być wyjątkowo nieobiektywne przemyślenia :-)</p>
<h5>Część 1: Co zrobić, by łatwiej było zdobyć pracę?</h5>
<ol>
<li><strong>Dbaj o swoje CV.</strong> Przede wszystkim zawsze miej aktualne CV, bo nigdy nie wiesz, kiedy będzie potrzebne. Po drugie – dbaj o treść i formę swojego CV. Pokazuj CV znajomym i proś ich o opisanie wrażeń (przede wszystkim czy jest czytelne). Nie wpisuj do niego nieprawdziwych informacji, koloryzowanych kompetencji, a nawet wymyślonych zainteresowań (ale zainteresowania koniecznie wpisz – a może to dzięki nim uda Ci się zdobyć nową pracę). Banał? Było sto razy? To powtórzmy po raz sto pierwszy! CV to często pierwsza informacja o Tobie, jaką ewentualny przyszły pracodawca otrzyma. Niech pierwsze wrażenie będzie jak najlepsze. Wersje polska i angielska zawierające dokładnie tę samą treść to “must have” każdego człowieka pracy.</li>
<li><strong>Nie wstydź się swojej pracy i nie mów o niej źle. </strong>Ile to razy słuchałem na rozmowach kwalifikacyjnych człowieka, który otwarcie podważał wagę tego, co robił w życiu zawodowym. A może to, co robiłeś jest tym, co najbardziej interesuje Twojego przyszłego pracodawcę? Na rozmowach kwalifikacyjnych celem jest wyciągnięcie na światło dzienne tego, co było w dotychczasowej pracy najlepsze, a nie najgorsze. O złych stronach pracy mów tylko na wyraźne żądanie rozmówcy i nigdy więcej. To zapewnia pozytywny odbiór Twojej osoby.</li>
<li><strong>Buduj swoje kontakty. </strong>Dasz wiarę, że w życiu da się uniknąć brnięcia przez sito rozmów kwalifikacyjnych i testów? Twoje kontakty z ludźmi mogą mieć wielką siłę sprawczą. Dlatego szanuj kontakty z ludźmi z branży, z którymi się stykasz na gruncie zawodowym, ale i nie tylko (o społecznościach będę jeszcze pisał). Nie pal mostów kończąc z kimś współpracę (rozstanie z pracodawcą nie musi być bolesne i pełne wzajemnej niechęci, o wiele lepiej pozostawać w dobrym kontakcie i rozstawać się w atmosferze zrozumienia – zadbaj, by eks-pracodawca poznał logiczne wyjaśnienie Twojego odejścia). Tu nie obowiązuje powiedzenie mówiące, że “nie wchodzi się dwa razy do tej samej rzeki”. A teraz wyobraź sobie, że dostajesz ofertę na portalu GoldenLine.pl czy LinkedIn.com (a dostaję tam ofert naprawdę sporo). Headhunter podesłał Ci coś, co kompletnie nie pasuje do Twojego profilu zawodowego. Co robisz? Jeżeli puszczasz człowieka kantem i ignorujesz jego wiadomość, wg mnie popełniasz błąd. Zawsze odpowiadam na oferty pracy, jakie dostaję. I zawsze zachowuję kontakt do osoby, która ową ofertę mi podesłała. Czasem zdarza mi się, że podsyłam headhunterowi znajomego, który w mojej ocenie lepiej pasuje do oferty (i być może akurat rozgląda się za nowymi wyzwaniami). Kontakty z “łowcami głów” są nierzadko szansą na ciekawą pracę w przyszłości.</li>
<li><strong>Bądź w społecznościach związanych z branżą. </strong>Sprawdź, czy nie warto zbudować kontaktów w społecznościach, np. w grupach pasjonackich, w ramach portali tematycznych albo grup dyskusyjnych. Z moich obserwacji wynika, że takie kontakty mogą okazać się niezwykle cenne. Dzięki udziałowi w spotkaniach Polskiej Grupy Użytkowników SQL Server czy dzięki uczestnictwu w dyskusjach na forum portalu WSS.pl niejednokrotnie zdobywałem klientów oraz poznawałem osoby, dzięki którym łatwiej było myśleć o przyszłości i planować rozwój mojej kariery.</li>
<li><strong>Specjalizuj się.</strong> Czasy, kiedy człowiek w IT był od wszystkiego, minęły bezpowrotnie. Dzisiaj wygląda na to, że o wiele łatwiej jest zdobyć pracę będąc specjalistą w jednej / dwóch technologiach. Ja wybrałem bazy danych, a dotychczasowa kariera w IT skierowała moje zainteresowania w stronę systemu Microsoft SQL Server. Ale nie czuję się specjalistą z zakresu SQL Servera jako produktu, a jedynie wybranych elementów tego systemu. I tak już jest – systemy są coraz bardziej skomplikowane i ogarnięcie nawet pojedynczego “potwora” jest praktycznie niewykonalne. W czym się specjalizować? Jeśli jeszcze nie masz swojej specjalizacji, porozmawiaj o tym ze znajomymi z branży. Ja sam chętnie też doradzam swoim studentom, jeżeli kierują do mnie pytania o to, w czym warto się specjalizować. Idealnie jest wpasować się w jakąś niszę – znaleźć technologię, która ma przyszłość, a jest w niej jeszcze miejsce dla Ciebie. Choć tak naprawdę nawet mając specjalizację uznaną za dość powszechną, możesz nie mieć problemu ze znalezieniem pracy, ponieważ rynek może potrzebować wielu specjalistów z danej dziedziny. Tu złotego środka nie ma.</li>
<li><strong>Miej otwarte horyzonty. </strong>Nie zamykaj się na technologie. Używasz Windows? Poznaj Linuksa. Pracujesz z bazami Oracle? Zobacz, jak analogiczne rzeczy można robić w PostgreSQL. Oczywiście, chodzi o ogólne pojęcie, co oferują systemy czy technologie inne niż te, z którymi na co dzień przyszło Ci pracować.</li>
<li><strong>Bądź na bieżąco. </strong>Staraj się śledzić rozwój technologii i systemów. Obserwuj trendy, kierunki rozwoju produktów. To da Ci szansę znalezienia nisz, w których specjalizacja może być przyczynkiem do zdobycia ciekawej pracy. Czytaj aktualności na portalach, blogach, w gazetach. Na przykład, doskonałą okazją do dokonania przeglądu są konferencje typu Microsoft Technology Summit.</li>
<li><strong>Rozwijaj się nie tylko technologicznie. </strong>Szalenie ważne są dziś tzw. “miękkie umiejętności”. Umiejętność komunikacji z drugim człowiekiem, kultura osobista, zdolności w zakresie prowadzenia negocjacji i przeprowadzania rozmów z klientami są w cenie. Jeżeli tylko masz okazję do pracy na styku Twoja firma – klient, korzystaj z okazji i rozwijaj właśnie te zdolności. Jeśli masz taką możliwość, porozmawiaj z trenerem lub osobą, która w pracy używa takich “miękkich umiejętności”.</li>
<li><strong>Wyznaczaj sobie cele. </strong>Nie ma nic gorszego niż brak celu w życiu zawodowym. Znam ludzi, którzy już w wieku dwudziestu paru lat wiedzieli, co chcą robić za 5-10 lat. Duży szacunek, jeżeli człowiek myśli o przyszłości i stara się dążyć do czegoś w życiu. Wyznacz sobie wiele celów i dla każdego załóż jakiś czas realizacji. Gdy czas upłynie, spróbuj podsumować, co udało się zrealizować, a co nie (i dlaczego nie!). Przy czym celem nie musi być &#8211; “za 5 lat będę project managerem”. To może być coś zupełnie innego – np. “za 5 lat będę miał wyrobioną markę w kraju i 2-3 stałych klientów, dla których będę wykonywał projekty”.</li>
<li><strong>Zdobywaj udokumentowane kompetencje.</strong> Certyfikaty, referencje, listy polecające, szkolenia. Niezależnie od obiegowych opinii to one są często podstawą do tego, czy masz szansę na zdobycie atrakcyjnej i rozwojowej pracy. Nie lekceważ zwłaszcza potęgi certyfikatów. Mówi się o nich dużo, niekoniecznie dobrze, ale ja już dzisiaj wiem, że na pewnym poziomie w branży IT bez nich po prostu człowiek nie istnieje. Co do referencji – jeśli czujesz, że udało Ci się wykonać kawał dobrej roboty dla klienta, poproś o pisemne potwierdzenie satysfakcji klienta. Ważne zwłaszcza wtedy, gdy klient ma uznaną markę – to może być kiedyś przepustka do “lepszego świata” :-)</li>
</ol>
<h5>Część 2: Jak pracować i nie zwariować?</h5>
<ol>
<li><strong>Po pierwsze – pracuj uczciwie. </strong>Niech praca nie będzie przykrym obowiązkiem. Pamiętaj, że zazwyczaj pracujesz za takie pieniądze, jakie samemu udało Ci się wynegocjować. Nie narzekaj więc, że “słabo płacą”, tylko rób swoje. Pokaż, że z Twojej strony wszystko jest w porządku, że swoje obowiązki wypełniasz z właściwym profesjonalizmem. Nie dostosowuj się poziomem do innych. Pracownik wypełniający sumiennie swoje obowiązki jest cenniejszy od znudzonego “wielkiego eksperta”, który już na nic w pracy nie ma ochoty i buduje w firmie atmosferę błogiego lenistwa. Takiego marazmu nie znoszę, bo bywa zaraźliwy :-)</li>
<li><strong>Nie patrz innym na ręce. </strong>Jeżeli nie jesteś zwierzchnikiem współpracownika, nie staraj się odgrywać tej roli. Widząc, że ktoś popełnia błąd, zwróć mu uwagę, pomóż. Ale nie besztaj, bo błędów nie popełnia tylko ten, który nic nie robi. Ponadto, to, że inny pracownik firmy nie wykonuje właściwie swoich obowiązków, nie upoważnia Cię do dorównywania mu w niedbalstwie czy nieróbstwie. Inni nie robią dokumentacji swoich modułów kodu? Jeżeli nie ma przeciwwskazań, Ty dokumentuj swój kod. Powtórzę raz jeszcze – bądź dobrym przykładem dla innych.</li>
<li><strong>Ucz się. </strong>W każdej firmie zgromadzona jest wiedza. Rzadko kiedy udokumentowana, ale ona tam jest. Znajdź w firmie ludzi, od których możesz się uczyć i korzystaj w miarę możliwości z ich doświadczenia. Miałem w życiu to szczęście, że pracowałem w każdej firmie z ludźmi, rzekłbym, wybitnymi. I to jest bezcenne. Zbieraj doświadczenia, rób podsumowanie po każdym projekcie (a nawet po każdej fazie projektu). W miarę możliwości spisuj wiedzę (notes, baza wiedzy, blog – każdy sposób jest dobry). Staraj się uczyć głównie rzeczy przydatnych w codziennej pracy.</li>
<li><strong>Bądź otwarty na pomysły współpracowników. </strong>Nawet, jeśli jesteś już w pozycji przełożonego i zarządzasz zespołem, słuchaj swoich współpracowników. Oni naprawdę też mogą mieć dobre pomysły. Znam sytuacje, kiedy bardzo silne zespoły rozpadały się, a pracownicy odchodzili z firmy, ponieważ lider zespołu narzucał swój – niekoniecznie słuszny &#8211; punkt widzenia.</li>
<li><strong>Nigdy nie przestawaj ulepszać swojego modelu pracy. </strong>Zawsze możesz coś poprawić w pracy swojej czy swojego zespołu. Staraj się myśleć konstruktywnie o tym, co można poprawić w modelu pracy. Zapoznaj się z metodykami prowadzenia projektów, tam często są gotowe rozwiązania, które mogą sprawić, że praca będzie przyjemniejsza, bardziej zorganizowana, zorientowana na współpracę grupy ludzi. Wprowadzaj w swojej pracy uznane powszechnie dobre praktyki (tu chodzi o dowolne “best practices” – zarówno w odniesieniu do technologii, jak i pracy zespołowej).</li>
<li><strong>Automatyzuj. </strong>To szczególnie dotyczy pracy w IT. Staraj się wyeliminować ze swojego dnia pracy czynności, które może za Ciebie wykonywać automat. Jeżeli widzisz, że codziennie robisz powtarzalną czynność inną niż przeglądanie logów czy czytanie dokumentacji, być może dałoby się coś zautomatyzować. To nie jest lenistwo, to pragmatyzm. Mniej powtarzalnych czynności = mniejsze znużenie pracą + więcej czasu na inne czynności (np. na naukę).</li>
<li><strong>Miej zdrowe priorytety. </strong>Praca jest ważna. Ale ważniejsze są zdrowie czy rodzina. Zadbaj o to, by praca wpasowała się w Twoje życie bezboleśnie. Jeżeli czujesz, że praca psuje Twoje relacje z bliskimi lub rujnuje Ci zdrowie (stres, nadgodziny), pomyśl, co można z tym zrobić. Nie pracuj ponad swoje możliwości fizyczne (pracujesz po 12-14 godzin dziennie? ten punkt napisałem specjalnie dla Ciebie – opamiętaj się!).</li>
<li><strong>Szanuj swój czas i swoją pracę. </strong>Wiele się mówi o tym, że ludzie z IT bywają niedoceniani, a przez to słabo opłacani. Ale spróbuj odpowiedzieć sobie na pytanie – co robię, by pracodawca miał podstawy do płacenia mi pieniędzy zgodnych z moimi oczekiwaniami? Jeśli Ty nie jesteś w stanie logicznie uzasadnić swoich oczekiwań, nikt nie będzie w stanie tego zrobić za Ciebie. Ceń siebie i swoją pracę, nie pracuj za darmo (nadgodziny, weekendy). I ważna rzecz – na rozmowach o pracę zazwyczaj wypada podawać oczekiwaną kwotę nieco zawyżoną, ponieważ najprawdopodobniej Twoi rozmówcy będą negocjować w dół :-)</li>
<li><strong>Okazuj ludziom szacunek.</strong> Najbliższym współpracownikom, starszym pracownikom, podwładnym i przełożonym. Pamiętaj, że kiedyś ktoś może okazać brak szacunku wobec Ciebie. Traktuj ludzi tak, jak chcesz, by Ciebie traktowano. To naprawdę działa w dwie strony.</li>
<li><strong>Spróbuj odnaleźć swoje miejsce w firmie czy w zespole.</strong> Zawsze jest coś, co robisz lepiej od swoich koleżanek i kolegów. Staraj się, by w tym względzie Twój wkład w firmie był widoczny. Jeżeli to możliwe, dziel się wiedzą. Wiem, że czasem może to spowodować, że poczujesz zagrożenie Twojej pozycji w firmie/zespole. Ale dzielenie się wiedzą może dać Ci wielką satysfakcję, wdzięczność współpracowników i szanse na to, że ktoś inny podzieli się z Tobą swoją wiedzą.</li>
</ol>
<h4>Veni, vidi, vici</h4>
<p>Jeżeli udało Ci się dotrzeć aż tutaj, to znaczy, że dałem radę i udało mi się nie zepsuć tego wpisu :-) Oczywiście, to nie wszystkie moje przemyślenia. Niektóre zatrzymuję dla siebie ;-) Te, które wymieniłem, zawierają zasady, jakimi kieruję się ja. I jak dotąd wydaje mi się, że te zasady działają na moją korzyść. To dzięki nim jestem dzisiaj w tym miejscu mojej kariery. W miejscu, w którym – przynajmniej na razie – nie martwię się o swoją przyszłość i widzę swoje ścieżki rozwoju. Robię to, co lubię, daje mi to satysfakcję i pieniądze, mam czas dla rodziny i dla siebie, a i ludzie, którzy mają okazję ze mną pracować na moje oko są z tej współpracy zadowoleni. I o to w tym wszystkim chyba chodzi :-)</p>
<p>PS. Czekam na komentarze i przemyślenia. Tylko dyskutując możemy się czegoś od siebie nauczyć!</p>
<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
<li class="shr-comfeed">
			<a href="http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
<li class="shr-twitter">
			<a href="http://twitter.com/home?status=%5BPL%5D+Jak+odnale%C5%BA%C4%87+si%C4%99+w+bran%C5%BCy+IT+i+mie%C4%87+z+pracy+co%C5%9B+wi%C4%99cej+ni%C5%BC+tylko+pi%5B..%5D+-+http://b2l.me/ajzh4u&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/&amp;t=%5BPL%5D+Jak+odnale%C5%BA%C4%87+si%C4%99+w+bran%C5%BCy+IT+i+mie%C4%87+z+pracy+co%C5%9B+wi%C4%99cej+ni%C5%BC+tylko+pieni%C4%85dze%3F" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/&amp;title=%5BPL%5D+Jak+odnale%C5%BA%C4%87+si%C4%99+w+bran%C5%BCy+IT+i+mie%C4%87+z+pracy+co%C5%9B+wi%C4%99cej+ni%C5%BC+tylko+pieni%C4%85dze%3F&amp;summary=Po%20lekturze%20wielu%20wpis%C3%B3w%20na%20wielu%20blogach%20%28m.in.%20na%20blogach%20Mariusza%20K%C4%99dziory%20i%20Ma%C4%87ka%20Aniserowicza%29%20na%20temat%20pracy%20w%20bran%C5%BCy%20IT%2C%20specjalizacji%2C%20planowania%20kariery%20i%20podobnych%20spraw%20postanowi%C5%82em%2C%20%C5%BCe%20i%20ja%20dorzuc%C4%99%20do%20tego%20zestawu%20co%C5%9B%20od%20siebie.%20Okazja%20nadarza%20si%C4%99%20niez%C5%82a%2C%20jako%20%C5%BCe%20w%20tym%20roku%20min%C4%99%C5%82o%2010%20lat%20odk%C4%85d%20pracuj%C4%99%20w%20bran%C5%BCy%20IT.&amp;source=SQLGeek.pl" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/&amp;title=%5BPL%5D+Jak+odnale%C5%BA%C4%87+si%C4%99+w+bran%C5%BCy+IT+i+mie%C4%87+z+pracy+co%C5%9B+wi%C4%99cej+ni%C5%BC+tylko+pieni%C4%85dze%3F" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/&amp;title=%5BPL%5D+Jak+odnale%C5%BA%C4%87+si%C4%99+w+bran%C5%BCy+IT+i+mie%C4%87+z+pracy+co%C5%9B+wi%C4%99cej+ni%C5%BC+tylko+pieni%C4%85dze%3F" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/&amp;title=%5BPL%5D+Jak+odnale%C5%BA%C4%87+si%C4%99+w+bran%C5%BCy+IT+i+mie%C4%87+z+pracy+co%C5%9B+wi%C4%99cej+ni%C5%BC+tylko+pieni%C4%85dze%3F&amp;srcUrl=http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/&amp;srcTitle=%5BPL%5D+Jak+odnale%C5%BA%C4%87+si%C4%99+w+bran%C5%BCy+IT+i+mie%C4%87+z+pracy+co%C5%9B+wi%C4%99cej+ni%C5%BC+tylko+pieni%C4%85dze%3F&amp;snippet=Po%20lekturze%20wielu%20wpis%C3%B3w%20na%20wielu%20blogach%20%28m.in.%20na%20blogach%20Mariusza%20K%C4%99dziory%20i%20Ma%C4%87ka%20Aniserowicza%29%20na%20temat%20pracy%20w%20bran%C5%BCy%20IT%2C%20specjalizacji%2C%20planowania%20kariery%20i%20podobnych%20spraw%20postanowi%C5%82em%2C%20%C5%BCe%20i%20ja%20dorzuc%C4%99%20do%20tego%20zestawu%20co%C5%9B%20od%20siebie.%20Okazja%20nadarza%20si%C4%99%20niez%C5%82a%2C%20jako%20%C5%BCe%20w%20tym%20roku%20min%C4%99%C5%82o%2010%20lat%20odk%C4%85d%20pracuj%C4%99%20w%20bran%C5%BCy%20IT." rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
<li class="shr-gmail">
			<a href="https://mail.google.com/mail/?ui=2&amp;view=cm&amp;fs=1&amp;tf=1&amp;su=%5BPL%5D+Jak+odnale%C5%BA%C4%87+si%C4%99+w+bran%C5%BCy+IT+i+mie%C4%87+z+pracy+co%C5%9B+wi%C4%99cej+ni%C5%BC+tylko+pieni%C4%85dze%3F&amp;body=Link: http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Po%20lekturze%20wielu%20wpis%C3%B3w%20na%20wielu%20blogach%20%28m.in.%20na%20blogach%20Mariusza%20K%C4%99dziory%20i%20Ma%C4%87ka%20Aniserowicza%29%20na%20temat%20pracy%20w%20bran%C5%BCy%20IT%2C%20specjalizacji%2C%20planowania%20kariery%20i%20podobnych%20spraw%20postanowi%C5%82em%2C%20%C5%BCe%20i%20ja%20dorzuc%C4%99%20do%20tego%20zestawu%20co%C5%9B%20od%20siebie.%20Okazja%20nadarza%20si%C4%99%20niez%C5%82a%2C%20jako%20%C5%BCe%20w%20tym%20roku%20min%C4%99%C5%82o%2010%20lat%20odk%C4%85d%20pracuj%C4%99%20w%20bran%C5%BCy%20IT." rel="nofollow" class="external" title="Email this via Gmail">Email this via Gmail</a>
		</li>
<li class="shr-googlebookmarks">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/&amp;title=%5BPL%5D+Jak+odnale%C5%BA%C4%87+si%C4%99+w+bran%C5%BCy+IT+i+mie%C4%87+z+pracy+co%C5%9B+wi%C4%99cej+ni%C5%BC+tylko+pieni%C4%85dze%3F" rel="nofollow" class="external" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
<li class="shr-hotmail">
			<a href="http://mail.live.com/?rru=compose?subject=%5BPL%5D+Jak+odnale%C5%BA%C4%87+si%C4%99+w+bran%C5%BCy+IT+i+mie%C4%87+z+pracy+co%C5%9B+wi%C4%99cej+ni%C5%BC+tylko+pieni%C4%85dze%3F&amp;body=Link: http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Po%20lekturze%20wielu%20wpis%C3%B3w%20na%20wielu%20blogach%20%28m.in.%20na%20blogach%20Mariusza%20K%C4%99dziory%20i%20Ma%C4%87ka%20Aniserowicza%29%20na%20temat%20pracy%20w%20bran%C5%BCy%20IT%2C%20specjalizacji%2C%20planowania%20kariery%20i%20podobnych%20spraw%20postanowi%C5%82em%2C%20%C5%BCe%20i%20ja%20dorzuc%C4%99%20do%20tego%20zestawu%20co%C5%9B%20od%20siebie.%20Okazja%20nadarza%20si%C4%99%20niez%C5%82a%2C%20jako%20%C5%BCe%20w%20tym%20roku%20min%C4%99%C5%82o%2010%20lat%20odk%C4%85d%20pracuj%C4%99%20w%20bran%C5%BCy%20IT." rel="nofollow" class="external" title="Email this via Hotmail">Email this via Hotmail</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sqlgeek.pl/2010/08/21/pl-jak-odnalezc-sie-w-branzy-it-i-miec-z-pracy-cos-wiecej-niz-tylko-pieniadze/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>[PL] Ewolucja SQLGeek.pl – potrzebny feedback</title>
		<link>http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/</link>
		<comments>http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/#comments</comments>
		<pubDate>Fri, 20 Aug 2010 09:40:13 +0000</pubDate>
		<dc:creator>Pawel Potasinski</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[feedback]]></category>
		<category><![CDATA[SQLGeek]]></category>

		<guid isPermaLink="false">http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/</guid>
		<description><![CDATA[Ostatnio zrobiłem porządki na blogu. SQLGeek.pl wreszcie zaczął chyba przypominać blog ;-) Teraz, gdy już pozamiatałem, usunąłem niepotrzebne pluginy WordPressa, uporządkowałem kategorie i dodałem archiwum wpisów, mogę iść dalej.

Do tego potrzebny mi jest feedback czytelników mojego bloga. A zatem…]]></description>
			<content:encoded><![CDATA[<p>Ostatnio zrobiłem porządki na blogu. SQLGeek.pl wreszcie zaczął chyba przypominać blog ;-) Teraz, gdy już pozamiatałem, usunąłem niepotrzebne pluginy WordPressa, uporządkowałem kategorie i dodałem <a href="http://sqlgeek.pl/archives/">archiwum wpisów,</a> mogę iść dalej.</p>
<p>Do tego potrzebny mi jest feedback czytelników mojego bloga. A zatem…</p>
<p>1) Po prawej stronie znajduje się ankieta – prosta, by nie rzec banalna. Chodzi o układ <a href="http://sqlgeek.pl/">strony głównej</a> bloga. Czy lepiej się go czyta, gdy na stronie głównej są tylko “zajawki” wpisów, czy może jednak lepiej było, gdy wyświetlała się pełna treść wpisów? Bardzo proszę o pomoc w tym temacie. To dla Waszej wygody! Ankieta będzie aktywna do końca sierpnia.</p>
<p>2) Tematy. Ja mogę jeszcze długo i namiętnie smarować o SQL Serverze ;-) Ale może są jakieś tematy, o których poczytałbyś / poczytałabyś chętniej niż o innych? Jeżeli tak jest, daj znać – czy to w komentarzu do tego wpisu, czy na adres mailowy podany na stronie <a href="http://sqlgeek.pl/about">o autorze bloga</a>.</p>
<p>Przypinam ten wpis, żeby wisiał póki co na wierzchu :-) I czekam na Twój feedback. Dla najbardziej kreatywnych i pomocnych – “ustne gratulacje ojca prowadzącego” :-)</p>
<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center">
<ul class="socials">
<li class="shr-comfeed">
			<a href="http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
<li class="shr-twitter">
			<a href="http://twitter.com/home?status=%5BPL%5D+Ewolucja+SQLGeek.pl+%E2%80%93+potrzebny+feedback+-+http://b2l.me/ajn75t&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/&amp;t=%5BPL%5D+Ewolucja+SQLGeek.pl+%E2%80%93+potrzebny+feedback" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
<li class="shr-linkedin">
			<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/&amp;title=%5BPL%5D+Ewolucja+SQLGeek.pl+%E2%80%93+potrzebny+feedback&amp;summary=Ostatnio%20zrobi%C5%82em%20porz%C4%85dki%20na%20blogu.%20SQLGeek.pl%20wreszcie%20zacz%C4%85%C5%82%20chyba%20przypomina%C4%87%20blog%20%3B-%29%20Teraz%2C%20gdy%20ju%C5%BC%20pozamiata%C5%82em%2C%20usun%C4%85%C5%82em%20niepotrzebne%20pluginy%20WordPressa%2C%20uporz%C4%85dkowa%C5%82em%20kategorie%20i%20doda%C5%82em%20archiwum%20wpis%C3%B3w%2C%20mog%C4%99%20i%C5%9B%C4%87%20dalej.%0D%0A%0D%0ADo%20tego%20potrzebny%20mi%20jest%20feedback%20czytelnik%C3%B3w%20mojego%20bloga.%20A%20zatem%E2%80%A6&amp;source=SQLGeek.pl" rel="nofollow" class="external" title="Share this on LinkedIn">Share this on LinkedIn</a>
		</li>
<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/&amp;title=%5BPL%5D+Ewolucja+SQLGeek.pl+%E2%80%93+potrzebny+feedback" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/&amp;title=%5BPL%5D+Ewolucja+SQLGeek.pl+%E2%80%93+potrzebny+feedback" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
<li class="shr-googlereader">
			<a href="http://www.google.com/reader/link?url=http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/&amp;title=%5BPL%5D+Ewolucja+SQLGeek.pl+%E2%80%93+potrzebny+feedback&amp;srcUrl=http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/&amp;srcTitle=%5BPL%5D+Ewolucja+SQLGeek.pl+%E2%80%93+potrzebny+feedback&amp;snippet=Ostatnio%20zrobi%C5%82em%20porz%C4%85dki%20na%20blogu.%20SQLGeek.pl%20wreszcie%20zacz%C4%85%C5%82%20chyba%20przypomina%C4%87%20blog%20%3B-%29%20Teraz%2C%20gdy%20ju%C5%BC%20pozamiata%C5%82em%2C%20usun%C4%85%C5%82em%20niepotrzebne%20pluginy%20WordPressa%2C%20uporz%C4%85dkowa%C5%82em%20kategorie%20i%20doda%C5%82em%20archiwum%20wpis%C3%B3w%2C%20mog%C4%99%20i%C5%9B%C4%87%20dalej.%0D%0A%0D%0ADo%20tego%20potrzebny%20mi%20jest%20feedback%20czytelnik%C3%B3w%20mojego%20bloga.%20A%20zatem%E2%80%A6" rel="nofollow" class="external" title="Add this to Google Reader">Add this to Google Reader</a>
		</li>
<li class="shr-gmail">
			<a href="https://mail.google.com/mail/?ui=2&amp;view=cm&amp;fs=1&amp;tf=1&amp;su=%5BPL%5D+Ewolucja+SQLGeek.pl+%E2%80%93+potrzebny+feedback&amp;body=Link: http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Ostatnio%20zrobi%C5%82em%20porz%C4%85dki%20na%20blogu.%20SQLGeek.pl%20wreszcie%20zacz%C4%85%C5%82%20chyba%20przypomina%C4%87%20blog%20%3B-%29%20Teraz%2C%20gdy%20ju%C5%BC%20pozamiata%C5%82em%2C%20usun%C4%85%C5%82em%20niepotrzebne%20pluginy%20WordPressa%2C%20uporz%C4%85dkowa%C5%82em%20kategorie%20i%20doda%C5%82em%20archiwum%20wpis%C3%B3w%2C%20mog%C4%99%20i%C5%9B%C4%87%20dalej.%0D%0A%0D%0ADo%20tego%20potrzebny%20mi%20jest%20feedback%20czytelnik%C3%B3w%20mojego%20bloga.%20A%20zatem%E2%80%A6" rel="nofollow" class="external" title="Email this via Gmail">Email this via Gmail</a>
		</li>
<li class="shr-googlebookmarks">
			<a href="http://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/&amp;title=%5BPL%5D+Ewolucja+SQLGeek.pl+%E2%80%93+potrzebny+feedback" rel="nofollow" class="external" title="Add this to Google Bookmarks">Add this to Google Bookmarks</a>
		</li>
<li class="shr-hotmail">
			<a href="http://mail.live.com/?rru=compose?subject=%5BPL%5D+Ewolucja+SQLGeek.pl+%E2%80%93+potrzebny+feedback&amp;body=Link: http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/ (sent via shareaholic)%0D%0A%0D%0A----%0D%0A Ostatnio%20zrobi%C5%82em%20porz%C4%85dki%20na%20blogu.%20SQLGeek.pl%20wreszcie%20zacz%C4%85%C5%82%20chyba%20przypomina%C4%87%20blog%20%3B-%29%20Teraz%2C%20gdy%20ju%C5%BC%20pozamiata%C5%82em%2C%20usun%C4%85%C5%82em%20niepotrzebne%20pluginy%20WordPressa%2C%20uporz%C4%85dkowa%C5%82em%20kategorie%20i%20doda%C5%82em%20archiwum%20wpis%C3%B3w%2C%20mog%C4%99%20i%C5%9B%C4%87%20dalej.%0D%0A%0D%0ADo%20tego%20potrzebny%20mi%20jest%20feedback%20czytelnik%C3%B3w%20mojego%20bloga.%20A%20zatem%E2%80%A6" rel="nofollow" class="external" title="Email this via Hotmail">Email this via Hotmail</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sqlgeek.pl/2010/08/20/pl-ewolucja-sqlgeek-pl-potrzebny-feedback/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
