<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://zine.net.pl/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang=""><title type="html">Marek Adamczuk</title><subtitle type="html" /><id>http://zine.net.pl/blogs/mad/atom.aspx</id><link rel="alternate" type="text/html" href="http://zine.net.pl/blogs/mad/default.aspx" /><link rel="self" type="application/atom+xml" href="http://zine.net.pl/blogs/mad/atom.aspx" /><generator uri="http://communityserver.org" version="2.1.61129.2">Community Server</generator><updated>2008-07-07T22:52:03Z</updated><entry><title>Limit 8060 bajtów na wiersz odszedł inaczej</title><link rel="alternate" type="text/html" href="http://zine.net.pl/blogs/mad/archive/2008/08/30/limit-8060-bajt-w-na-wiersz-odszed-inaczej.aspx" /><id>http://zine.net.pl/blogs/mad/archive/2008/08/30/limit-8060-bajt-w-na-wiersz-odszed-inaczej.aspx</id><published>2008-08-30T19:44:00Z</published><updated>2008-08-30T19:44:00Z</updated><content type="html">&lt;P&gt;Jedną z istotnych nowości w SQL Server 2005 było zniesienie limitu 8060 bajtów zapisanych w jednym wierszu. Oto krótki test.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;create&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;table&lt;/span&gt; dbo.temp_duzaTabela ( &lt;br /&gt;    a &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;varchar&lt;/span&gt;(8000), &lt;br /&gt;    b &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;varchar&lt;/span&gt;(8000), &lt;br /&gt;    c &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;varchar&lt;/span&gt;(8000) &lt;br /&gt;    )&lt;br /&gt;&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;insert&lt;/span&gt; dbo.temp_duzaTabela (a,b,c) &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;select&lt;/span&gt; &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;replicate&lt;/span&gt;(&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'x'&lt;/span&gt;,8000),&lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;replicate&lt;/span&gt;(&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'x'&lt;/span&gt;,8000),&lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;replicate&lt;/span&gt;(&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'x'&lt;/span&gt;,8000)&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Na SQL Server 2000 pierwszy batch generował ostrzeżenie, a drugi błąd. Na SQL Server 2005 oba przechodzą bez problemu. Czy zatem limit 8060 bajtów odszedł? Niestety nie do końca. Spróbujmy tego samego z kolumnami typu char.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;create&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;table&lt;/span&gt; dbo.temp_duzaTabela ( &lt;br /&gt;    a &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;char&lt;/span&gt;(8000), &lt;br /&gt;    b &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;char&lt;/span&gt;(8000), &lt;br /&gt;    c &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;char&lt;/span&gt;(8000) &lt;br /&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Próba wykonania tego batcha ku mojemu zdziwieniu skończyła się komunikatem:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff0000&gt;Msg 1701, Level 16, State 1, Line 1 &lt;BR&gt;Creating or altering table 'temp_duzaTabela' failed because the minimum row size would be 24007, including 7 bytes of internal overhead. This exceeds the maximum allowable table row size of 8060 bytes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Chwila uparczywego wpatrywania się w komunikat obnaża problem. Kluczowe jest tu słówko minimum. Zatem dla minimalnej wielkości wiersza limit wciąż obowiązuje.&amp;nbsp;Problem rozwiązuje w jakiejś mierze&amp;nbsp;SQL Server 2008 w tej kwestii bynajmniej nie wprowadza żadnej nowej jakości.&lt;/P&gt;
&lt;P&gt;Dziękuję Pawłowi Gailardowi za uświadomienie mi tego problemu.&lt;/P&gt;
&lt;P&gt;[01-09-2008] Edycja: Okazuje się, że jednak SQL Server 2008 w jakiś sposób&amp;nbsp;życie nam tu ułatwia. Nie automatycznie, ale jednak.&amp;nbsp;Otóż atrybut SPARSE powoduje, że damy radę założyć tabelę z typami o stałej długości przekraczającymi sumarycznie 8060 bajtów. &lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;create&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;table&lt;/span&gt; dbo.temp_duzaTabela ( &lt;br /&gt;    a &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;char&lt;/span&gt;(8000) SPARSE, &lt;br /&gt;    b &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;char&lt;/span&gt;(8000) SPARSE, &lt;br /&gt;    c &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;char&lt;/span&gt;(8000) SPARSE&lt;br /&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=1858" width="1" height="1"&gt;</content><author><name>mad</name><uri>http://zine.net.pl/members/mad.aspx</uri></author><category term="SQL Server" scheme="http://zine.net.pl/blogs/mad/archive/tags/SQL+Server/default.aspx" /><category term="row length limit" scheme="http://zine.net.pl/blogs/mad/archive/tags/row+length+limit/default.aspx" /><category term="Sparse" scheme="http://zine.net.pl/blogs/mad/archive/tags/Sparse/default.aspx" /></entry><entry><title>Konkurs - przywrócenie pierwotnej kolejności kolumn tabeli</title><link rel="alternate" type="text/html" href="http://zine.net.pl/blogs/mad/archive/2008/07/23/konkurs-przywr-cenie-pierwotnej-kolejno-ci-kolumn-tabeli.aspx" /><id>http://zine.net.pl/blogs/mad/archive/2008/07/23/konkurs-przywr-cenie-pierwotnej-kolejno-ci-kolumn-tabeli.aspx</id><published>2008-07-23T19:24:00Z</published><updated>2008-07-23T19:24:00Z</updated><content type="html">&lt;P&gt;Zgodnie z obietnicą ogłaszam konkurs zapowiedziany na wczorajszej sesji PLSSUG. Zadanie polega na przywróceniu pierwotnej kolejności kolumn tabeli po usunięciu i ponownym odtworzeniu kolumny wyliczanej. Np. mamy tabelę:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;create&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;table&lt;/span&gt; dbo.Osoby ( &lt;br /&gt;id &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;int&lt;/span&gt;, &lt;br /&gt;Imie &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;varchar&lt;/span&gt;(50) &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;NOT&lt;/span&gt; &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;NULL&lt;/span&gt;, &lt;br /&gt;Nazwisko &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;varchar&lt;/span&gt;(100) &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;NOT&lt;/span&gt; &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;NULL&lt;/span&gt;, &lt;br /&gt;NazwaPelna &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;as&lt;/span&gt; Imie+&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;' '&lt;/span&gt;+Nazwisko, &lt;br /&gt;TelefonDoPracy &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;varchar&lt;/span&gt;(30) &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;NULL&lt;/span&gt;, &lt;br /&gt;TelefonDomowy &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;varchar&lt;/span&gt;(30) &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;NULL&lt;/span&gt;, &lt;br /&gt;TelefonKom &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;varchar&lt;/span&gt;(30) &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;NULL&lt;/span&gt;, &lt;br /&gt;Telefony &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;as&lt;/span&gt;  &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;ISNULL&lt;/span&gt;(TelefonDoPracy+&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;';'&lt;/span&gt;,&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;''&lt;/span&gt;)+&lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;ISNULL&lt;/span&gt;(TelefonDomowy+&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;';'&lt;/span&gt;,&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;''&lt;/span&gt;)+&lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;ISNULL&lt;/span&gt;(TelefonKom+&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;';'&lt;/span&gt;,&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;''&lt;/span&gt;),&lt;br /&gt;EMail &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;varchar&lt;/span&gt;(100), &lt;br /&gt;DataRejestracji &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;datetime&lt;/span&gt;&lt;br /&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Po usunięciu i ponownym odtworzeniu kolumn NazwaPelna i Telefony, znajdą się one na końcu listy kolumn tabeli. Słabo napisane aplikacje mogą tej zmiany nie wytrzymać. Dlatego będziemy chcieli przywrócić kolejność pierwotną. &lt;/P&gt;
&lt;P&gt;W czasie sesji pokazałem, jak wygenerować skrypty, które dla dowolnej tabeli:&lt;/P&gt;
&lt;P&gt;1. Zapisze definicję wszystkich kolumn wyliczanych wraz z pierwotną kolejnością do tabeli &lt;BR&gt;2. Usunie wszystkie kolumny wyliczane&amp;nbsp; &lt;BR&gt;3. Odtworzy kolumny wyliczane (lądują na końcu listy)&lt;/P&gt;
&lt;P&gt;Definicja tabeli jest w skrypcie recollate.sql umieszczonych w &lt;A href="http://ms-groups.pl/communities/PLSSUG/Shared%20Documents/Forms/AllItems.aspx?RootFolder=%2fcommunities%2fPLSSUG%2fShared%20Documents%2fSkrypty%20SQL&amp;amp;FolderCTID=&amp;amp;View=%7b94539CEA%2d073B%2d47E6%2dB583%2d3F4E29D67266%7d" target=_blank&gt;zasobach&lt;/A&gt; PLSSUG. Dla wygody zacytuję ją ponownie tutaj.&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;create&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;table&lt;/span&gt; dbo.temp_ComputedCols ( &lt;br /&gt;    TableName &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;sysname&lt;/span&gt;, &lt;br /&gt;    ColumnName &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;sysname&lt;/span&gt;, &lt;br /&gt;    definition &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;nvarchar&lt;/span&gt;(&lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;max&lt;/span&gt;), &lt;br /&gt;    position &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;int&lt;/span&gt;, &lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;PRIMARY&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;KEY&lt;/span&gt; (TableName, ColumnName) &lt;br /&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Zadanie konkursowe polega na tym, żeby na podstawie definicji tabeli po operacji usunięcia i odtworzenia kolumn wyliczanych + zawartości tabeli temp_ComputedCols wygenerować skrypt, który doprowadzi tabelę do pierwotnej postaci - wszystkie kolumny są w tej samej kolejności co przed operacją. Linie skryptu mają być wygenerowane w języku TSQL w postaci procedury lub funkcji tabelarycznej. Jako jedyny parametr procedury/funkcji powinna być przekazana nazwa tabeli, dla której generujemy skrypt.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Warunki oceny rozwiązania:&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;1. Rozwiązanie nie może spowodować jakiejkolwiek utraty danych w tabeli &lt;BR&gt;2. Rozwiązanie powinno wykonać minimalną liczbę manipulacji na danych i strukturze tabeli &lt;BR&gt;3. Rozwiązanie powinno przewidywać, że jest więcej niż jedna kolumna wyliczana, tak jak w przykładzie &lt;BR&gt;4. Rozwiązanie powinno być możliwie jak najszybsze&lt;/P&gt;
&lt;P&gt;Dla uproszczenia zakładamy, że w chwili rozpoczęcia naprawy na tabeli, którą mamy naprawić nie ma żadnych więzów ani indeksów.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Czekam na rozwiązania konkursowe do końca 15-08-2008 - proszę o przysyłanie ich na mój mail z profilu na wss.pl. Najciekawsze rozwiązania opublikuję, a najlepsze nagrodzę na najbliższym spotkaniu PLSSUG. Do 10.08.2008 będę poza Polską i nie wiem, czy będę miał dostęp do maila, zatem proszę nie zrażać się brakiem mojej reakcji w tym czasie.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Pozdrawiam &lt;BR&gt;Marek Adamczuk&lt;/P&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=1608" width="1" height="1"&gt;</content><author><name>mad</name><uri>http://zine.net.pl/members/mad.aspx</uri></author><category term="SQL Server" scheme="http://zine.net.pl/blogs/mad/archive/tags/SQL+Server/default.aspx" /><category term="TSQL" scheme="http://zine.net.pl/blogs/mad/archive/tags/TSQL/default.aspx" /><category term="konkurs" scheme="http://zine.net.pl/blogs/mad/archive/tags/konkurs/default.aspx" /><category term="Kolumny wyliczane" scheme="http://zine.net.pl/blogs/mad/archive/tags/Kolumny+wyliczane/default.aspx" /></entry><entry><title>Hash czy małpa a sprawa collation</title><link rel="alternate" type="text/html" href="http://zine.net.pl/blogs/mad/archive/2008/07/23/hash-czy-ma-pa-a-sprawa-collation.aspx" /><id>http://zine.net.pl/blogs/mad/archive/2008/07/23/hash-czy-ma-pa-a-sprawa-collation.aspx</id><published>2008-07-23T09:56:00Z</published><updated>2008-07-23T09:56:00Z</updated><content type="html">&lt;P&gt;Wczoraj miałem przyjemność poprowadzić na PLSSUG Warszawa prezentację dotyczącą collation na SQL Serverze. W czasie prezentacji wygłosiłem pewną, nie do końca uprawnioną tezę. Mianowicie stwierdziłem, że collation z którym zakładane są domyślnie kolumny tabeli tymczasowej ustawia się na collation bazy bieżącej w SQL Server 2005 i z collation bazy tempdb w SQL Server 2000. W rzeczywistości jest to prawdą tylko dla zmiennych tablicowych. Oto przykład:&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;&lt;span style="color: Teal;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;-- ważne, żeby to nie było collation servera!&lt;/span&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;create&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;database&lt;/span&gt; bad_db &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;collate&lt;/span&gt; SQL_Polish_CP1250_CI_AS&lt;br /&gt;GO&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;use&lt;/span&gt; bad_db&lt;br /&gt;GO&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;declare&lt;/span&gt; @t &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;table&lt;/span&gt; (a &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;nvarchar&lt;/span&gt;(128))&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;select&lt;/span&gt; * &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; @t t &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;join&lt;/span&gt; &lt;span style="color: LawnGreen;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;sysobjects&lt;/span&gt; o &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;on&lt;/span&gt; t.a = o.name&lt;br /&gt;GO&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;create&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;table&lt;/span&gt; #t (a &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;nvarchar&lt;/span&gt;(128))&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;select&lt;/span&gt; * &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; #t t &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;join&lt;/span&gt; &lt;span style="color: LawnGreen;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;sysobjects&lt;/span&gt; o &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;on&lt;/span&gt; t.a = o.name&lt;br /&gt;GO&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Przykład uruchamiamy na SQL Server 2000 i SQL Server 2005. Jak się okazuje, query ze zmienną tablicową wykonuje się prawidłowo tylko na 2005. Wszystkie inne zwracają błąd konfliktu collation. Zatem #tabele tymczasowe w kontekście collation nadal są złe na SQL Server 2005. Co więcej, test przeprowadzony na ostatnim dostępnym mi buildzie SQL Server 2008 daje identyczny rezultat, co 2005.&lt;/P&gt;
&lt;P&gt;Czy zatem, będąc świadomymi zła, jesteśmy w stanie mu zaradzić? Owszem jesteśmy, ale wymaga to zmiany przyzwyczajeń w pisaniu kodu. Otóż, aby być collation insensitive, musimy przy tworzeniu tabel tymczasowych, a na SQL 2000 również zmiennych tablicowych, dopisywać przy stringowych kolumnach klauzulę COLLATE database_default. Na naszym przykładzie wygląda to tak:&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;&lt;span style="color: Teal;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;-- tak już nie musimy robić na SQL Server 2005 i wyższych&lt;/span&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;declare&lt;/span&gt; @t &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;table&lt;/span&gt; (a &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;nvarchar&lt;/span&gt;(128) &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;collate&lt;/span&gt; database_default)&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;select&lt;/span&gt; * &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; @t t &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;join&lt;/span&gt; &lt;span style="color: LawnGreen;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;sysobjects&lt;/span&gt; o &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;on&lt;/span&gt; t.a = o.name&lt;br /&gt;GO&lt;br /&gt;&lt;span style="color: Teal;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;-- tak niestety musimy nadal&lt;/span&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;create&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;table&lt;/span&gt; #t (a &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;nvarchar&lt;/span&gt;(128) &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;collate&lt;/span&gt; database_default)&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;select&lt;/span&gt; * &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; #t t &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;join&lt;/span&gt; &lt;span style="color: LawnGreen;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;sysobjects&lt;/span&gt; o &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;on&lt;/span&gt; t.a = o.name&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;drop&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;table&lt;/span&gt; #t&lt;br /&gt;GO&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Wnioski&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Jeśli nie chcemy mieć potencjalnego konfliktu collation: &lt;BR&gt;1. Dopisujemy collate database_default przy definicjach kolumn stringowych #tabel tymczasowych zawsze i zmiennych @tablicowych na SQL 2000. &lt;BR&gt;2. Jeśli mamy SQL 2005 i nie chcemy wyrabiać sobie odruchu z punktu 1 - bardziej lubimy @tabele niż #tabele. Abstrahując od innych warunków ich zastosowania, rzecz jasna.&lt;/P&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=1605" width="1" height="1"&gt;</content><author><name>mad</name><uri>http://zine.net.pl/members/mad.aspx</uri></author><category term="SQL" scheme="http://zine.net.pl/blogs/mad/archive/tags/SQL/default.aspx" /><category term="Tabela tymczasowa" scheme="http://zine.net.pl/blogs/mad/archive/tags/Tabela+tymczasowa/default.aspx" /><category term="Collation" scheme="http://zine.net.pl/blogs/mad/archive/tags/Collation/default.aspx" /><category term="SQL Server" scheme="http://zine.net.pl/blogs/mad/archive/tags/SQL+Server/default.aspx" /><category term="zmienna tablicowa" scheme="http://zine.net.pl/blogs/mad/archive/tags/zmienna+tablicowa/default.aspx" /><category term="T-SQL" scheme="http://zine.net.pl/blogs/mad/archive/tags/T-SQL/default.aspx" /></entry><entry><title>Obsługa wyjątków na SQL - (nie) daj się złapać</title><link rel="alternate" type="text/html" href="http://zine.net.pl/blogs/mad/archive/2008/07/07/obs-uga-wyj-tk-w-na-sql-daj-si-z-apa.aspx" /><id>http://zine.net.pl/blogs/mad/archive/2008/07/07/obs-uga-wyj-tk-w-na-sql-daj-si-z-apa.aspx</id><published>2008-07-07T20:59:00Z</published><updated>2008-07-07T20:59:00Z</updated><content type="html">&lt;P&gt;Będzie trochę o obsłudze wyjątków na SQL Server. O tym, kiedy może okazać się przydatna i jakie czyhają pułapki. A będzie na przykładzie. Otóż mamy sytuację, w której musimy na chwilę zdropić sporą ilość obiektów proceduralnych na bazie danych, aby je po wykonaniu pewnej operacji odtworzyć. Po co? O tym za następnym razem. Dziś skupię się na zawiłościach dropienia i odtwarzania obiektów. Dla uproszczenia wywodu przyjmijmy, że wszystkie interesujące nas obiekty należą do schematu dbo i są procedurami, widokami, funkcjami TSQL wszelkiej maści lub triggerami. Przyjmijmy też, że nazwy obiektów podlegających naszej operacji mamy w następującej tabeli:&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;create&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;table&lt;/span&gt; dbo.ObjectsToRecreate (&lt;br /&gt;  ObjectName &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;sysname&lt;/span&gt; &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;NOT&lt;/span&gt; &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;NULL&lt;/span&gt;,&lt;br /&gt;  ObjectDefinition &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;sysname&lt;/span&gt; &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;NULL&lt;/span&gt;,&lt;br /&gt;  ObjectId &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;int&lt;/span&gt; &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;NULL&lt;/span&gt;,&lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;CONSTRAINT&lt;/span&gt; PK_ObjectsToRecreate &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;PRIMARY&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;KEY&lt;/span&gt; (ObjectName))&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Aby było co odtwarzać po zdropieniu - zapiszmy sobie definicje obiektów do naszej tabeli. Z SQL Server 2005 sprawa jest prosta - używamy nowej, fajnej funkcji object_definition. &lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;update&lt;/span&gt; ObjectsToRecreate &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;SET&lt;/span&gt; ObjectDefinition = OBJECT_DEFINITION(&lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;OBJECT_ID&lt;/span&gt;(ObjectName))&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Kiedy już mamy kopię treści ciał obiektów możemy zabrać się do dropienia. O ile obiekty nie są użyte w innych z klauzulą SCHEMABINDING, tudzież w niskopoziomowych obiektach takich jak defaulty, checki czy kolumny wyliczalne - operacja powinna pójść bezproblemowo. Jak? Sprawę załatwi kawałek dynamicznego SQL-a.&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;declare&lt;/span&gt; @sql &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;nvarchar&lt;/span&gt;(&lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;max&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;select&lt;/span&gt; @sql = N&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;''&lt;/span&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;select&lt;/span&gt; @sql = @sql +N&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'drop '&lt;/span&gt;+ &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;case&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;when&lt;/span&gt; o.type &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;in&lt;/span&gt; (&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'IF'&lt;/span&gt;,&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'TF'&lt;/span&gt;,&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'FN'&lt;/span&gt;) &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;then&lt;/span&gt; N&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'function '&lt;/span&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;when&lt;/span&gt; o.type = &lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'P'&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;then&lt;/span&gt; N&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'procedure '&lt;/span&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;when&lt;/span&gt; o.type = &lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'V'&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;then&lt;/span&gt; N&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'view '&lt;/span&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;when&lt;/span&gt; o.type = &lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'TR'&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;then&lt;/span&gt; N&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'trigger '&lt;/span&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;end&lt;/span&gt; +schema_name(o.schema_id)+N&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;'.'&lt;/span&gt;+&lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;quotename&lt;/span&gt;(o.name)+N&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;';'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; dbo.objectsToRecreate otr&lt;br /&gt;&lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;join&lt;/span&gt; sys.objects o &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;on&lt;/span&gt; otr.ObjectName = o.name&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;exec&lt;/span&gt; (@sql)&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Teraz śmiało wykonujemy naszą operację, której przeszkadzałyby zdropione obiekty i zabieramy się do ich odtworzenia. Tym razem raczej nie obejdzie się bez kursora. Nie wydaje się on na pierwszy rzut oka czymś specjalnie trudnym:&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;declare&lt;/span&gt; @definition &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;nvarchar&lt;/span&gt;(&lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;max&lt;/span&gt;)&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;declare&lt;/span&gt; c &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;cursor&lt;/span&gt; local static read_only forward_only&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;for&lt;/span&gt; &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;select&lt;/span&gt; ObjectDefinition &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; dbo.objectsToRecreate&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;open&lt;/span&gt; c&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;fetch&lt;/span&gt; next &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; c &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;into&lt;/span&gt; @definition&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;while&lt;/span&gt; &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;@@fetch_status&lt;/span&gt; = 0 &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;begin&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;exec&lt;/span&gt; (@definition)&lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;fetch&lt;/span&gt; next &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; c &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;into&lt;/span&gt; @definition  &lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;close&lt;/span&gt; c &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;deallocate&lt;/span&gt; c&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Wszystko zadziała pięknie, o ile usunięte uprzednio obiekty nie będą zależne od siebie. Szczególnie boleśnie możemy to odczuć na widokach i funkcjach. Jeśli nie odtworzymy obiektów we właściwej kolejności – operacja po prostu się nie uda. Pytanie tylko: Jak znaleźć tę właściwą kolejność? Jak się okazuje – pytanie niebanalne. Mamy wprawdzie tabelę sys.sql_dependencies, ale po zdropieniu obiektów pustą, a i przed trudno wciąż jej ufać. Nawet gdy ją mamy porządnie uzupełnioną – rozplątanie właściwej kolejności obiektów w skomplikowanym przypadku wcale nie jest oczywiste. O sys.sql_dependencies napiszę innym razem – to temat na osobny artykuł. Tymczasem jest dużo prostsza metoda na uzyskanie właściwej kolejności. Jednym zdaniem: próbuj odtwarzać obiekty do skutku. Osiągniemy to łatwo obudowując nasz kod pętlą while. Kończymy, gdy uda nam się odtworzyć wszystkie obiekty. Aby nie oglądać paskudnych komunikatów błędów – opakujmy nasz kod bloki obsługi wyjątków:&lt;/P&gt;
&lt;P&gt;&lt;code&gt;&lt;span style="color: Black;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;declare&lt;/span&gt; @definition &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;nvarchar&lt;/span&gt;(&lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;max&lt;/span&gt;), @name &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;sysname&lt;/span&gt;&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;while&lt;/span&gt; &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;exists&lt;/span&gt; (&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;select&lt;/span&gt; 1 &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; dbo.objectsToRecreate &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;where&lt;/span&gt; objectId &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;is&lt;/span&gt; &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;null&lt;/span&gt;) &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;begin&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;declare&lt;/span&gt; c &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;cursor&lt;/span&gt; local static read_only forward_only&lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;for&lt;/span&gt; &lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;select&lt;/span&gt; ObjectDefinition, ObjectName &lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; dbo.objectsToRecreate &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;where&lt;/span&gt; objectId &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;is&lt;/span&gt; &lt;span style="color: Silver;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;null&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;open&lt;/span&gt; c&lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;fetch&lt;/span&gt; next &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; c &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;into&lt;/span&gt; @definition, @name&lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;while&lt;/span&gt; &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;@@fetch_status&lt;/span&gt; = 0 &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;begin&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;begin&lt;/span&gt; try&lt;br /&gt;      &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;exec&lt;/span&gt; (@definition)&lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;end&lt;/span&gt; try&lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;begin&lt;/span&gt; catch&lt;br /&gt;      &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;set&lt;/span&gt; @definition = @name+&lt;span style="color: Red;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;':'&lt;/span&gt;+error_message()&lt;br /&gt;      &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;print&lt;/span&gt; @definition&lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;end&lt;/span&gt; catch&lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;update&lt;/span&gt; dbo.objectsToRecreate &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;set&lt;/span&gt; objectId = &lt;span style="color: Fuchsia;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;object_id&lt;/span&gt;(@name) &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;where&lt;/span&gt; ObjectName = @name&lt;br /&gt;    &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;fetch&lt;/span&gt; next &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;from&lt;/span&gt; c &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;into&lt;/span&gt; @definition, @name  &lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;close&lt;/span&gt; c &lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;deallocate&lt;/span&gt; c&lt;br /&gt;&lt;span style="color: Blue;background-color: Transparent;font-family: Courier New;font-size: 11px;font-weight: normal;"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/P&gt;
&lt;P&gt;Jeśli nasza baza była spójna na moment zdropienia, po kilku iteracjach będziemy mieli prawidłowo odtworzone obiekty. Niestety nasza radość trwa do momentu opakowania w/w kodu w transakcję. Po pierwszym błędzie, każda kolejna próba odtworzenia, prawidłowa lub nie,&amp;nbsp; kończy się komunikatem:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff0000&gt;Msg 3930, Level 16, State 1, Line 18&lt;BR&gt;The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Co gorsza, ten kod nigdy się nie kończy, bo nigdy nie dojdziemy do warunku wyjścia z pętli. I niestety dochodzimy tu do poważnego ograniczenia stosowalności mechanizmu obsługi wyjątków na SQL-u w obecnie dostępnych wersjach. I właśnie z tego powodu w tym miejscu porzuciłem ten mechanizm do rozwiązania bieżącego problemu i dobrałem się do niego w zupełnie inny sposób. Wniosek: jeśli używamy try catch, nie liczmy na to, że uda nam się w tej samej transakcji cokolwiek jeszcze wykonać poza zaprezentowaniem błędu. Musimy być zawsze gotowi na zakończenie transakcji po takiej operacji.&lt;/P&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=1442" width="1" height="1"&gt;</content><author><name>mad</name><uri>http://zine.net.pl/members/mad.aspx</uri></author></entry><entry><title>Pierwszy raz ...</title><link rel="alternate" type="text/html" href="http://zine.net.pl/blogs/mad/archive/2008/07/07/pierwszy-raz.aspx" /><id>http://zine.net.pl/blogs/mad/archive/2008/07/07/pierwszy-raz.aspx</id><published>2008-07-07T20:52:03Z</published><updated>2008-07-07T20:52:03Z</updated><content type="html">&lt;p&gt;...kiedyś musi być. Do tej pory nie prowadziłem jeszcze bloga i nie mam pojęcia, jak mi to będzie szło. Nam&amp;#243;wiony przez Pawła Potasińskiego skorzystałem z uprzejmości Michała Grzegorzewskiego i postanowiłem spr&amp;#243;bować. Inaczej nigdy się nie przekonam. Będę tu pisał o tym, czym co dzień zaskakuje mnie SQL Server i inne wynalazki świata informatyki. Pierwszy tekst już niebawem.&lt;/p&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=1439" width="1" height="1"&gt;</content><author><name>mad</name><uri>http://zine.net.pl/members/mad.aspx</uri></author></entry></feed>