<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>SQL Server på svenska</title>
    <link>http://www.underlandet.com/SqlServer/</link>
    <description>En svensk blogg om SQL Server, skriven på svenska</description>
    <language>en-us</language>
    <copyright>Magnus Ahlkvist</copyright>
    <lastBuildDate>Thu, 24 Jun 2010 21:29:46 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.0.7226.0</generator>
    <managingEditor>magnus.ahlkvist@vansterpartiet.se</managingEditor>
    <webMaster>magnus.ahlkvist@vansterpartiet.se</webMaster>
    <item>
      <trackback:ping>http://www.underlandet.com/SqlServer/Trackback.aspx?guid=dfddba20-57c1-4396-9d78-3f3c2dc3fbe7</trackback:ping>
      <pingback:server>http://www.underlandet.com/SqlServer/pingback.aspx</pingback:server>
      <pingback:target>http://www.underlandet.com/SqlServer/PermaLink,guid,dfddba20-57c1-4396-9d78-3f3c2dc3fbe7.aspx</pingback:target>
      <dc:creator>Magnus Ahlkvist</dc:creator>
      <wfw:comment>http://www.underlandet.com/SqlServer/CommentView,guid,dfddba20-57c1-4396-9d78-3f3c2dc3fbe7.aspx</wfw:comment>
      <wfw:commentRss>http://www.underlandet.com/SqlServer/SyndicationService.asmx/GetEntryCommentsRss?guid=dfddba20-57c1-4396-9d78-3f3c2dc3fbe7</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Flera gånger har jag sett och svarat på en fråga om sortering i SQL Server. Frågan
har formulerats på olika sätt, men I princip är det samma fråga som ställts:
</p>
        <blockquote>
          <p>
            <em>När jag gör SELECT mot min tabell får jag tillbaka raderna i “fel” ordning, jag
lade till rad A först, sen rad B, men SQL Server ger mig rad B före rad A.</em>
          </p>
        </blockquote>
        <p>
Det är en vanlig missuppfattning att SQL Server ger oss rader i någon särskild ordning.
Men det kan vi inte på något sätt förvänta oss att SQL Server gör. SQL Server försöker
att ge oss det vi frågar om så snabbt som möjligt. Om vi ber om rader genom <strong>SELECT
* FROM tabell</strong> så försöker SQL Server att så snabbt som möjligt ge oss alla
rader i tabellen <strong>tabell</strong>. Om det snabbaste sättet är att ge oss datat
I samma ordning som det lades in i tabellen så får vi det i den ordningen. Men om
det går snabbare att få raderna på något helt annat sätt så får vi raderna sorterade
på ett helt annat sätt. Eller snarare: Vi får alltid raderna osorterade.
</p>
        <p>
Det är ganska vanligt att man använder en IDENTITY-kolumn som primärnyckel i en tabell.
Då vet vi att datat på disk fysiskt är sorterat i den ordning det har lagts in I tabellen.
Detta eftersom en primärnyckel som default skapar ett klustrat index och ett klustrat
index lagras ihop med själva datat för tabellen. Alltså: Klustrat index sorterar själva
tabellen istället för att lagras vid sidan om tabellen i ett index-träd.
</p>
        <p>
I diskussionerna om sortering på data från SQL Server brukar klustrat index dyka upp
och någon brukar påstå att ett klustrat index garanterar att SQL Server ger oss data
I en viss ordning. Men det är också fullständigt fel. Ett klustrat index garanterar
ingenting annat än att datat är fysiskt sorterat. Men det har ju ingenting att göra
med hur SQL Server hämtar data från en tabell att göra. Om SQL Server hittar ett snabbare
sätt att ge oss rader i en tabell än att bara läsa från början till sut så kommer
ju SQL Server att göra det.
</p>
        <p>
Alltså: Om vi inte har något klustrat index så är datat i en tabell bara en hög med
tabellrader, helt utan inbördes ordning. Det är omöjligt att veta vilken ordning vi
kommer att få raderna om vi inte ber SQL Server att sortera raderna med en ORDER BY-klausul.
Om det finns ett klustrat index så är raderna prydligt ordnade på disk. Men det är
precis lika omöjligt att veta i vilken ordning vi kommer att få raderna om vi inte
använder en ORDER BY-klausul.
</p>
        <p>
Jag påmindes om det här ämnet i en <strong><a href="http://ask.sqlservercentral.com/questions/7532/how-to-get-results-in-ascending-order-when-creating-table">diskussion
på Ask SQL Server Central</a><em></em></strong> idag. Just den diskussionen handlade
om hur man kan sortera data vid en INSERT. Men det är egentligen samma sak – frågan
bygger på missuppfattningen att SQL Server sorterar data i den ordning raderna lagts
till.
</p>
        <p>
Det kan ibland finnas skäl att försöka lägga in rader i en viss ordning – nämligen
om det finns ett klustrat index som INTE är en IDENTITY-kolumn, eller en datetime-kolumn
med CURRENT_TIMESTAMP som default-värde. Ta till exempel ett personregister. Där skulle
jag vilja ha ett klustrat index över efternamn, förnamn. Om jag ska lägga in massor
av rader i tabellen så är jag lite intresserad av att försöka lägga in dem i “naturlig
ordning”, för att undvika fragmentering av data. Men det är ett helt annat ämne…
</p>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:a9423c3c-8ea0-417c-ae90-5a51c32c8fff" class="wlWriterEditableSmartContent">Technorati
Tags: <a href="http://technorati.com/tags/SQL+Server" rel="tag">SQL Server</a>,<a href="http://technorati.com/tags/Clustered+Index" rel="tag">Clustered
Index</a>,<a href="http://technorati.com/tags/Order+By" rel="tag">Order By</a></div>
      </body>
      <title>Hur &amp;auml;r raderna i en tabell sorterade?</title>
      <guid isPermaLink="false">http://www.underlandet.com/SqlServer/PermaLink,guid,dfddba20-57c1-4396-9d78-3f3c2dc3fbe7.aspx</guid>
      <link>http://www.underlandet.com/SqlServer/2010/06/24/HurAumlrRadernaIEnTabellSorterade.aspx</link>
      <pubDate>Thu, 24 Jun 2010 21:29:46 GMT</pubDate>
      <description>&lt;p&gt;
Flera gånger har jag sett och svarat på en fråga om sortering i SQL Server. Frågan
har formulerats på olika sätt, men I princip är det samma fråga som ställts:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;När jag gör SELECT mot min tabell får jag tillbaka raderna i “fel” ordning, jag
lade till rad A först, sen rad B, men SQL Server ger mig rad B före rad A.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Det är en vanlig missuppfattning att SQL Server ger oss rader i någon särskild ordning.
Men det kan vi inte på något sätt förvänta oss att SQL Server gör. SQL Server försöker
att ge oss det vi frågar om så snabbt som möjligt. Om vi ber om rader genom &lt;strong&gt;SELECT
* FROM tabell&lt;/strong&gt; så försöker SQL Server att så snabbt som möjligt ge oss alla
rader i tabellen &lt;strong&gt;tabell&lt;/strong&gt;. Om det snabbaste sättet är att ge oss datat
I samma ordning som det lades in i tabellen så får vi det i den ordningen. Men om
det går snabbare att få raderna på något helt annat sätt så får vi raderna sorterade
på ett helt annat sätt. Eller snarare: Vi får alltid raderna osorterade.
&lt;/p&gt;
&lt;p&gt;
Det är ganska vanligt att man använder en IDENTITY-kolumn som primärnyckel i en tabell.
Då vet vi att datat på disk fysiskt är sorterat i den ordning det har lagts in I tabellen.
Detta eftersom en primärnyckel som default skapar ett klustrat index och ett klustrat
index lagras ihop med själva datat för tabellen. Alltså: Klustrat index sorterar själva
tabellen istället för att lagras vid sidan om tabellen i ett index-träd.
&lt;/p&gt;
&lt;p&gt;
I diskussionerna om sortering på data från SQL Server brukar klustrat index dyka upp
och någon brukar påstå att ett klustrat index garanterar att SQL Server ger oss data
I en viss ordning. Men det är också fullständigt fel. Ett klustrat index garanterar
ingenting annat än att datat är fysiskt sorterat. Men det har ju ingenting att göra
med hur SQL Server hämtar data från en tabell att göra. Om SQL Server hittar ett snabbare
sätt att ge oss rader i en tabell än att bara läsa från början till sut så kommer
ju SQL Server att göra det.
&lt;/p&gt;
&lt;p&gt;
Alltså: Om vi inte har något klustrat index så är datat i en tabell bara en hög med
tabellrader, helt utan inbördes ordning. Det är omöjligt att veta vilken ordning vi
kommer att få raderna om vi inte ber SQL Server att sortera raderna med en ORDER BY-klausul.
Om det finns ett klustrat index så är raderna prydligt ordnade på disk. Men det är
precis lika omöjligt att veta i vilken ordning vi kommer att få raderna om vi inte
använder en ORDER BY-klausul.
&lt;/p&gt;
&lt;p&gt;
Jag påmindes om det här ämnet i en &lt;strong&gt;&lt;a href="http://ask.sqlservercentral.com/questions/7532/how-to-get-results-in-ascending-order-when-creating-table"&gt;diskussion
på Ask SQL Server Central&lt;/a&gt;&lt;em&gt;&lt;/em&gt;&lt;/strong&gt; idag. Just den diskussionen handlade
om hur man kan sortera data vid en INSERT. Men det är egentligen samma sak – frågan
bygger på missuppfattningen att SQL Server sorterar data i den ordning raderna lagts
till.
&lt;/p&gt;
&lt;p&gt;
Det kan ibland finnas skäl att försöka lägga in rader i en viss ordning – nämligen
om det finns ett klustrat index som INTE är en IDENTITY-kolumn, eller en datetime-kolumn
med CURRENT_TIMESTAMP som default-värde. Ta till exempel ett personregister. Där skulle
jag vilja ha ett klustrat index över efternamn, förnamn. Om jag ska lägga in massor
av rader i tabellen så är jag lite intresserad av att försöka lägga in dem i “naturlig
ordning”, för att undvika fragmentering av data. Men det är ett helt annat ämne…
&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:a9423c3c-8ea0-417c-ae90-5a51c32c8fff" class="wlWriterEditableSmartContent"&gt;Technorati
Tags: &lt;a href="http://technorati.com/tags/SQL+Server" rel="tag"&gt;SQL Server&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Clustered+Index" rel="tag"&gt;Clustered
Index&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Order+By" rel="tag"&gt;Order By&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.underlandet.com/SqlServer/CommentView,guid,dfddba20-57c1-4396-9d78-3f3c2dc3fbe7.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.underlandet.com/SqlServer/Trackback.aspx?guid=6dd41ae9-0c4e-441b-b486-798debfbc567</trackback:ping>
      <pingback:server>http://www.underlandet.com/SqlServer/pingback.aspx</pingback:server>
      <pingback:target>http://www.underlandet.com/SqlServer/PermaLink,guid,6dd41ae9-0c4e-441b-b486-798debfbc567.aspx</pingback:target>
      <dc:creator>Magnus Ahlkvist</dc:creator>
      <wfw:comment>http://www.underlandet.com/SqlServer/CommentView,guid,6dd41ae9-0c4e-441b-b486-798debfbc567.aspx</wfw:comment>
      <wfw:commentRss>http://www.underlandet.com/SqlServer/SyndicationService.asmx/GetEntryCommentsRss?guid=6dd41ae9-0c4e-441b-b486-798debfbc567</wfw:commentRss>
      <title>Microsoft.SqlServer.Management.Smo</title>
      <guid isPermaLink="false">http://www.underlandet.com/SqlServer/PermaLink,guid,6dd41ae9-0c4e-441b-b486-798debfbc567.aspx</guid>
      <link>http://www.underlandet.com/SqlServer/2010/02/18/MicrosoftSqlServerManagementSmo.aspx</link>
      <pubDate>Thu, 18 Feb 2010 12:58:09 GMT</pubDate>
      <description>&lt;p&gt;
Tänk dig att du får följande uppgift:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;“Vi behöver göra en &lt;u&gt;liten ändring&lt;/u&gt; i den här databasen, som har hundratals
tabeller och tusentals kolumner. Vi behöver ett bättre stöd för olika språk i applikationen
så alla kolumner måste ändras till &lt;strong&gt;&lt;a href="http://sv.wikipedia.org/wiki/Unicode"&gt;&lt;font color=#696969&gt;unicode&lt;/font&gt;&lt;/a&gt;&lt;/strong&gt; (dvs
varchar blir nvarchar, char blir nchar osv).”&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Med små datamängder kan man alltid använda SQL Server Management Studio och göra ändringarna
där. Men det är knappast ett alternativ när man har utvecklingsmiljöer, test-miljöer
och produktionsmiljöer med flera installerade instanser av liknande databaser osv.
När produktionssättningen av en sådan här ändring ska göras vill man inte behöva stänga
sina system två veckor för att manuellt ändra kolumner.
&lt;/p&gt;
&lt;p&gt;
En andra tanke skulle vara att just göra manuellt ändringar i en test-miljö och via
Script-knappen i Management Studio få det SQL-script som används för att göra förändringen
och spara ändringen till en text-fil. Men det skulle också vara extremt tidsödande.
Jag skrev ovan om produktionsmiljöer med &lt;strong&gt;liknande&lt;/strong&gt; databaser. Det
är ett problem med ändra-manuellt-i-Management-Studio-och-spara-undan-scriptet-metoden.
Är inte databaserna identiska måste samma procedur utföras för varje databas. 
&lt;/p&gt;
&lt;p&gt;
En tredje idé är ju förstås att scripta ut databaserna och göra ändringar med Sök/Ersätt
i valfri text-editor. Så tänkte jag först när jag ställdes inför uppgiften. Men ganska
snabbt slog jag idén ur hågen. I mitt fall har flera tabeller kolumnnamn som är datatyper
(“Text” till exempel). Det gjorde enkel Sök/Ersätt i text ganska svårt. Dessutom skulle
scriptet behöva omstruktureras en hel del för att saker och ting skulle göras i rätt
ordning (droppa constraints och index, ändra tabellerna, återskapa constraints och
index).
&lt;/p&gt;
&lt;p&gt;
Därför testade jag mig fram med Microsoft.SqlServer.Management.Smo i VB.NET och kom
fram till ganska lite kod som gör ett väldigt stort jobb. Jag älskar verkligen SMO!
På första försöket blev jag 95% färdig. Två-tre försök senare hade jag en lösning
som fungerade “universellt” för alla databaser.
&lt;/p&gt;
&lt;p&gt;
Jag har även använt SMO och reguljära uttryck för att ändra alla stored procedures
i en databas till att använda unicode-ekvivalenter, men den funktionen har så mycket
buggar än så länge, så jag väntar lite med den. De två största problem jag haft med
den är: Jag har inte ett korrekt reguljärt uttryck för att känna igen strängar. Det
blir fel när det finns fyra eller sex enkla citattecken invid varandra i koden. Jag
har inte heller fått till igenkänning av alla variabler och parametrar. Parametrarna
är OK, det är rätt enkelt att matcha &lt;em&gt;&lt;strong&gt;“@någonting&amp;lt;ett eller flera blanksteg&amp;gt;variabeltyp&lt;/strong&gt;&lt;/em&gt;”.
Men det är inte alls lika enkelt att hitta alla förekomster av varchar, text eller
char i löpande SQL-kod (exempelvis “&lt;strong&gt;&lt;em&gt;SELECT CAST(kolumnen AS varchar(10))
FROM tabellen” &lt;/em&gt;&lt;/strong&gt;osv. Men jag kanske finslipar lite, och återkommer när
den är “fulländad” (as if..). Tills vidare körde jag min funktion och blev sedan sittande
i nästan två dagar med rättning av koden. Men det sparade ändå massor av tid, jämfört
med att helt manuellt göra förändringarna.
&lt;/p&gt;
&lt;p&gt;
Här är VB.NET-koden för att ändra tabeller till unicode. En klass, med en publik och
en privat metod:
&lt;/p&gt;
&lt;p style="mso-layout-grid-align: none" class=MsoNormal&gt;
&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;Imports&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt; Microsoft.SqlServer.Management 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;Public&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt; &lt;span style="COLOR: blue"&gt;Class&lt;/span&gt; TableUnicodyfier&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Sex
globaler, två för att lagra fel och constraints, två som är namn på SMO-objekt&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'och
två som är självaste SMO-objekten. Inga publika variabler.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Private&lt;/span&gt; clConstraints &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Collection&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Private&lt;/span&gt; clErrors &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Collection&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Private&lt;/span&gt; s &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Smo.Server&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Private&lt;/span&gt; d &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Smo.Database&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;Private&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; sDBName &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Private&lt;/span&gt; sInstanceName &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Sub&lt;/span&gt; &lt;span style="COLOR: blue"&gt;New&lt;/span&gt;(&lt;span style="COLOR: blue"&gt;ByVal&lt;/span&gt; DBName &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&lt;/span&gt;, &lt;span style="COLOR: blue"&gt;ByVal&lt;/span&gt; InstanceName &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&lt;/span&gt;)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;sDBName
= DBName&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;sInstanceName
= InstanceName&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Sub&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: green; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;'Publik
metod som returnerar ett SQL-script för att ändra alla text-kolumner till Unicode.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;Public&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; &lt;span style="COLOR: blue"&gt;Function&lt;/span&gt; ReplaceAllTablesWithUnicode() &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&amp;nbsp; 
&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Variabler&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Dim&lt;/span&gt; sError &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&lt;/span&gt; = &lt;span style="COLOR: #a31515"&gt;""&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Dim&lt;/span&gt; j &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Integer&lt;/span&gt; =
0&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Dim&lt;/span&gt; i &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Integer&lt;/span&gt; =
0&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Dim&lt;/span&gt; str &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&lt;/span&gt; = &lt;span style="COLOR: #a31515"&gt;""&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Initiera
object&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;clConstraints
= &lt;span style="COLOR: blue"&gt;New&lt;/span&gt; Collection()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;clErrors
= &lt;span style="COLOR: blue"&gt;New&lt;/span&gt; Collection()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;s
= &lt;span style="COLOR: blue"&gt;New&lt;/span&gt; Smo.Server(sInstanceName)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;d
= s.Databases(sDBName) &lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2 face="Courier New"&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="mso-layout-grid-align: none" class=MsoNormal&gt;
&lt;font size=2 face="Courier New"&gt;&lt;/font&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Viktigt!!
Jag föredrar att kunna granska alla ändringar i text innan de genomförs (jag kanske
är feg?).&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Om
inte raden nedan finns med görs alla ändringar "på riktigt". Finns den med sparas
bara alla SQL-anrop&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'och
kan hämtas sedan.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;s.ConnectionContext.SqlExecutionModes
= Common.SqlExecutionModes.CaptureSql&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&amp;nbsp;&lt;/span&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2 face="Courier New"&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="mso-layout-grid-align: none" class=MsoNormal&gt;
&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Loopa
igenom alla tabeller och kör replaceTableWithUnicode&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;For&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; &lt;span style="COLOR: blue"&gt;Each&lt;/span&gt; t &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Smo.Table &lt;span style="COLOR: blue"&gt;In&lt;/span&gt; d.Tables&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;If&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Not&lt;/span&gt; t.IsSystemObject &lt;span style="COLOR: blue"&gt;Then&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;replaceTableWithUnicode(t.Name, &lt;span style="COLOR: blue"&gt;True&lt;/span&gt;)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;If&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;i
+= 1&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Application.DoEvents()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;Next&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2 face="Courier New"&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="mso-layout-grid-align: none" class=MsoNormal&gt;
&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Eftersom
replaceTableWithUnicode bara droppar Foreign Keys men inte återskapar dem så gör vi
det sist av allt.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Anledningen
är förstås att alla tabeller måste ändras innan vi kan återskapa FK:n igen. Annars
riskerar vi&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'att
försöka skapa en FK mellan en varchar-kolumn i tabell A och en nvarchar-kolumn i tabell
B.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Därför
loopar vi igenom clConstraints och kör Create på varje FK.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;For&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; &lt;span style="COLOR: blue"&gt;Each&lt;/span&gt; f2 &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Object&lt;/span&gt; &lt;span style="COLOR: blue"&gt;In&lt;/span&gt; clConstraints&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;f2.create()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Next&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2 face="Courier New"&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="mso-layout-grid-align: none" class=MsoNormal&gt;
&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Loopa
igenom all SQL-text som SMO sparat åt oss istället för att genomföra förändringarna
på riktigt.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: green; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;'Bygg
upp en resultat-sträng&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;For&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Each&lt;/span&gt; str2 &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&lt;/span&gt; &lt;span style="COLOR: blue"&gt;In&lt;/span&gt; s.ConnectionContext.CapturedSql.Text&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;str
&amp;amp;= str2 &amp;amp; vbCrLf &amp;amp; &lt;span style="COLOR: #a31515"&gt;"GO"&lt;/span&gt; &amp;amp; vbCrLf&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;Next&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2 face="Courier New"&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="mso-layout-grid-align: none" class=MsoNormal&gt;
&lt;font size=2 face="Courier New"&gt;&lt;/font&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Om
några fel uppstod under körningen så har de objekten lagrats i clErrors. Loopa igenom
den och&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'lägg
till även den SQL-koden sist i resultat-strängen.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;If&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; clErrors.Count
&amp;gt; 0 &lt;span style="COLOR: blue"&gt;Then&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;str
&amp;amp;= &lt;span style="COLOR: #a31515"&gt;"--Errors occured while saving scripts"&lt;/span&gt; &amp;amp;
vbCrLf&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;For&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Each&lt;/span&gt; o &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Object&lt;/span&gt; &lt;span style="COLOR: blue"&gt;In&lt;/span&gt; clErrors&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;For&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Each&lt;/span&gt; strScript &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&lt;/span&gt; &lt;span style="COLOR: blue"&gt;In&lt;/span&gt; o.script()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;str
&amp;amp;= strScript &amp;amp; vbCrLf&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Next&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Next&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;If&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: green; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;'str
innehåller nu:&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'-
Drop statements för alla Foreign Key constraints&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'-
Drop-statements för alla index, primärnycklar, defaults och triggers&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'-
Alter statements för alla tabeller&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'-
Create-statements för alla index, primärnycklar, defaults och&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;triggers&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: green; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;'-
Create-statements för alla Foreign Key constraints&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Return&lt;/span&gt; str&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Function &lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&gt; 
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2 face="Courier New"&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="mso-layout-grid-align: none" class=MsoNormal&gt;
&lt;font size=2 face="Courier New"&gt;&lt;/font&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Private&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Function&lt;/span&gt; replaceTableWithUnicode(&lt;span style="COLOR: blue"&gt;ByVal&lt;/span&gt; tableName &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&lt;/span&gt;, &lt;span style="COLOR: blue"&gt;ByVal&lt;/span&gt; commit &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Boolean&lt;/span&gt;) &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Dim&lt;/span&gt; cl &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;New&lt;/span&gt; Collection&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Dim&lt;/span&gt; bChange &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Boolean&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: fr" lang=FR&gt;Dim&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: fr" lang=FR&gt; t &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Smo.Table
= d.Tables(tableName)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: fr" lang=FR&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;Dim&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; c &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Smo.Column&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Dim&lt;/span&gt; str &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;String&lt;/span&gt; = &lt;span style="COLOR: #a31515"&gt;""&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: #a31515; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: #a31515; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;
&lt;br&gt;
&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: green; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;'Loopa
igenom alla kolumner. Ändra dem till respektive Unicode-ekvivalent&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;For&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; &lt;span style="COLOR: blue"&gt;Each&lt;/span&gt; c &lt;span style="COLOR: blue"&gt;In&lt;/span&gt; t.Columns&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;bChange
= &lt;span style="COLOR: blue"&gt;False&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Select&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Case&lt;/span&gt; c.DataType.Name&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Case&lt;/span&gt; &lt;span style="COLOR: #a31515"&gt;"varchar"&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;bChange
= &lt;span style="COLOR: blue"&gt;True&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;If&lt;/span&gt; c.DataType.MaximumLength
&amp;gt; 4000 &lt;span style="COLOR: blue"&gt;Then&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;c.DataType
= Smo.DataType.NVarCharMax&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Else&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;c.DataType
= Smo.DataType.NVarChar(c.DataType.MaximumLength)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;If&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Case&lt;/span&gt; &lt;span style="COLOR: #a31515"&gt;"char"&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;bChange
= &lt;span style="COLOR: blue"&gt;True&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;c.DataType
= Smo.DataType.NChar(c.DataType.MaximumLength)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Case&lt;/span&gt; &lt;span style="COLOR: #a31515"&gt;"text"&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;bChange
= &lt;span style="COLOR: blue"&gt;True&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;c.DataType
= Smo.DataType.NVarCharMax&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;End&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt; &lt;span style="COLOR: blue"&gt;Select&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Notera
att vi inte har gjort Alter på tabellen ännu. Än så länge har vi bara ändrat i kolumn-objekten.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Om
någon kolumn ska ändras så är det säkrast att återskapa alla default-constraints,
annars kommer&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'SQL
Server att gnälla. Vi loopar igenom dem, lägger till dem i cl och droppar dem sedan.
På så sätt&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'genererar
ett DROP-statement till vår SQL-kod, och vi kan göra Create senare när tabellen är
ändrad.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;If&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; bChange &lt;span style="COLOR: blue"&gt;Then&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;If&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Not&lt;/span&gt; c.DefaultConstraint &lt;span style="COLOR: blue"&gt;Is&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Nothing&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Then&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cl.Add(c.DefaultConstraint)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;c.DefaultConstraint.Drop()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;If&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;If&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Next&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Try&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: green; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;'Nu
ska vi hitta alla FK-constraints som refererar till den här tabellen.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'För
varje FK som refererar till den här tabellen - lägg till den i både funktionens interna&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'cl2
och i klassvariablen clConstraints&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Sist
- loopa igenom alla constraints i cl2 och droppa. Resultatet blir att alla FK kommer
att droppas&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'men
själva objekten kommer att finnas kvar i clConstraints, för att anropande funktion
ska kunna återskapa dem&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;For&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; &lt;span style="COLOR: blue"&gt;Each&lt;/span&gt; t2 &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Smo.Table &lt;span style="COLOR: blue"&gt;In&lt;/span&gt; d.Tables&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Dim&lt;/span&gt; cl2 &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;New&lt;/span&gt; Collection&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;For&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Each&lt;/span&gt; f2 &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Smo.ForeignKey &lt;span style="COLOR: blue"&gt;In&lt;/span&gt; t2.ForeignKeys&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;If&lt;/span&gt; f2.ReferencedTable.ToUpper()
= tableName.ToUpper() &lt;span style="COLOR: blue"&gt;Then&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cl2.Add(f2)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;clConstraints.Add(f2)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;If&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Next&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;For&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Each&lt;/span&gt; f2 &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Smo.ForeignKey &lt;span style="COLOR: blue"&gt;In&lt;/span&gt; cl2&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;f2.Drop()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Next&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Next&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Droppa
även alla FK som är skapade i aktuell tabell och som refererar andra tabeller&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;Do&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; &lt;span style="COLOR: blue"&gt;Until&lt;/span&gt; t.ForeignKeys.Count
= 0&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;clConstraints.Add(t.ForeignKeys(0))&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;t.ForeignKeys(0).Drop()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;Loop&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Droppa
alla index. Lägg först till indexet i den privata variabeln cl&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;Do&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; &lt;span style="COLOR: blue"&gt;Until&lt;/span&gt; t.Indexes.Count
= 0&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: green; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;'Om
inte den här raden är med funkar inte koden för Primärnycklar. Raden gör ingenting
mer än att&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'läsa
indextypen, men tydligen görs något i själva Index-objektet som initierar den korrekt
för primärnycklar.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;Dim&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; it &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Smo.IndexKeyType
= t.Indexes(0).IndexKeyType&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cl.Add(t.Indexes(0))&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;t.Indexes(0).Drop()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
&lt;PLACE w:st="on"&gt;
&lt;span style="COLOR: blue"&gt;Loop 
&lt;br&gt;
&lt;/span&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: green; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;'Och
slutligen samma sak med alla triggers i tabellen&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;Do&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; &lt;span style="COLOR: blue"&gt;Until&lt;/span&gt; t.Triggers.Count
= 0&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cl.Add(t.Triggers(0))&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;t.Triggers(0).Drop()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;Loop&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Sådärja,
då är alla beroende objekt droppade. Då gör vi Alter på tabellen för att ge genomslag&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'åt
våra förändringar av kolumn-datatyper&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;Try&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;t.Alter()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Catch&lt;/span&gt; ex &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Exception&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: green; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;'Och
det här kan ju gå fel om vi glömt något, så då sparar vi i sådant fall undan tabellen
i clErrors&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;MsgBox(&lt;span style="COLOR: #a31515"&gt;"Error
when altering table "&lt;/span&gt; &amp;amp; t.Name)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;clErrors.Add(t)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Try &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2 face="Courier New"&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p style="mso-layout-grid-align: none" class=MsoNormal&gt;
&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Nu
är tabellen ändrad, men den har varken index, primärnycklar defaults eller triggers.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Tur
att vi sparat undan de objekten i privata variabeln cl. &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: green; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;Loopa
och återskapa.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;For&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Each&lt;/span&gt; o &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Object&lt;/span&gt; &lt;span style="COLOR: blue"&gt;In&lt;/span&gt; cl&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Try&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;o.Create()&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Catch&lt;/span&gt; ex &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Exception&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: green; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;'Det
här är fult, men jag vill direkt få reda på när något går fel, och få se en Stacktrace.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'I
normala fall ska naturligtvis inte en sådan här klass försöka sig på att kommunicera
interaktivt.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;'Den
som orkar fixar självklart en ErrorMessages-collection som public property i klassen.&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes; mso-ansi-language: sv" lang=SV&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;MsgBox(&lt;span style="COLOR: #a31515"&gt;"Error
when creating object(s)"&lt;/span&gt; &amp;amp; vbCrLf &amp;amp; ex.ToString())&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;clErrors.Add(o)&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Try&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Next&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Catch&lt;/span&gt; ex &lt;span style="COLOR: blue"&gt;As&lt;/span&gt; Exception&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;MsgBox(ex.ToString())&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Try&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;Return&lt;/span&gt; str&amp;nbsp; 
&lt;br&gt;
&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;End&lt;/span&gt; &lt;span style="COLOR: blue"&gt;Function 
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;End&lt;/span&gt;&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt; &lt;span style="COLOR: blue"&gt;Class &lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="mso-layout-grid-align: none" class=MsoNormal&gt;
&lt;span style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;span style="COLOR: blue"&gt;&lt;font color=#003300 face=Verdana&gt;Andra &lt;/font&gt;&lt;a href="http://intressant.se/intressant"&gt;&lt;strong&gt;&lt;font color=#696969 face=Verdana&gt;intressanta&lt;/font&gt;&lt;/strong&gt;&lt;/a&gt;&lt;font color=#003300 face=Verdana&gt; blogginlägg
om: &lt;/font&gt;&lt;a href="http://bloggar.se/om/Unicode" rel=tag&gt;&lt;strong&gt;&lt;font color=#696969 face=Verdana&gt;Unicode&lt;/font&gt;&lt;/strong&gt;&lt;/a&gt;&lt;font color=#003300 face=Verdana&gt;, &lt;/font&gt;&lt;a href="http://bloggar.se/om/SQL+Server" rel=tag&gt;&lt;strong&gt;&lt;font color=#696969 face=Verdana&gt;SQL
Server&lt;/font&gt;&lt;/strong&gt;&lt;/a&gt;&lt;font color=#003300 face=Verdana&gt;, &lt;/font&gt;&lt;a href="http://bloggar.se/om/Microsoft" rel=tag&gt;&lt;strong&gt;&lt;font color=#696969 face=Verdana&gt;Microsoft&lt;/font&gt;&lt;/strong&gt;&lt;/a&gt;&lt;font color=#003300 face=Verdana&gt;, &lt;/font&gt;&lt;a href="http://bloggar.se/om/Microsoft.SqlServer.Management.Smo" rel=tag&gt;&lt;strong&gt;&lt;font color=#696969 face=Verdana&gt;Microsoft.SqlServer.Management.Smo&lt;/font&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;</description>
      <comments>http://www.underlandet.com/SqlServer/CommentView,guid,6dd41ae9-0c4e-441b-b486-798debfbc567.aspx</comments>
      <category>.NET</category>
      <category>DBA</category>
    </item>
    <item>
      <trackback:ping>http://www.underlandet.com/SqlServer/Trackback.aspx?guid=d20c0c03-f207-4aff-a46f-a14bb6d77d01</trackback:ping>
      <pingback:server>http://www.underlandet.com/SqlServer/pingback.aspx</pingback:server>
      <pingback:target>http://www.underlandet.com/SqlServer/PermaLink,guid,d20c0c03-f207-4aff-a46f-a14bb6d77d01.aspx</pingback:target>
      <dc:creator>Magnus Ahlkvist</dc:creator>
      <wfw:comment>http://www.underlandet.com/SqlServer/CommentView,guid,d20c0c03-f207-4aff-a46f-a14bb6d77d01.aspx</wfw:comment>
      <wfw:commentRss>http://www.underlandet.com/SqlServer/SyndicationService.asmx/GetEntryCommentsRss?guid=d20c0c03-f207-4aff-a46f-a14bb6d77d01</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I <a href="http://www.underlandet.com/SqlServer/2009/10/19/MissvisandeFelmeddelandeWITHDROPEXISTINGOchRensningIMSDB.aspx">mitt
förra blogginlägg</a> skrev jag bland annat om spDeleteBackupRestoreHistory, som är
en Stored Procedure som rensar backup- och restore-historik i MSDB. Den gick <strong>VERKLIGEN</strong> långsamt
i sitt ursprungsutförande. Därför började jag kolla indexeringen i MSDB och upptäckte
att den är minst sagt sparsam. Det kan säkert göras massor för att snabba upp både
det ena och det andra i MSDB. Men jag hade två specifika problem:
</p>
        <p>
1) Tabellen <strong>backupset</strong> har ett enda index – backupsetuuid. Men det
finns en Foreign Key-constraint som refererar kolumnen media_set_id till tabellen <strong>backupmediaset</strong>.
I SPn spDeleteBackupRestoreHistory görs en sökning i just den kolumnen, vilket innebär
en table-scan. Eftersom den sökningen görs väldigt många gånger innebär det väldigt
många tablescans och därmed väldigt dålig prestanda.
</p>
        <p>
2) I spDeleteBackupRestoreHistory läses kolumnerna <strong>backup_set_id</strong> och <strong>media_set_id</strong> i
tabellen <strong>backupset</strong>. Det finns ett index (primärnyckel, klustrad)
på <strong>backup_set_id</strong>, men inget index på <strong>media_set_id</strong>. 
</p>
        <p>
För att slå två flugor i en smäll skapade jag ett sammansatt index över kolumnerna <strong>media_set_id</strong> och <strong>backup_set_id</strong>.
Då fick jag dels sökbarhet på <strong>media_set_id</strong> vilket gör att table_scan
undviks, dels fick jag ett täckande index över de två kolumner i tabellen <strong>backupset</strong> som
spDeleteBackupRestoreHistory använder.
</p>
        <p>
Alltså:
</p>
        <blockquote>
          <p>
            <strong>
              <font color="#0000ff">CREATE  
<br />
  INDEX</font> [backupset_mediaset_id] 
<br /><font color="#0000ff">ON 
<br /></font>  [dbo].[backupset]([media_set_id], 
<br />
  [backup_set_id])</strong>
          </p>
        </blockquote>
        <p>
Jag testkörde genom att:
</p>
        <ul>
          <li>
Först göra <strong><font color="#0000ff">exec </font>spDeleteBackupRestoreHistory
100</strong> utan att mäta tiden. 
</li>
          <li>
Sedan gjorde jag <strong><font color="#0000ff">exec </font>spDeleteBackupRestoreHistory
90</strong> med tidsmätning innan jag skapat mitt nya index. Resultatet: 12 minuters
körning. 
</li>
          <li>
Sedan skapade jag indexet och gjorde <strong><font color="#0000ff">exec </font>spDeleteBackupRestoreHistory
90</strong>. Resultat: 5 sekunders körning.</li>
        </ul>
        <p>
Sensmoral: Ha alltid index på kolumner som refereras i främmande nycklar. Försök att
skapa täckande index.
</p>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:77d0a3c7-99d3-4fa9-81ac-5526481e6b7d" class="wlWriterEditableSmartContent">Technorati: <a href="http://technorati.com/tags/SQL+Server" rel="tag">SQL
Server</a>,<a href="http://technorati.com/tags/T%c3%a4ckande+index" rel="tag">Täckande
index</a>,<a href="http://technorati.com/tags/Optimering" rel="tag">Optimering</a></div>
        <br />
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:548266be-19c8-44a3-b028-39efba0cff34" class="wlWriterEditableSmartContent">Andra <a href="http://intressant.se/intressant">intressanta</a> blogginlägg
om: <a href="http://bloggar.se/om/SQL+Server" rel="tag">SQL Server</a>, <a href="http://bloggar.se/om/T%c3%a4ckande+index" rel="tag">Täckande
index</a>, <a href="http://bloggar.se/om/Optimering" rel="tag">Optimering</a></div>
      </body>
      <title>Tusenfalt snabbare spDeleteBackupRestoreHistory med ett index</title>
      <guid isPermaLink="false">http://www.underlandet.com/SqlServer/PermaLink,guid,d20c0c03-f207-4aff-a46f-a14bb6d77d01.aspx</guid>
      <link>http://www.underlandet.com/SqlServer/2009/10/19/TusenfaltSnabbareSpDeleteBackupRestoreHistoryMedEttIndex.aspx</link>
      <pubDate>Mon, 19 Oct 2009 09:13:27 GMT</pubDate>
      <description>&lt;p&gt;
I &lt;a href="http://www.underlandet.com/SqlServer/2009/10/19/MissvisandeFelmeddelandeWITHDROPEXISTINGOchRensningIMSDB.aspx"&gt;mitt
förra blogginlägg&lt;/a&gt; skrev jag bland annat om spDeleteBackupRestoreHistory, som är
en Stored Procedure som rensar backup- och restore-historik i MSDB. Den gick &lt;strong&gt;VERKLIGEN&lt;/strong&gt; långsamt
i sitt ursprungsutförande. Därför började jag kolla indexeringen i MSDB och upptäckte
att den är minst sagt sparsam. Det kan säkert göras massor för att snabba upp både
det ena och det andra i MSDB. Men jag hade två specifika problem:
&lt;/p&gt;
&lt;p&gt;
1) Tabellen &lt;strong&gt;backupset&lt;/strong&gt; har ett enda index – backupsetuuid. Men det
finns en Foreign Key-constraint som refererar kolumnen media_set_id till tabellen &lt;strong&gt;backupmediaset&lt;/strong&gt;.
I SPn spDeleteBackupRestoreHistory görs en sökning i just den kolumnen, vilket innebär
en table-scan. Eftersom den sökningen görs väldigt många gånger innebär det väldigt
många tablescans och därmed väldigt dålig prestanda.
&lt;/p&gt;
&lt;p&gt;
2) I spDeleteBackupRestoreHistory läses kolumnerna &lt;strong&gt;backup_set_id&lt;/strong&gt; och &lt;strong&gt;media_set_id&lt;/strong&gt; i
tabellen &lt;strong&gt;backupset&lt;/strong&gt;. Det finns ett index (primärnyckel, klustrad)
på &lt;strong&gt;backup_set_id&lt;/strong&gt;, men inget index på &lt;strong&gt;media_set_id&lt;/strong&gt;. 
&lt;/p&gt;
&lt;p&gt;
För att slå två flugor i en smäll skapade jag ett sammansatt index över kolumnerna &lt;strong&gt;media_set_id&lt;/strong&gt; och &lt;strong&gt;backup_set_id&lt;/strong&gt;.
Då fick jag dels sökbarhet på &lt;strong&gt;media_set_id&lt;/strong&gt; vilket gör att table_scan
undviks, dels fick jag ett täckande index över de två kolumner i tabellen &lt;strong&gt;backupset&lt;/strong&gt; som
spDeleteBackupRestoreHistory använder.
&lt;/p&gt;
&lt;p&gt;
Alltså:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;&lt;font color="#0000ff"&gt;CREATE&amp;#160; 
&lt;br /&gt;
&amp;#160; INDEX&lt;/font&gt; [backupset_mediaset_id] 
&lt;br /&gt;
&lt;font color="#0000ff"&gt;ON 
&lt;br /&gt;
&lt;/font&gt;&amp;#160; [dbo].[backupset]([media_set_id], 
&lt;br /&gt;
&amp;#160; [backup_set_id])&lt;/strong&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Jag testkörde genom att:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Först göra &lt;strong&gt;&lt;font color="#0000ff"&gt;exec &lt;/font&gt;spDeleteBackupRestoreHistory
100&lt;/strong&gt; utan att mäta tiden. 
&lt;/li&gt;
&lt;li&gt;
Sedan gjorde jag &lt;strong&gt;&lt;font color="#0000ff"&gt;exec &lt;/font&gt;spDeleteBackupRestoreHistory
90&lt;/strong&gt; med tidsmätning innan jag skapat mitt nya index. Resultatet: 12 minuters
körning. 
&lt;/li&gt;
&lt;li&gt;
Sedan skapade jag indexet och gjorde &lt;strong&gt;&lt;font color="#0000ff"&gt;exec &lt;/font&gt;spDeleteBackupRestoreHistory
90&lt;/strong&gt;. Resultat: 5 sekunders körning.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Sensmoral: Ha alltid index på kolumner som refereras i främmande nycklar. Försök att
skapa täckande index.
&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:77d0a3c7-99d3-4fa9-81ac-5526481e6b7d" class="wlWriterEditableSmartContent"&gt;Technorati: &lt;a href="http://technorati.com/tags/SQL+Server" rel="tag"&gt;SQL
Server&lt;/a&gt;,&lt;a href="http://technorati.com/tags/T%c3%a4ckande+index" rel="tag"&gt;T&amp;#228;ckande
index&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Optimering" rel="tag"&gt;Optimering&lt;/a&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:548266be-19c8-44a3-b028-39efba0cff34" class="wlWriterEditableSmartContent"&gt;Andra &lt;a href="http://intressant.se/intressant"&gt;intressanta&lt;/a&gt; blogginlägg
om: &lt;a href="http://bloggar.se/om/SQL+Server" rel="tag"&gt;SQL Server&lt;/a&gt;, &lt;a href="http://bloggar.se/om/T%c3%a4ckande+index" rel="tag"&gt;T&amp;#228;ckande
index&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Optimering" rel="tag"&gt;Optimering&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.underlandet.com/SqlServer/CommentView,guid,d20c0c03-f207-4aff-a46f-a14bb6d77d01.aspx</comments>
      <category>Optimering</category>
      <category>SQL Server 2000</category>
    </item>
    <item>
      <trackback:ping>http://www.underlandet.com/SqlServer/Trackback.aspx?guid=002df521-dd8c-4c6d-bb49-5e657efd5c22</trackback:ping>
      <pingback:server>http://www.underlandet.com/SqlServer/pingback.aspx</pingback:server>
      <pingback:target>http://www.underlandet.com/SqlServer/PermaLink,guid,002df521-dd8c-4c6d-bb49-5e657efd5c22.aspx</pingback:target>
      <dc:creator>Magnus Ahlkvist</dc:creator>
      <wfw:comment>http://www.underlandet.com/SqlServer/CommentView,guid,002df521-dd8c-4c6d-bb49-5e657efd5c22.aspx</wfw:comment>
      <wfw:commentRss>http://www.underlandet.com/SqlServer/SyndicationService.asmx/GetEntryCommentsRss?guid=002df521-dd8c-4c6d-bb49-5e657efd5c22</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Jag har upptäckt att MSDB i en server jag hanterar är ALLDELES för välfylld. Att droppa
en databas har tagit flera timmar om jag valt att radera backup-historik samtidigt.
Därför googlade jag och fann en användbar SP: <strong><a href="http://solihinho.wordpress.com/2008/07/19/cleanup-msdb/">spDeleteBackupRestoreHistory</a></strong> hos <a href="http://solihinho.wordpress.com/">DBA
and SysAdmin workd</a>. Det är en procedur som rensar backuphistorik ändre än X dagar.
Mycket användbar SP som redan hamnat som ett veckojobb på en testmaskin och som jag
körde över helgen på en produktionsmaskin, för att den skulle rensa bort all historik
som är äldre än två år (jag hade sex år gammal historik sparad).
</p>
        <p>
Det hade gått alldeles utmärkt om inte nedanstående “trevliga” lilla felmeddelande
uppenbarat sig i Query Analyzer strax efter att jag lämnat datorn att jobba över helgen:
</p>
        <p>
          <strong>[Microsoft][ODBC SQL Server Driver][DBNETLIB]ConnectionCheckForData (CheckforData()).Server:
Msg 11, Level 16, State 1, Line 0 
<br />
Generalnetwork error. Check your network documentation.Connection Broken.</strong>
        </p>
        <p>
Jobbigt tänkte jag, men det är säkert något tillfälligt – någon som i helgen ryckte
och drog i någon sladd. Så jag testade att köra igång den igen, och fick direkt samma
fel. Jag bytte databas och testade lite olika queries utan att få något felmeddelande.
Jag gick tillbaka till MSDB och körde igen, och fick samma fel. Andra queries gick
utmärkt att köra i MSDB, det var bara spDeleteBackupRestoreHistory som ballade ur.
</p>
        <p>
Jag loggade in direkt på servern och öppnade en anslutning mot Localhost och körde
spDeleteBackupRestoreHistory och fick åter samma fel. Ganska säker på att det verkligen
inte är ett nätverksproblem körde jag DBCC CHECKDB på databasen och upptäckte ett
fel på indexet <em>backupsetuuid</em> i tabellen <em>backupset</em>.
</p>
        <p>
Nu när jag visste vad felet var kunde jag åtgärda det genom att bygga om indexet.
Tabellen innehåller ungefär en miljon rader, och att bygga om indexet tog fem sekunder.
“Förarbetet” – det vill säga att hitta vad som faktiskt var fel – tog däremot ungefär
en timme. Nu är felet åtgärdat, och spDeleteBackupRestoreHistory är igång igen. Återstår
att söka efter orsaken till att ett index gått sönder från början.
</p>
        <blockquote>
          <p>
            <strong>
              <font color="#0000ff">CREATE 
<br /></font>
            </strong>
            <strong>
              <font color="#0000ff">  INDEX </font>[backupsetuuid] 
<br /><font color="#0000ff">ON </font>backupset ([backup_set_uuid]) 
<br /><font color="#0000ff">  WITH DROP_EXISTING</font></strong>
          </p>
        </blockquote>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e4334f3c-2ecb-48b4-aef0-9dadff7d67e6" class="wlWriterEditableSmartContent">Technorati: <a href="http://technorati.com/tags/WITH+DROP_EXISTING" rel="tag">WITH
DROP_EXISTING</a>,<a href="http://technorati.com/tags/SQL+Server" rel="tag">SQL Server</a>,<a href="http://technorati.com/tags/MSDB" rel="tag">MSDB</a>,<a href="http://technorati.com/tags/Backuphistorik" rel="tag">Backuphistorik</a>,<a href="http://technorati.com/tags/DBCC+CHECKDB" rel="tag">DBCC
CHECKDB</a>,<a href="http://technorati.com/tags/CheckforData()" rel="tag">CheckforData()</a></div>
        <br />
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e2f09316-f300-4b30-9396-219c40bb91a6" class="wlWriterEditableSmartContent">Andra <a href="http://intressant.se/intressant">intressanta</a> blogginlägg
om: <a href="http://bloggar.se/om/WITH+DROP_EXISTING" rel="tag">WITH DROP_EXISTING</a>, <a href="http://bloggar.se/om/SQL+Server" rel="tag">SQL
Server</a>, <a href="http://bloggar.se/om/MSDB" rel="tag">MSDB</a>, <a href="http://bloggar.se/om/Backuphistorik" rel="tag">Backuphistorik</a>, <a href="http://bloggar.se/om/DBCC+CHECKDB" rel="tag">DBCC
CHECKDB</a>, <a href="http://bloggar.se/om/CheckforData()" rel="tag">CheckforData()</a></div>
      </body>
      <title>Missvisande felmeddelande, WITH DROP_EXISTING och rensning i MSDB</title>
      <guid isPermaLink="false">http://www.underlandet.com/SqlServer/PermaLink,guid,002df521-dd8c-4c6d-bb49-5e657efd5c22.aspx</guid>
      <link>http://www.underlandet.com/SqlServer/2009/10/19/MissvisandeFelmeddelandeWITHDROPEXISTINGOchRensningIMSDB.aspx</link>
      <pubDate>Mon, 19 Oct 2009 07:11:14 GMT</pubDate>
      <description>&lt;p&gt;
Jag har upptäckt att MSDB i en server jag hanterar är ALLDELES för välfylld. Att droppa
en databas har tagit flera timmar om jag valt att radera backup-historik samtidigt.
Därför googlade jag och fann en användbar SP: &lt;strong&gt;&lt;a href="http://solihinho.wordpress.com/2008/07/19/cleanup-msdb/"&gt;spDeleteBackupRestoreHistory&lt;/a&gt;&lt;/strong&gt; hos &lt;a href="http://solihinho.wordpress.com/"&gt;DBA
and SysAdmin workd&lt;/a&gt;. Det är en procedur som rensar backuphistorik ändre än X dagar.
Mycket användbar SP som redan hamnat som ett veckojobb på en testmaskin och som jag
körde över helgen på en produktionsmaskin, för att den skulle rensa bort all historik
som är äldre än två år (jag hade sex år gammal historik sparad).
&lt;/p&gt;
&lt;p&gt;
Det hade gått alldeles utmärkt om inte nedanstående “trevliga” lilla felmeddelande
uppenbarat sig i Query Analyzer strax efter att jag lämnat datorn att jobba över helgen:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;[Microsoft][ODBC SQL Server Driver][DBNETLIB]ConnectionCheckForData (CheckforData()).Server:
Msg 11, Level 16, State 1, Line 0 
&lt;br /&gt;
Generalnetwork error. Check your network documentation.Connection Broken.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Jobbigt tänkte jag, men det är säkert något tillfälligt – någon som i helgen ryckte
och drog i någon sladd. Så jag testade att köra igång den igen, och fick direkt samma
fel. Jag bytte databas och testade lite olika queries utan att få något felmeddelande.
Jag gick tillbaka till MSDB och körde igen, och fick samma fel. Andra queries gick
utmärkt att köra i MSDB, det var bara spDeleteBackupRestoreHistory som ballade ur.
&lt;/p&gt;
&lt;p&gt;
Jag loggade in direkt på servern och öppnade en anslutning mot Localhost och körde
spDeleteBackupRestoreHistory och fick åter samma fel. Ganska säker på att det verkligen
inte är ett nätverksproblem körde jag DBCC CHECKDB på databasen och upptäckte ett
fel på indexet &lt;em&gt;backupsetuuid&lt;/em&gt; i tabellen &lt;em&gt;backupset&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;
Nu när jag visste vad felet var kunde jag åtgärda det genom att bygga om indexet.
Tabellen innehåller ungefär en miljon rader, och att bygga om indexet tog fem sekunder.
“Förarbetet” – det vill säga att hitta vad som faktiskt var fel – tog däremot ungefär
en timme. Nu är felet åtgärdat, och spDeleteBackupRestoreHistory är igång igen. Återstår
att söka efter orsaken till att ett index gått sönder från början.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;&lt;font color="#0000ff"&gt;CREATE 
&lt;br /&gt;
&lt;/font&gt;&lt;/strong&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;&amp;#160; INDEX &lt;/font&gt;[backupsetuuid] 
&lt;br /&gt;
&lt;font color="#0000ff"&gt;ON &lt;/font&gt;backupset ([backup_set_uuid]) 
&lt;br /&gt;
&lt;font color="#0000ff"&gt;&amp;#160; WITH DROP_EXISTING&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e4334f3c-2ecb-48b4-aef0-9dadff7d67e6" class="wlWriterEditableSmartContent"&gt;Technorati: &lt;a href="http://technorati.com/tags/WITH+DROP_EXISTING" rel="tag"&gt;WITH
DROP_EXISTING&lt;/a&gt;,&lt;a href="http://technorati.com/tags/SQL+Server" rel="tag"&gt;SQL Server&lt;/a&gt;,&lt;a href="http://technorati.com/tags/MSDB" rel="tag"&gt;MSDB&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Backuphistorik" rel="tag"&gt;Backuphistorik&lt;/a&gt;,&lt;a href="http://technorati.com/tags/DBCC+CHECKDB" rel="tag"&gt;DBCC
CHECKDB&lt;/a&gt;,&lt;a href="http://technorati.com/tags/CheckforData()" rel="tag"&gt;CheckforData()&lt;/a&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e2f09316-f300-4b30-9396-219c40bb91a6" class="wlWriterEditableSmartContent"&gt;Andra &lt;a href="http://intressant.se/intressant"&gt;intressanta&lt;/a&gt; blogginlägg
om: &lt;a href="http://bloggar.se/om/WITH+DROP_EXISTING" rel="tag"&gt;WITH DROP_EXISTING&lt;/a&gt;, &lt;a href="http://bloggar.se/om/SQL+Server" rel="tag"&gt;SQL
Server&lt;/a&gt;, &lt;a href="http://bloggar.se/om/MSDB" rel="tag"&gt;MSDB&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Backuphistorik" rel="tag"&gt;Backuphistorik&lt;/a&gt;, &lt;a href="http://bloggar.se/om/DBCC+CHECKDB" rel="tag"&gt;DBCC
CHECKDB&lt;/a&gt;, &lt;a href="http://bloggar.se/om/CheckforData()" rel="tag"&gt;CheckforData()&lt;/a&gt;
&lt;/div&gt;</description>
      <comments>http://www.underlandet.com/SqlServer/CommentView,guid,002df521-dd8c-4c6d-bb49-5e657efd5c22.aspx</comments>
      <category>DBA</category>
      <category>SQL Server 2000</category>
    </item>
    <item>
      <trackback:ping>http://www.underlandet.com/SqlServer/Trackback.aspx?guid=8ccf2ecd-86dd-4f76-9844-48c3ecf34c56</trackback:ping>
      <pingback:server>http://www.underlandet.com/SqlServer/pingback.aspx</pingback:server>
      <pingback:target>http://www.underlandet.com/SqlServer/PermaLink,guid,8ccf2ecd-86dd-4f76-9844-48c3ecf34c56.aspx</pingback:target>
      <dc:creator>Magnus Ahlkvist</dc:creator>
      <wfw:comment>http://www.underlandet.com/SqlServer/CommentView,guid,8ccf2ecd-86dd-4f76-9844-48c3ecf34c56.aspx</wfw:comment>
      <wfw:commentRss>http://www.underlandet.com/SqlServer/SyndicationService.asmx/GetEntryCommentsRss?guid=8ccf2ecd-86dd-4f76-9844-48c3ecf34c56</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Det har varit tyst härifrån ett tag. Det beror på att min fritid ägnas i större utsträckning
till att umgås med min bebis och min sambo (kloka val) och att jag begränsar min fritid
genom att arbeta mycket (inget val..). Snart har jag semester följt av föräldraledighet.
10 veckor tillsammans med sambon, följt av ett halvår med 80% föräldraledighet. Skönt!
</p>
        <p>
Men lite bloggande blir det nog under den här tiden. Jag håller på att installera
SQL Server 2008 och Visual Studio Express 2008, och återkommer med lite rapporter
om både SQL Server 2008 och om interaktionen mellan VS2008 Express och SQL Server.
</p>
        <p>
Jag har ett projekt i huvudet, som i korthet går ut på att skriva om <a href="http://www.bloggvanstern.se/">Bloggvänstern</a> så
att den BARA körs under SQL Server. Det är vansinnigt, men kunde vara kul att prova
på. Självklart blir det CLR för en stor del av slanten. Det blir inte Bloggvänstern
som sådant i första hand som ska köras i SQL Server, utan det blir en mer generell
Bloggportal-applikation. Om det här projektet verkligen blir av beror till stor del
på tillgång till tid. Jag återkommer löpande, och kommer också att - när/om det blir
klart - skriva fullständig dokumentation för sajten, och avslöja eventuella "hemligheter".
</p>
        <p>
          <a href="http://intressant.se/intressant">Intressant?</a>
          <br />
Andra bloggar om <a href="http://bloggar.se/om/SQL+Server">SQL Server</a>, <a href="http://bloggar.se/om/Optimering">Optimering</a>, <a href="http://bloggar.se/om/SQL+Server+2008">SQL
Server 2008</a>, <a href="http://bloggar.se/om/Metabloggande">Metabloggande</a></p>
      </body>
      <title>2008</title>
      <guid isPermaLink="false">http://www.underlandet.com/SqlServer/PermaLink,guid,8ccf2ecd-86dd-4f76-9844-48c3ecf34c56.aspx</guid>
      <link>http://www.underlandet.com/SqlServer/2008/06/15/2008.aspx</link>
      <pubDate>Sun, 15 Jun 2008 21:16:24 GMT</pubDate>
      <description>&lt;p&gt;
Det har varit tyst härifrån ett tag. Det beror på att min fritid ägnas i större utsträckning
till att umgås med min bebis och min sambo (kloka val) och att jag begränsar min fritid
genom att arbeta mycket (inget val..). Snart har jag semester följt av föräldraledighet.
10 veckor tillsammans med sambon, följt av ett halvår med 80% föräldraledighet. Skönt!
&lt;/p&gt;
&lt;p&gt;
Men lite bloggande blir det nog under den här tiden. Jag håller på att installera
SQL Server 2008 och Visual Studio Express 2008, och återkommer med lite rapporter
om både SQL Server 2008 och om interaktionen mellan VS2008 Express och SQL Server.
&lt;/p&gt;
&lt;p&gt;
Jag har ett projekt i huvudet, som i korthet går ut på att skriva om &lt;a href="http://www.bloggvanstern.se/"&gt;Bloggvänstern&lt;/a&gt; så
att den BARA körs under SQL Server. Det är vansinnigt, men kunde vara kul att prova
på. Självklart blir det CLR för en stor del av slanten. Det blir inte Bloggvänstern
som sådant i första hand som ska köras i SQL Server, utan det blir en mer generell
Bloggportal-applikation. Om det här projektet verkligen blir av beror till stor del
på tillgång till tid. Jag återkommer löpande, och kommer också att - när/om det blir
klart - skriva fullständig dokumentation för sajten, och avslöja eventuella "hemligheter".
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://intressant.se/intressant"&gt;Intressant?&lt;/a&gt;
&lt;br&gt;
Andra bloggar om &lt;a href="http://bloggar.se/om/SQL+Server"&gt;SQL Server&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Optimering"&gt;Optimering&lt;/a&gt;, &lt;a href="http://bloggar.se/om/SQL+Server+2008"&gt;SQL
Server 2008&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Metabloggande"&gt;Metabloggande&lt;/a&gt;
&lt;/p&gt;</description>
      <comments>http://www.underlandet.com/SqlServer/CommentView,guid,8ccf2ecd-86dd-4f76-9844-48c3ecf34c56.aspx</comments>
      <category>Bloggen</category>
      <category>SQL Server 2008</category>
    </item>
    <item>
      <trackback:ping>http://www.underlandet.com/SqlServer/Trackback.aspx?guid=2604e25a-ce62-4708-bb34-b46ba2b5db29</trackback:ping>
      <pingback:server>http://www.underlandet.com/SqlServer/pingback.aspx</pingback:server>
      <pingback:target>http://www.underlandet.com/SqlServer/PermaLink,guid,2604e25a-ce62-4708-bb34-b46ba2b5db29.aspx</pingback:target>
      <dc:creator>Magnus Ahlkvist</dc:creator>
      <wfw:comment>http://www.underlandet.com/SqlServer/CommentView,guid,2604e25a-ce62-4708-bb34-b46ba2b5db29.aspx</wfw:comment>
      <wfw:commentRss>http://www.underlandet.com/SqlServer/SyndicationService.asmx/GetEntryCommentsRss?guid=2604e25a-ce62-4708-bb34-b46ba2b5db29</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Nyligen stötte jag på en fråga som lyder:
</p>
        <blockquote>
          <p>
            <em>Hur skriver jag en stored procedure för att göra en insert bara om det inte redan
finns en rad med de värden jag försöker göra insert med.</em>
          </p>
        </blockquote>
        <p>
Mitt svar är:
</p>
        <blockquote>
          <p>
            <em>Använd <strong>IF NOT EXISTS(SELECT * FROM tabellen where kolumn1 = @kolumn1 AND
kolumn2 = @kolumn2 [..] AND kolumnN = @kolumnN</strong></em>
          </p>
        </blockquote>
        <p>
Den som ställde frågan stötte på syntaktiska problem, och återkom med beskedet:
</p>
        <blockquote>
          <p>
            <em>Jag har löst det. Jag skapade ett icke-klustrat unikt index med alternativet WITH
IGNORE_DUP_KEY</em>
          </p>
        </blockquote>
        <p>
Såhär alltså:
</p>
        <blockquote>
          <p>
            <strong>CREATE UNIQUE NONCLUSTERED INDEX UQI_tabellen_all ON tabellen(kolumn1, kolumn2,
[..], kolumnN) WITH IGNORE_DUP_KEY</strong>
          </p>
        </blockquote>
        <p>
Fiffigt. Då behöver man inte programmera sin kontroll. Man kan bara göra en insert,
och om en identisk rad redan finns så händer ingenting. Eller nästan ingenting iallafall.
Sanningen är att SQL Server kastar ifrån sig en varning: "Duplicate key was ignored".
Men det är ingenting jag i de flesta fall märker i min ADO.NET-kod. Där tror jag att
allt gått som det ska, och kör vidare till nästa rad.
</p>
        <p>
Frågan är om det verkligen är vad jag vill. Eller rättare sagt. Det här är INTE vad
jag vill. Jag vill verkligen inte att SQL Server ska låtsas som att den har gjort
en INSERT när den inte har gjort det. Försöker jag göra insert i en tabell där det
finns en unique-constraint så vill jag veta att jag bryter mot databas-regler. Jag
vill ha ett stort fett ERROR kastat när jag försöker bryta mot en unique-constraint.
</p>
        <p>
Ett STORT problem med lösningen är också att den som frågade hade gjort ett ICKEKLUSTRAT
index istället för ett KLUSTRAT. Det innebär att allt data dubbellagras, dels i tabellen
själv, dels i indexträd för tabellen. Ska man använda sig av heltäckande index så
ska de vara klustrade!
</p>
        <p>
Jag vill alltså göra kontrollen med EXISTS-funktionen som jag beskriver ovan. Till
min STORA glädje upptäcker jag också att det är mycket effektivare att göra så. Exakt
varför vet jag inte, men troligen är det så att det snor en del resurser från SQL
Server att konstatera att ett brott mot en constraint håller på att begås, och därför
ge ifrån sig en varning och ignorera den fysiska inserten, istället för att "bara"
göra en EXISTS-kontroll (som ju SQL Server ändå måste göra för att upprätthålla UNIQUE-constrainten).
</p>
        <p>
Jag testade genom att först skapa en tabell:
</p>
        <blockquote>
          <p>
            <strong>create table t (id int identity(1,1) primary key nonclustered, c1 varchar(10),
c2 varchar(10), c3 varchar(10))</strong>
          </p>
        </blockquote>
        <p>
Sedan skapade jag ett klustrat unique-index med WITH IGNORE_DUP_KEY:
</p>
        <blockquote>
          <p>
            <strong>create unique clustered index uqi_t_all ON t(c1,c2,c3) WITH IGNORE_DUP_KEY<br />
go</strong>
          </p>
        </blockquote>
        <p>
Slutligen ett script som loopar 100000 gånger för att göra en INSERT: 
</p>
        <blockquote>
          <p>
            <strong>declare @c1 varchar(10), @c2 varchar(10), @c3 varchar(10)<br />
set @c1='1'<br />
set @c2='2'<br />
set @c3='3'<br />
declare @i int<br />
set @i=0<br />
while @i&lt;100000<br />
begin<br />
insert into t(c1,c2,c3) values(@c1,@c2,@c3)<br />
set @i=@i+1<br />
end</strong>
          </p>
        </blockquote>
        <p>
          <u>Scriptet körs på 12 sekunder</u>
        </p>
        <p>
Jag testar igen, denna gång med ett unique index UTAN <strong>WITH IGNORE_DUP_KEY</strong></p>
        <blockquote>
          <p>
            <strong>drop index t.uqi_t_all<br />
go<br />
create unique clustered index uqi_t_all ON t(c1,c2,c3)<br />
go</strong>
          </p>
        </blockquote>
        <p>
Jag kör sedan mitt insert-script igen, den här gången med en <strong>EXISTS</strong>-kontroll: 
</p>
        <blockquote>
          <p>
            <strong>declare @c1 varchar(10), @c2 varchar(10), @c3 varchar(10)<br />
set @c1='1'<br />
set @c2='2'<br />
set @c3='3'<br />
declare @i int<br />
set @i=0<br />
while @i&lt;100000<br />
begin<br />
IF NOT EXISTS(SELECT * FROM t where c1=@c1 AND c2=@c2 AND c3=@c3)<br />
insert into t(c1,c2,c3) values(@c1,@c2,@c3)<br />
set @i=@i+1<br />
end</strong>
          </p>
        </blockquote>
        <p>
          <u>Scriptet körs på 1-2 sekunder</u>
        </p>
        <p>
6-12 gånger snabbare alltså att göra kontroll i T-SQL istället för att låta SQL Server
ignorera en insert genom IGNORE_DUP_KEY. Dessutom betydligt tydligare - alla kan se
i SQL-koden att ingen insert kommer att göras om det skulle innebära skapande av dubletter.
Med IGNORE_DUP_KEY är det betydligt mer otydligt. 
</p>
        <p>
Jag är nästan lite småsur över att IGNORE_DUP_KEY överhuvudtaget finns som ett alternativ
för unique index. Varför gör man så? Det skapar risk för missförstånd och förvirring,
och det är långsammare än att göra kontrollen i Transact-SQL. 
</p>
        <p>
För mer information om klustrade och icke-klustrade index: <a href="http://www.underlandet.com/SqlServer/2008/04/18/VaddaringKlusterindex.aspx">Vaddå
klusterindex?</a></p>
        <a href="http://intressant.se/intressant">Intressant?</a>
        <br />
Andra bloggar om <a href="http://bloggar.se/om/SQL+Server">SQL Server</a>, <a href="http://bloggar.se/om/Index">Index</a>, <a href="http://bloggar.se/om/Optimering">Optimering</a>, <a href="http://bloggar.se/om/Transact-SQL">Transact-SQL</a></body>
      <title>Varf&amp;ouml;r jag inte skulle anv&amp;auml;nda unika index med ignorerade dubletter</title>
      <guid isPermaLink="false">http://www.underlandet.com/SqlServer/PermaLink,guid,2604e25a-ce62-4708-bb34-b46ba2b5db29.aspx</guid>
      <link>http://www.underlandet.com/SqlServer/2008/05/16/VarfoumlrJagInteSkulleAnvaumlndaUnikaIndexMedIgnoreradeDubletter.aspx</link>
      <pubDate>Fri, 16 May 2008 13:55:42 GMT</pubDate>
      <description>&lt;p&gt;
Nyligen stötte jag på en fråga som lyder:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;Hur skriver jag en stored procedure för att göra en insert bara om det inte redan
finns en rad med de värden jag försöker göra insert med.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Mitt svar är:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;Använd &lt;strong&gt;IF NOT EXISTS(SELECT * FROM tabellen where kolumn1 = @kolumn1 AND
kolumn2 = @kolumn2 [..] AND kolumnN = @kolumnN&lt;/strong&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Den som ställde frågan stötte på syntaktiska problem, och återkom med beskedet:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;Jag har löst det. Jag skapade ett icke-klustrat unikt index med alternativet WITH
IGNORE_DUP_KEY&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Såhär alltså:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;CREATE UNIQUE NONCLUSTERED INDEX UQI_tabellen_all ON tabellen(kolumn1, kolumn2,
[..], kolumnN) WITH IGNORE_DUP_KEY&lt;/strong&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Fiffigt. Då behöver man inte programmera sin kontroll. Man kan bara göra en insert,
och om en identisk rad redan finns så händer ingenting. Eller nästan ingenting iallafall.
Sanningen är att SQL Server kastar ifrån sig en varning: "Duplicate key was ignored".
Men det är ingenting jag i de flesta fall märker i min ADO.NET-kod. Där tror jag att
allt gått som det ska, och kör vidare till nästa rad.
&lt;/p&gt;
&lt;p&gt;
Frågan är om det verkligen är vad jag vill. Eller rättare sagt. Det här är INTE vad
jag vill. Jag vill verkligen inte att SQL Server ska låtsas som att den har gjort
en INSERT när den inte har gjort det. Försöker jag göra insert i en tabell där det
finns en unique-constraint så vill jag veta att jag bryter mot databas-regler. Jag
vill ha ett stort fett ERROR kastat när jag försöker bryta mot en unique-constraint.
&lt;/p&gt;
&lt;p&gt;
Ett STORT problem med lösningen är också att den som frågade hade gjort ett ICKEKLUSTRAT
index istället för ett KLUSTRAT. Det innebär att allt data dubbellagras, dels i tabellen
själv, dels i indexträd för tabellen. Ska man använda sig av heltäckande index så
ska de vara klustrade!
&lt;/p&gt;
&lt;p&gt;
Jag vill alltså göra kontrollen med EXISTS-funktionen som jag beskriver ovan. Till
min STORA glädje upptäcker jag också att det är mycket effektivare att göra så. Exakt
varför vet jag inte, men troligen är det så att det snor en del resurser från SQL
Server att konstatera att ett brott mot en constraint håller på att begås, och därför
ge ifrån sig en varning och ignorera den fysiska inserten, istället för att "bara"
göra en EXISTS-kontroll (som ju SQL Server ändå måste göra för att upprätthålla UNIQUE-constrainten).
&lt;/p&gt;
&lt;p&gt;
Jag testade genom att först skapa en tabell:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;create table t (id int identity(1,1) primary key nonclustered, c1 varchar(10),
c2 varchar(10), c3 varchar(10))&lt;/strong&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Sedan skapade jag ett klustrat unique-index med WITH IGNORE_DUP_KEY:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;create unique clustered index uqi_t_all ON t(c1,c2,c3) WITH IGNORE_DUP_KEY&lt;br&gt;
go&lt;/strong&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Slutligen ett script som loopar 100000 gånger för att göra en INSERT: &lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;declare @c1 varchar(10), @c2 varchar(10), @c3 varchar(10)&lt;br&gt;
set @c1='1'&lt;br&gt;
set @c2='2'&lt;br&gt;
set @c3='3'&lt;br&gt;
declare @i int&lt;br&gt;
set @i=0&lt;br&gt;
while @i&amp;lt;100000&lt;br&gt;
begin&lt;br&gt;
insert into t(c1,c2,c3) values(@c1,@c2,@c3)&lt;br&gt;
set @i=@i+1&lt;br&gt;
end&lt;/strong&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;u&gt;Scriptet körs på 12 sekunder&lt;/u&gt; 
&lt;p&gt;
Jag testar igen, denna gång med ett unique index UTAN &lt;strong&gt;WITH IGNORE_DUP_KEY&lt;/strong&gt; &lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;drop index t.uqi_t_all&lt;br&gt;
go&lt;br&gt;
create unique clustered index uqi_t_all ON t(c1,c2,c3)&lt;br&gt;
go&lt;/strong&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Jag kör sedan mitt insert-script igen, den här gången med en &lt;strong&gt;EXISTS&lt;/strong&gt;-kontroll: &lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;declare @c1 varchar(10), @c2 varchar(10), @c3 varchar(10)&lt;br&gt;
set @c1='1'&lt;br&gt;
set @c2='2'&lt;br&gt;
set @c3='3'&lt;br&gt;
declare @i int&lt;br&gt;
set @i=0&lt;br&gt;
while @i&amp;lt;100000&lt;br&gt;
begin&lt;br&gt;
IF NOT EXISTS(SELECT * FROM t where c1=@c1 AND c2=@c2 AND c3=@c3)&lt;br&gt;
insert into t(c1,c2,c3) values(@c1,@c2,@c3)&lt;br&gt;
set @i=@i+1&lt;br&gt;
end&lt;/strong&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
&lt;u&gt;Scriptet körs på 1-2 sekunder&lt;/u&gt; 
&lt;p&gt;
6-12 gånger snabbare alltså att göra kontroll i T-SQL istället för att låta SQL Server
ignorera en insert genom IGNORE_DUP_KEY. Dessutom betydligt tydligare - alla kan se
i SQL-koden att ingen insert kommer att göras om det skulle innebära skapande av dubletter.
Med IGNORE_DUP_KEY är det betydligt mer otydligt. 
&lt;p&gt;
Jag är nästan lite småsur över att IGNORE_DUP_KEY överhuvudtaget finns som ett alternativ
för unique index. Varför gör man så? Det skapar risk för missförstånd och förvirring,
och det är långsammare än att göra kontrollen i Transact-SQL. 
&lt;p&gt;
För mer information om klustrade och icke-klustrade index: &lt;a href="http://www.underlandet.com/SqlServer/2008/04/18/VaddaringKlusterindex.aspx"&gt;Vaddå
klusterindex?&lt;/a&gt;
&lt;/p&gt;
&lt;a href="http://intressant.se/intressant"&gt;Intressant?&lt;/a&gt;
&lt;br&gt;
Andra bloggar om &lt;a href="http://bloggar.se/om/SQL+Server"&gt;SQL Server&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Index"&gt;Index&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Optimering"&gt;Optimering&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Transact-SQL"&gt;Transact-SQL&lt;/a&gt;</description>
      <comments>http://www.underlandet.com/SqlServer/CommentView,guid,2604e25a-ce62-4708-bb34-b46ba2b5db29.aspx</comments>
      <category>Design</category>
      <category>Optimering</category>
    </item>
    <item>
      <trackback:ping>http://www.underlandet.com/SqlServer/Trackback.aspx?guid=27c7bc11-eb85-4612-af45-79e2743b4e8d</trackback:ping>
      <pingback:server>http://www.underlandet.com/SqlServer/pingback.aspx</pingback:server>
      <pingback:target>http://www.underlandet.com/SqlServer/PermaLink,guid,27c7bc11-eb85-4612-af45-79e2743b4e8d.aspx</pingback:target>
      <dc:creator>Magnus Ahlkvist</dc:creator>
      <wfw:comment>http://www.underlandet.com/SqlServer/CommentView,guid,27c7bc11-eb85-4612-af45-79e2743b4e8d.aspx</wfw:comment>
      <wfw:commentRss>http://www.underlandet.com/SqlServer/SyndicationService.asmx/GetEntryCommentsRss?guid=27c7bc11-eb85-4612-af45-79e2743b4e8d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Via <a href="http://sqlblog.com/blogs/adam_machanic/archive/2008/04/22/sql-server-query-processing-puzzle-like-vs.aspx">en
bloggpost</a> från <a href="http://sqlblog.com/blogs/adam_machanic/">Adam Machanic</a> har
jag deltagit i en tävling om ett exemplar av <a href="http://www.amazon.com/dp/159059729X">Expert
SQL Server 2005 Development</a>. Frågan från Adam är:
</p>
        <p>
Givet att du har två tabeller, som skapats med scriptet nedan:
</p>
        <blockquote>
          <pre>USE TempDB<br />
GO<br /><br />
CREATE TABLE b1 (blat1 CHAR(5) NOT NULL)<br />
CREATE TABLE b2 (blat2 VARCHAR(200) NOT NULL)<br />
GO<br /><br />
INSERT b1<br />
SELECT LEFT(AddressLine1, 5) AS blat1<br />
FROM AdventureWorks.Person.Address<br /><br />
INSERT b2<br />
SELECT AddressLine1 AS blat2<br />
FROM AdventureWorks.Person.Address<br />
GO</pre>
        </blockquote>
        <p>
Hur kan man skriva om nedanstående fråga så att den blir snabbare (den tar ungefär
sex minuter på min PC):
</p>
        <blockquote>
          <pre>SELECT *<br />
FROM b1<br />
JOIN b2 ON<br />
b2.blat2 LIKE b1.blat1 + '%'</pre>
        </blockquote>
        <p>
Inga objekt-ändringar är tillåtna, dvs ingen indexering av tabellerna får göras.
</p>
        <p>
Lösningen är att göra exakta jämförelser istället för ungefärliga. Dvs att använda
"="-operatorn istället för "LIKE"-operatorn. Varför? Jo, därför att "LIKE"-operatorn
gör att vi måste använda oss av en "NESTED LOOP" för att jämföra raderna. Dvs SQL
Servers Query Processor (QP) måste titta på varje rad i den yttre tabellen i JOIN-operationen,
och för varje rad i den yttre tabellen måste QP titta på varje rad i den inre tabellen
för att jämföra data. Både b1 och b2 innehåller 19614 rader. Det är inga extrema datamängder,
långt därifrån. För att köra ovanstående fråga måste QP titta på 19614 i b1, och för
varje av dessa rader måste 19614 rader i b2 undersökas. Dvs 384 708 996 rader måste
undersökas.
</p>
        <p>
Lyckas vi istället använda en "="-operator kan QP använda en "MERGE" eller "HASH MATCH",
vilket väsentligen reducerar antalet rader att titta på.
</p>
        <p>
Min omskrivna fråga blir:
</p>
        <blockquote>
          <p>
SELECT *<br />
FROM b1<br />
JOIN b2 ON<br />
LEFT(b2.blat2,5) = b1.blat1
</p>
        </blockquote>
        <p>
Det funkar därför att vi vet att b1.blat2 innehåller de första fem tecknen från b2.blat2.
Tack vare den vetskapen kan frågan skrivas om, och köras på två sekunder. QP utför
en "HASH MATCH" och antalet rader som måste undersökas för att utföra JOIN-operationen
reduceras väsentligt.
</p>
        <p>
Nedan ser du bilder av de estimerade planerna för de båda frågorna, och kan själv
se skillnaden i estimerat antal rader för "NESTED LOOP" jämfört med "HASH MATCH" (Jämför
"Estimated Number of Rows")
</p>
        <p>
          <a href="http://www.underlandet.com/SqlServer/content/binary/WindowsLiveWriter/Attjmfraexaktochungefrligt_E6C5/image_2.png">
            <img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; WIDTH: 557px; BORDER-BOTTOM: 0px; HEIGHT: 224px" height="274" alt="image" src="http://www.underlandet.com/SqlServer/content/binary/WindowsLiveWriter/Attjmfraexaktochungefrligt_E6C5/image_thumb.png" width="608" border="0" />
          </a> <br />
SELECT * FROM b1 JOIN b2 ON b2.blat2 like b1.blat1 +'%'
</p>
        <p>
          <a href="http://www.underlandet.com/SqlServer/content/binary/WindowsLiveWriter/Attjmfraexaktochungefrligt_E6C5/image_4.png">
            <img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; WIDTH: 558px; BORDER-BOTTOM: 0px; HEIGHT: 235px" height="282" alt="image" src="http://www.underlandet.com/SqlServer/content/binary/WindowsLiveWriter/Attjmfraexaktochungefrligt_E6C5/image_thumb_1.png" width="610" border="0" />
          </a>
          <br />
SELECT * FROM b1 JOIN b2 ON left(b2.blat2,5) = b1.blat1
</p>
        <a href="http://intressant.se/intressant">Intressant?</a>
        <br />
Andra bloggar om <a href="http://bloggar.se/om/SQL+Server">SQL Server</a>, <a href="http://bloggar.se/om/Optimering">Optimering</a></body>
      <title>Att j&amp;auml;mf&amp;ouml;ra exakt och ungef&amp;auml;rligt</title>
      <guid isPermaLink="false">http://www.underlandet.com/SqlServer/PermaLink,guid,27c7bc11-eb85-4612-af45-79e2743b4e8d.aspx</guid>
      <link>http://www.underlandet.com/SqlServer/2008/04/23/AttJaumlmfoumlraExaktOchUngefaumlrligt.aspx</link>
      <pubDate>Wed, 23 Apr 2008 14:29:52 GMT</pubDate>
      <description>&lt;p&gt;
Via &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2008/04/22/sql-server-query-processing-puzzle-like-vs.aspx"&gt;en
bloggpost&lt;/a&gt; från &lt;a href="http://sqlblog.com/blogs/adam_machanic/"&gt;Adam Machanic&lt;/a&gt; har
jag deltagit i en tävling om ett exemplar av &lt;a href="http://www.amazon.com/dp/159059729X"&gt;Expert
SQL Server 2005 Development&lt;/a&gt;. Frågan från Adam är:
&lt;/p&gt;
&lt;p&gt;
Givet att du har två tabeller, som skapats med scriptet nedan:
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;USE TempDB&lt;br&gt;
GO&lt;br&gt;
&lt;br&gt;
CREATE TABLE b1 (blat1 CHAR(5) NOT NULL)&lt;br&gt;
CREATE TABLE b2 (blat2 VARCHAR(200) NOT NULL)&lt;br&gt;
GO&lt;br&gt;
&lt;br&gt;
INSERT b1&lt;br&gt;
SELECT LEFT(AddressLine1, 5) AS blat1&lt;br&gt;
FROM AdventureWorks.Person.Address&lt;br&gt;
&lt;br&gt;
INSERT b2&lt;br&gt;
SELECT AddressLine1 AS blat2&lt;br&gt;
FROM AdventureWorks.Person.Address&lt;br&gt;
GO&lt;/pre&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Hur kan man skriva om nedanstående fråga så att den blir snabbare (den tar ungefär
sex minuter på min PC):
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;SELECT *&lt;br&gt;
FROM b1&lt;br&gt;
JOIN b2 ON&lt;br&gt;
b2.blat2 LIKE b1.blat1 + '%'&lt;/pre&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Inga objekt-ändringar är tillåtna, dvs ingen indexering av tabellerna får göras.
&lt;/p&gt;
&lt;p&gt;
Lösningen är att göra exakta jämförelser istället för ungefärliga. Dvs att använda
"="-operatorn istället för "LIKE"-operatorn. Varför? Jo, därför att "LIKE"-operatorn
gör att vi måste använda oss av en "NESTED LOOP" för att jämföra raderna. Dvs SQL
Servers Query Processor (QP) måste titta på varje rad i den yttre tabellen i JOIN-operationen,
och för varje rad i den yttre tabellen måste QP titta på varje rad i den inre tabellen
för att jämföra data. Både b1 och b2 innehåller 19614 rader. Det är inga extrema datamängder,
långt därifrån. För att köra ovanstående fråga måste QP titta på 19614 i b1, och för
varje av dessa rader måste 19614 rader i b2 undersökas. Dvs 384 708 996 rader måste
undersökas.
&lt;/p&gt;
&lt;p&gt;
Lyckas vi istället använda en "="-operator kan QP använda en "MERGE" eller "HASH MATCH",
vilket väsentligen reducerar antalet rader att titta på.
&lt;/p&gt;
&lt;p&gt;
Min omskrivna fråga blir:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
SELECT *&lt;br&gt;
FROM b1&lt;br&gt;
JOIN b2 ON&lt;br&gt;
LEFT(b2.blat2,5) = b1.blat1
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Det funkar därför att vi vet att b1.blat2 innehåller de första fem tecknen från b2.blat2.
Tack vare den vetskapen kan frågan skrivas om, och köras på två sekunder. QP utför
en "HASH MATCH" och antalet rader som måste undersökas för att utföra JOIN-operationen
reduceras väsentligt.
&lt;/p&gt;
&lt;p&gt;
Nedan ser du bilder av de estimerade planerna för de båda frågorna, och kan själv
se skillnaden i estimerat antal rader för "NESTED LOOP" jämfört med "HASH MATCH" (Jämför
"Estimated Number of Rows")
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.underlandet.com/SqlServer/content/binary/WindowsLiveWriter/Attjmfraexaktochungefrligt_E6C5/image_2.png"&gt;&lt;img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; WIDTH: 557px; BORDER-BOTTOM: 0px; HEIGHT: 224px" height=274 alt=image src="http://www.underlandet.com/SqlServer/content/binary/WindowsLiveWriter/Attjmfraexaktochungefrligt_E6C5/image_thumb.png" width=608 border=0&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt;
SELECT * FROM b1 JOIN b2 ON b2.blat2 like b1.blat1 +'%'
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.underlandet.com/SqlServer/content/binary/WindowsLiveWriter/Attjmfraexaktochungefrligt_E6C5/image_4.png"&gt;&lt;img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; WIDTH: 558px; BORDER-BOTTOM: 0px; HEIGHT: 235px" height=282 alt=image src="http://www.underlandet.com/SqlServer/content/binary/WindowsLiveWriter/Attjmfraexaktochungefrligt_E6C5/image_thumb_1.png" width=610 border=0&gt;&lt;/a&gt; 
&lt;br&gt;
SELECT * FROM b1 JOIN b2 ON left(b2.blat2,5) = b1.blat1
&lt;/p&gt;
&lt;a href="http://intressant.se/intressant"&gt;Intressant?&lt;/a&gt;
&lt;br&gt;
Andra bloggar om &lt;a href="http://bloggar.se/om/SQL+Server"&gt;SQL Server&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Optimering"&gt;Optimering&lt;/a&gt;</description>
      <comments>http://www.underlandet.com/SqlServer/CommentView,guid,27c7bc11-eb85-4612-af45-79e2743b4e8d.aspx</comments>
      <category>Optimering</category>
    </item>
    <item>
      <trackback:ping>http://www.underlandet.com/SqlServer/Trackback.aspx?guid=0de5d30d-de7c-497c-b081-bf44b6783271</trackback:ping>
      <pingback:server>http://www.underlandet.com/SqlServer/pingback.aspx</pingback:server>
      <pingback:target>http://www.underlandet.com/SqlServer/PermaLink,guid,0de5d30d-de7c-497c-b081-bf44b6783271.aspx</pingback:target>
      <dc:creator>Magnus Ahlkvist</dc:creator>
      <wfw:comment>http://www.underlandet.com/SqlServer/CommentView,guid,0de5d30d-de7c-497c-b081-bf44b6783271.aspx</wfw:comment>
      <wfw:commentRss>http://www.underlandet.com/SqlServer/SyndicationService.asmx/GetEntryCommentsRss?guid=0de5d30d-de7c-497c-b081-bf44b6783271</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Fler än en gång har jag försökt att grundläggande förklara lite grann om index i SQL
Server (och egentligen alla andra databaser, det funkar ju faktiskt rätt lika). Det
som flest har svårt att förstå är det här med klustrade och icke-klustrade index.
Många undrar vad som är skillnaden, och många undrar vilket index som är bästa kandidaten
att använda som klustrat index. Här tänkte jag försöka sammanfatta vad jag brukar
svara.
</p>
        <p>
          <strong>Vad är det?</strong>
          <br />
Ett klustrat index är ett index som lagras tillsammans med datat för en tabell. Det
gör att datat självt är sorterat, vilket kan vara användbart emellanåt. 
</p>
        <p>
Den bästa jämförelsen jag känner till är en telefonkatalog. I en telefonkatalog finns
sidor, som vi kan jämföra med data-pages i SQL Server. Varje telefonnummer kan jämföras
med en rad i en tabell i SQL Server. Telefonnumren är sorterade efter Efternamn, Förnamn.
På samma sätt funkar ett klustrat index. Datat på varje data-page är sorterat efter
det klustrade indexet som finns på tabellen. Tabellens data-pages är sorterade inbördes
enligt samma princip. 
</p>
        <p>
I SQL Server finns dessutom ett index-träd utanför tabellen som gör att det blir lite
lättare att hitta till den första raden som uppfyller ett sökvillkor i det klustrade
indexet. Det kan jämföras med att högerkanten på sidorna i en telefonkatalog ofta
innehåller ett första-bokstaven-register, som ger genvägar till alla efternamn som
börjar på en viss bokstav.
</p>
        <p>
Har du en tabell med telefonnummer, Efternamn och Förnamn, där Efternamn, Förnamn
är ett klustrat index, och du vill söka ut alla telefonnummer tillhörande någon som
heter Andersson, så lägger du in "WHERE efternamn = 'Andersson'" som WHERE-klausul
i din fråga. SQL Server börjar då leta i sitt index-träd efter 'Andersson', och när
den hittar 'Andersson' så går den via en adress-pekare direkt till den data-page där
den första förekomsten av 'Andersson' finns. Eftersom datat är sorterat efter Efternamn,
Förnamn finns nu ingen anledning att gå tillbaka till något ytterligare index för
att hitta alla rader för med Efternamn='Andersson', utan SQL Server kan börja läsa
data-page efter data-page, tills den stöter på ett efternamn som INTE är 'Andersson'.
</p>
        <p>
          <strong>Icke-klustrat då?<br /></strong>Icke-klustrade index lagras helt och hållet utanför själva datat för en tabell.
De lagras också i trädstrukturer, men innehåller till skillnad från klustrade index
ett index-löv för varje rad i tabellen, och en pekare till adressen där raden lagras.
Vill du läsa alla som heter 'Andersson' enigt exemplet ovan får SQL Server jobba lite
mer för att hitta allt data. Den måste göra följande fler-stegs-raket:
</p>
        <ol>
          <li>
Leta upp första lövet/nästa löv med efternamn='Andersson' i indexträdet. 
</li>
          <li>
Följ pekaren till den data-pagen där raden som index-lövet motsvarar lagras. 
</li>
          <li>
Stoppa in raden i en temporär "Spool-tabell" 
</li>
          <li>
Upprepa steg 1-3 tills alla 'Andersson' är funna 
</li>
          <li>
Läs "Spool-tabellen" och returnera.</li>
        </ol>
        <p>
Alltså något mer arbete än att bara leta reda på den första raden och sen läsa och
returnera rad för rad.
</p>
        <p>
          <strong>Vad ska jag välja som klustrat index?</strong>
          <br />
När man börjar diskutera kandidater för klustrade index ändras ofta diskussionen till
att bli av religiös karaktär. 
</p>
        <p>
SQL Server skapar alltid ett klustrat index, oavsett om vi vill det eller inte. Om
vi inte själva bestämmer vilket index som ska vara klustrat skapas ett "osynligt"
klustrat index som vi inte har varken nytta av eller kontroll över. Därför är det
hyfsat självklart att vi ska välja ett klustrat index. Som standard skapar SQL Server
ett klustrat index över kolumnen eller kolumnerna som ingår i primärnyckeln, om det
inte redan finns ett klustrat index när primärnyckeln skapas. 
</p>
        <p>
Vissa hävdar att det här alltid är helt rätt och att man aldrig ska använda sig av
annat än primärnyckeln som klustrat index. Det är snick-snack i mina öron. Tänk dig
återigen fallet med telefonkatalogen. Man kan tänka sig att telefonnummer är primärnyckel
i en telefonkatalog, eller hur? Varför skulle vi vilja ha telefonnummer som klustrat
index i telefonkatalogen? Din Del skulle förmodligen ha betydligt färre nöjda mottagare
av katalogen om den var sorterad efter telefonnummer..
</p>
        <p>
Vissa hävdar att man ska ha HÖG selektivitet på det index som är klustrat. Dvs att
man får träff på väldigt få rader om man söker i indexet efter ett visst värde. Varför
det skulle vara en fördel förstår jag ärligt talat inte. Har man hög selektivitet
på ett index, till exempel en primärnyckel, så kostar det ju väldigt lite att först
söka reda på index-lövet och sen besöka en eller ett fåtal rader via pekare. Har man
däremot LÅG selektivitet (exempelvis efternamn i en telefonkatalog) så kostar det
ganska mycket att gå via ett icke-klustrat index.
</p>
        <p>
Jag tycker att främmande nycklar ofta utgör bra kandidater för klustrade index. Tänker
dig en order-applikation, med en Order-tabell och en Order-rad-tabell. Där vill man
väldigt ofta selektera ut alla orderrader som tillhör ett visst ordernummer. Då är
Ordernummer-kolumnen i orderrad-tabellen en perfekt kandidat för klustrat index. Nu
skulle jag i och för sig designa min tabell så att primärnyckeln bestod av Order-nummer
och Orderrad-nummer. Men många SQL Server-utvecklare använder sig ALDRIG av naturliga
nycklar, utan skapar istället en IDENTITY-kolumn som primärnyckel. Den kolumnen är
precis värdelös att använda som klustrat index, ur sökbarhetssynpunkt.
</p>
        <p>
          <strong>Sammanfattningsvis<br /></strong>Tänk dig för innan du bara accepterar SQL Servers förslag att skapa klustrat
index av primärnyckeln. Använder du dig av normaliserade tabeller, med bara naturliga
nycklar är det förmodligen bra kandidater för klustrade index. Men om du tillhör de
99% SQL Server-utvecklare som istället skapar en surrogat-nyckel och en UNIQUE-constraint
(VARFÖR GÖR FÖRRESTEN SÅ MÅNGA DET, DET ÄR VERKLIGEN DUBBELARBETE!!!) över det som
kunde varit naturlig nyckel - ja då ska du fundera både en och två gånger på vilket
klustrat index du bör använda. Tänk telefonkatalog!
</p>
        <a href="http://intressant.se/intressant">Intressant?</a>
        <br />
Andra bloggar om <a href="http://bloggar.se/om/SQL+Server">SQL Server</a>, <a href="http://bloggar.se/om/Databaser">Databaser</a>, <a href="http://bloggar.se/om/Index">Index</a>, <a href="http://bloggar.se/om/Klustrade+index">Klustrade
index</a></body>
      <title>Vadd&amp;aring; klusterindex?</title>
      <guid isPermaLink="false">http://www.underlandet.com/SqlServer/PermaLink,guid,0de5d30d-de7c-497c-b081-bf44b6783271.aspx</guid>
      <link>http://www.underlandet.com/SqlServer/2008/04/18/VaddaringKlusterindex.aspx</link>
      <pubDate>Fri, 18 Apr 2008 14:54:36 GMT</pubDate>
      <description>&lt;p&gt;
Fler än en gång har jag försökt att grundläggande förklara lite grann om index i SQL
Server (och egentligen alla andra databaser, det funkar ju faktiskt rätt lika). Det
som flest har svårt att förstå är det här med klustrade och icke-klustrade index.
Många undrar vad som är skillnaden, och många undrar vilket index som är bästa kandidaten
att använda som klustrat index. Här tänkte jag försöka sammanfatta vad jag brukar
svara.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Vad är det?&lt;/strong&gt;
&lt;br&gt;
Ett klustrat index är ett index som lagras tillsammans med datat för en tabell. Det
gör att datat självt är sorterat, vilket kan vara användbart emellanåt. 
&lt;/p&gt;
&lt;p&gt;
Den bästa jämförelsen jag känner till är en telefonkatalog. I en telefonkatalog finns
sidor, som vi kan jämföra med data-pages i SQL Server. Varje telefonnummer kan jämföras
med en rad i en tabell i SQL Server. Telefonnumren är sorterade efter Efternamn, Förnamn.
På samma sätt funkar ett klustrat index. Datat på varje data-page är sorterat efter
det klustrade indexet som finns på tabellen. Tabellens data-pages är sorterade inbördes
enligt samma princip. 
&lt;/p&gt;
&lt;p&gt;
I SQL Server finns dessutom ett index-träd utanför tabellen som gör att det blir lite
lättare att hitta till den första raden som uppfyller ett sökvillkor i det klustrade
indexet. Det kan jämföras med att högerkanten på sidorna i en telefonkatalog ofta
innehåller ett första-bokstaven-register, som ger genvägar till alla efternamn som
börjar på en viss bokstav.
&lt;/p&gt;
&lt;p&gt;
Har du en tabell med telefonnummer, Efternamn och Förnamn, där Efternamn, Förnamn
är ett klustrat index, och du vill söka ut alla telefonnummer tillhörande någon som
heter Andersson, så lägger du in "WHERE efternamn = 'Andersson'" som WHERE-klausul
i din fråga. SQL Server börjar då leta i sitt index-träd efter 'Andersson', och när
den hittar 'Andersson' så går den via en adress-pekare direkt till den data-page där
den första förekomsten av 'Andersson' finns. Eftersom datat är sorterat efter Efternamn,
Förnamn finns nu ingen anledning att gå tillbaka till något ytterligare index för
att hitta alla rader för med Efternamn='Andersson', utan SQL Server kan börja läsa
data-page efter data-page, tills den stöter på ett efternamn som INTE är 'Andersson'.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Icke-klustrat då?&lt;br&gt;
&lt;/strong&gt;Icke-klustrade index lagras helt och hållet utanför själva datat för en tabell.
De lagras också i trädstrukturer, men innehåller till skillnad från klustrade index
ett index-löv för varje rad i tabellen, och en pekare till adressen där raden lagras.
Vill du läsa alla som heter 'Andersson' enigt exemplet ovan får SQL Server jobba lite
mer för att hitta allt data. Den måste göra följande fler-stegs-raket:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Leta upp första lövet/nästa löv med efternamn='Andersson' i indexträdet. 
&lt;li&gt;
Följ pekaren till den data-pagen där raden som index-lövet motsvarar lagras. 
&lt;li&gt;
Stoppa in raden i en temporär "Spool-tabell" 
&lt;li&gt;
Upprepa steg 1-3 tills alla 'Andersson' är funna 
&lt;li&gt;
Läs "Spool-tabellen" och returnera.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Alltså något mer arbete än att bara leta reda på den första raden och sen läsa och
returnera rad för rad.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Vad ska jag välja som klustrat index?&lt;/strong&gt;
&lt;br&gt;
När man börjar diskutera kandidater för klustrade index ändras ofta diskussionen till
att bli av religiös karaktär. 
&lt;/p&gt;
&lt;p&gt;
SQL Server skapar alltid ett klustrat index, oavsett om vi vill det eller inte. Om
vi inte själva bestämmer vilket index som ska vara klustrat skapas ett "osynligt"
klustrat index som vi inte har varken nytta av eller kontroll över. Därför är det
hyfsat självklart att vi ska välja ett klustrat index. Som standard skapar SQL Server
ett klustrat index över kolumnen eller kolumnerna som ingår i primärnyckeln, om det
inte redan finns ett klustrat index när primärnyckeln skapas. 
&lt;/p&gt;
&lt;p&gt;
Vissa hävdar att det här alltid är helt rätt och att man aldrig ska använda sig av
annat än primärnyckeln som klustrat index. Det är snick-snack i mina öron. Tänk dig
återigen fallet med telefonkatalogen. Man kan tänka sig att telefonnummer är primärnyckel
i en telefonkatalog, eller hur? Varför skulle vi vilja ha telefonnummer som klustrat
index i telefonkatalogen? Din Del skulle förmodligen ha betydligt färre nöjda mottagare
av katalogen om den var sorterad efter telefonnummer..
&lt;/p&gt;
&lt;p&gt;
Vissa hävdar att man ska ha HÖG selektivitet på det index som är klustrat. Dvs att
man får träff på väldigt få rader om man söker i indexet efter ett visst värde. Varför
det skulle vara en fördel förstår jag ärligt talat inte. Har man hög selektivitet
på ett index, till exempel en primärnyckel, så kostar det ju väldigt lite att först
söka reda på index-lövet och sen besöka en eller ett fåtal rader via pekare. Har man
däremot LÅG selektivitet (exempelvis efternamn i en telefonkatalog) så kostar det
ganska mycket att gå via ett icke-klustrat index.
&lt;/p&gt;
&lt;p&gt;
Jag tycker att främmande nycklar ofta utgör bra kandidater för klustrade index. Tänker
dig en order-applikation, med en Order-tabell och en Order-rad-tabell. Där vill man
väldigt ofta selektera ut alla orderrader som tillhör ett visst ordernummer. Då är
Ordernummer-kolumnen i orderrad-tabellen en perfekt kandidat för klustrat index. Nu
skulle jag i och för sig designa min tabell så att primärnyckeln bestod av Order-nummer
och Orderrad-nummer. Men många SQL Server-utvecklare använder sig ALDRIG av naturliga
nycklar, utan skapar istället en IDENTITY-kolumn som primärnyckel. Den kolumnen är
precis värdelös att använda som klustrat index, ur sökbarhetssynpunkt.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Sammanfattningsvis&lt;br&gt;
&lt;/strong&gt;Tänk dig för innan du bara accepterar SQL Servers förslag att skapa klustrat
index av primärnyckeln. Använder du dig av normaliserade tabeller, med bara naturliga
nycklar är det förmodligen bra kandidater för klustrade index. Men om du tillhör de
99% SQL Server-utvecklare som istället skapar en surrogat-nyckel och en UNIQUE-constraint
(VARFÖR GÖR FÖRRESTEN SÅ MÅNGA DET, DET ÄR VERKLIGEN DUBBELARBETE!!!) över det som
kunde varit naturlig nyckel - ja då ska du fundera både en och två gånger på vilket
klustrat index du bör använda. Tänk telefonkatalog!
&lt;/p&gt;
&lt;a href="http://intressant.se/intressant"&gt;Intressant?&lt;/a&gt;
&lt;br&gt;
Andra bloggar om &lt;a href="http://bloggar.se/om/SQL+Server"&gt;SQL Server&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Databaser"&gt;Databaser&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Index"&gt;Index&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Klustrade+index"&gt;Klustrade
index&lt;/a&gt;</description>
      <comments>http://www.underlandet.com/SqlServer/CommentView,guid,0de5d30d-de7c-497c-b081-bf44b6783271.aspx</comments>
      <category>Optimering</category>
    </item>
    <item>
      <trackback:ping>http://www.underlandet.com/SqlServer/Trackback.aspx?guid=8c07ce1f-ec8f-4243-ac8d-005369d699cf</trackback:ping>
      <pingback:server>http://www.underlandet.com/SqlServer/pingback.aspx</pingback:server>
      <pingback:target>http://www.underlandet.com/SqlServer/PermaLink,guid,8c07ce1f-ec8f-4243-ac8d-005369d699cf.aspx</pingback:target>
      <dc:creator>Magnus Ahlkvist</dc:creator>
      <wfw:comment>http://www.underlandet.com/SqlServer/CommentView,guid,8c07ce1f-ec8f-4243-ac8d-005369d699cf.aspx</wfw:comment>
      <wfw:commentRss>http://www.underlandet.com/SqlServer/SyndicationService.asmx/GetEntryCommentsRss?guid=8c07ce1f-ec8f-4243-ac8d-005369d699cf</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
När man installerar SQL Server 2005 kan man få problem med att installationen verkar
"hänga sig" medan den gör "Setting File Security". Tittar man i loggen är det sista
den gör något i stil med "Write_sqlFileSDDL".
</p>
        <p>
I själva verket har inte installationen hängt sig. Den tar bara EXTREMT lång tid på
sig att hoppa till nästa steg. Problemet beskrivs av Microsoft i en KB-artikel (<a title="http://support.microsoft.com/kb/910070" href="http://support.microsoft.com/kb/910070">http://support.microsoft.com/kb/910070</a>)
som Active Directory-relaterat. Om domänen har många trust-relationer med andra domäner
kan det ta lång tid att göra uppslag i katalogen. Det verkar stämma med min erfarenhet.
Jag har stött på problemet då jag installerat SQL Server 2005 på maskiner som ingår
i ett stort Active Directory, spritt över flera kontor, med ibland så långsam uppkoppling
som 128kbit/s.
</p>
        <p>
Det finns en Hotfix att hämta från Microsoft. Det finns också en "Workaround" listad
i samma KB-artikel, som funkade bra för mig. Den går ut på att helt enkelt inaktivera
nätverkskortet en stund, så att SQL Server-installationen kan förstå att den inte
kommer att hitta en AD-resurs, och istället gå vidare med livet och slutföra installationen.
</p>
        <p>
Ett problem med att inaktivera ett nätverkskort kan förstås vara att man gör sin installation
på en server som man inte har fysisk tillgång till. Det kan upplevas som lite svårt
att logga in med Remote Desktop om man har inaktiverat nätverket på servern... Det
kan man lösa genom att köra ett command-script som inaktiverar nätverkskortet, pausar
en stund och sedan aktiverar nätverkskortet.
</p>
        <p>
Syntaxen för att inaktivera och aktivera nätverkskort varierar från version till version
av Windows. I Windows Server 2003 ser det ut såhär:
</p>
        <blockquote>
          <p>
netsh interface set interface "Local Area Connection" DISABLED
</p>
        </blockquote>
        <p>
och
</p>
        <blockquote>
          <p>
netsh interface set interface "Local Area Connection" ENABLED
</p>
        </blockquote>
        <p>
Då återstår alltså bara att lägga till "pausa en stund" så har vi en färdig bat- eller
cmd-fil som gör vad vi vill. Men det är dessvärre inte "bara" att pausa ett script.
PAUSE-kommandot som finns i Windows pausar i väntan på att användaren ska trycka på
en tangent. Det är inte dirket användbart när vi vill använda vårt script för att
inaktivera ett nätverkskort, pausa och sen aktivera. Det blir svårt att trycka på
en tangent när ens fjärranslutning kopplats ned så att man inte längre kommer åt maskinen
som scriptet körs på... Lyckligtvis finns det andra saker man kan göra för att pausa
ett script. Jag har använt mig av "ping 127.0.0.1", dvs att pinga "loopback interfacet"
(svensk översättning någon?). 
</p>
        <p>
Ett helt script kan alltså se ut såhär:
</p>
        <blockquote>
          <p>
REM Inaktivera nätverkskort<br />
netsh interface set interface "Local Area Connection" DISABLED<br />
REM Pausa cirka 10 sekunder<br />
ping -n 10 127.0.0.1<br />
REM Aktivera nätverkskort<br />
netsh interface set interface "Local Area Connection" ENABLED
</p>
        </blockquote>
        <a href="http://intressant.se/intressant">Intressant?</a>
        <br />
Andra bloggar om <a href="http://bloggar.se/om/Installation">Installation</a>, <a href="http://bloggar.se/om/netsh">netsh</a>, <a href="http://bloggar.se/om/SQL+Server+2005">SQL
Server 2005</a></body>
      <title>Installation av SQL Server 2005 h&amp;auml;nger sig</title>
      <guid isPermaLink="false">http://www.underlandet.com/SqlServer/PermaLink,guid,8c07ce1f-ec8f-4243-ac8d-005369d699cf.aspx</guid>
      <link>http://www.underlandet.com/SqlServer/2008/04/15/InstallationAvSQLServer2005HaumlngerSig.aspx</link>
      <pubDate>Tue, 15 Apr 2008 09:14:32 GMT</pubDate>
      <description>&lt;p&gt;
När man installerar SQL Server 2005 kan man få problem med att installationen verkar
"hänga sig" medan den gör "Setting File Security". Tittar man i loggen är det sista
den gör något i stil med "Write_sqlFileSDDL".
&lt;/p&gt;
&lt;p&gt;
I själva verket har inte installationen hängt sig. Den tar bara EXTREMT lång tid på
sig att hoppa till nästa steg. Problemet beskrivs av Microsoft i en KB-artikel (&lt;a title="http://support.microsoft.com/kb/910070" href="http://support.microsoft.com/kb/910070"&gt;http://support.microsoft.com/kb/910070&lt;/a&gt;)
som Active Directory-relaterat. Om domänen har många trust-relationer med andra domäner
kan det ta lång tid att göra uppslag i katalogen. Det verkar stämma med min erfarenhet.
Jag har stött på problemet då jag installerat SQL Server 2005 på maskiner som ingår
i ett stort Active Directory, spritt över flera kontor, med ibland så långsam uppkoppling
som 128kbit/s.
&lt;/p&gt;
&lt;p&gt;
Det finns en Hotfix att hämta från Microsoft. Det finns också en "Workaround" listad
i samma KB-artikel, som funkade bra för mig. Den går ut på att helt enkelt inaktivera
nätverkskortet en stund, så att SQL Server-installationen kan förstå att den inte
kommer att hitta en AD-resurs, och istället gå vidare med livet och slutföra installationen.
&lt;/p&gt;
&lt;p&gt;
Ett problem med att inaktivera ett nätverkskort kan förstås vara att man gör sin installation
på en server som man inte har fysisk tillgång till. Det kan upplevas som lite svårt
att logga in med Remote Desktop om man har inaktiverat nätverket på servern... Det
kan man lösa genom att köra ett command-script som inaktiverar nätverkskortet, pausar
en stund och sedan aktiverar nätverkskortet.
&lt;/p&gt;
&lt;p&gt;
Syntaxen för att inaktivera och aktivera nätverkskort varierar från version till version
av Windows. I Windows Server 2003 ser det ut såhär:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
netsh interface set interface "Local Area Connection" DISABLED
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
och
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
netsh interface set interface "Local Area Connection" ENABLED
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Då återstår alltså bara att lägga till "pausa en stund" så har vi en färdig bat- eller
cmd-fil som gör vad vi vill. Men det är dessvärre inte "bara" att pausa ett script.
PAUSE-kommandot som finns i Windows pausar i väntan på att användaren ska trycka på
en tangent. Det är inte dirket användbart när vi vill använda vårt script för att
inaktivera ett nätverkskort, pausa och sen aktivera. Det blir svårt att trycka på
en tangent när ens fjärranslutning kopplats ned så att man inte längre kommer åt maskinen
som scriptet körs på... Lyckligtvis finns det andra saker man kan göra för att pausa
ett script. Jag har använt mig av "ping 127.0.0.1", dvs att pinga "loopback interfacet"
(svensk översättning någon?). 
&lt;/p&gt;
&lt;p&gt;
Ett helt script kan alltså se ut såhär:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
REM Inaktivera nätverkskort&lt;br&gt;
netsh interface set interface "Local Area Connection" DISABLED&lt;br&gt;
REM Pausa cirka 10 sekunder&lt;br&gt;
ping -n 10 127.0.0.1&lt;br&gt;
REM Aktivera nätverkskort&lt;br&gt;
netsh interface set interface "Local Area Connection" ENABLED
&lt;/p&gt;
&lt;/blockquote&gt;&lt;a href="http://intressant.se/intressant"&gt;Intressant?&lt;/a&gt;
&lt;br&gt;
Andra bloggar om &lt;a href="http://bloggar.se/om/Installation"&gt;Installation&lt;/a&gt;, &lt;a href="http://bloggar.se/om/netsh"&gt;netsh&lt;/a&gt;, &lt;a href="http://bloggar.se/om/SQL+Server+2005"&gt;SQL
Server 2005&lt;/a&gt;</description>
      <comments>http://www.underlandet.com/SqlServer/CommentView,guid,8c07ce1f-ec8f-4243-ac8d-005369d699cf.aspx</comments>
      <category>Installation</category>
      <category>SQL Server 2005</category>
    </item>
    <item>
      <trackback:ping>http://www.underlandet.com/SqlServer/Trackback.aspx?guid=33163bb2-47ae-42ec-98ad-e0b5f2ca9792</trackback:ping>
      <pingback:server>http://www.underlandet.com/SqlServer/pingback.aspx</pingback:server>
      <pingback:target>http://www.underlandet.com/SqlServer/PermaLink,guid,33163bb2-47ae-42ec-98ad-e0b5f2ca9792.aspx</pingback:target>
      <dc:creator>Magnus Ahlkvist</dc:creator>
      <wfw:comment>http://www.underlandet.com/SqlServer/CommentView,guid,33163bb2-47ae-42ec-98ad-e0b5f2ca9792.aspx</wfw:comment>
      <wfw:commentRss>http://www.underlandet.com/SqlServer/SyndicationService.asmx/GetEntryCommentsRss?guid=33163bb2-47ae-42ec-98ad-e0b5f2ca9792</wfw:commentRss>
      <title>Undvik SQL Injection med parametriserade fr&amp;aring;gor!</title>
      <guid isPermaLink="false">http://www.underlandet.com/SqlServer/PermaLink,guid,33163bb2-47ae-42ec-98ad-e0b5f2ca9792.aspx</guid>
      <link>http://www.underlandet.com/SqlServer/2008/04/10/UndvikSQLInjectionMedParametriseradeFraringgor.aspx</link>
      <pubDate>Thu, 10 Apr 2008 11:44:06 GMT</pubDate>
      <description>&lt;p&gt;
När du programmerar mot en databas ifrån .NET - undvik att skicka in parametrar i
koden på det här viset:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;
&lt;span style="font-size: 10pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;Dim&lt;/span&gt; s &lt;span style="color: blue"&gt;As&lt;/span&gt; &lt;span style="color: blue"&gt;String&lt;/span&gt; =
TextBox1.Text&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;Dim&lt;/span&gt; cmd &lt;span style="color: blue"&gt;As&lt;/span&gt; &lt;span style="color: blue"&gt;New&lt;/span&gt; SqlClient.SqlCommand("SELECT
* FROM tabell WHERE kolumn='" &amp;amp; s &amp;amp; "'", cn)&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;Dim&lt;/span&gt; dr &lt;span style="color: blue"&gt;As&lt;/span&gt;&lt;?xml:namespace prefix = o /&gt; SqlClient.SqlDataReader
= cmd.ExecuteReader()&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p class="MsoNormal"&gt;
Det kan nämligen leda till SQL Injection. Vad det innebär? Jo, att en illvillig användare
anropar din sida med skadlig SQL-kod, genom att i TextBox1 skriva in SQL-kommandon.
Tänk dig att en användare skriver in följande i TextBox1:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
'; DROP DATABASE minDatabas;SELECT 'You suck!
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Vad skulle hända då? Jo, det som skulle hända är att det du egentligen vill göra -
nämligen att välja från tabellen "tabell" körs, med en tom sträng som WHERE-villkor
för kolumnen "kolumn". Därefter skulle kommandot "DROP DATABASE minDatabas" köras,
dvs databasen minDatabas skulle tas bort ifrån SQL Server. Slutligen skulle kommandot
"SELECT 'You suck!'" köras. Och det är ju INTE vad vi vill ska hända...
&lt;/p&gt;
&lt;p&gt;
Det absolut enklaste sättet att undvika SQL Injection är att använda parmeteriserade
frågor. Såhär kan det se ut:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;
&lt;span style="font-size: 10pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;Dim&lt;/span&gt; s &lt;span style="color: blue"&gt;As&lt;/span&gt; &lt;span style="color: blue"&gt;String&lt;/span&gt; =
TextBox1.Text&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;Dim&lt;/span&gt; cmd &lt;span style="color: blue"&gt;As&lt;/span&gt; &lt;span style="color: blue"&gt;New&lt;/span&gt; SqlClient.SqlCommand("SELECT
* FROM tabell WHERE kolumn = @kolumn", cn)&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'"&gt;cmd.Parameters.Add(&lt;span style="color: blue"&gt;New&lt;/span&gt; SqlClient.SqlParameter("@kolumn",
s))&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;Dim&lt;/span&gt; dr &lt;span style="color: blue"&gt;As&lt;/span&gt; SqlClient.SqlDataReader
= cmd.ExecuteReader()&lt;/span&gt;
&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Ytterligare en kodrad, och BETYDLIGT säkrare kod. ADO.NET tar hand om att parametern
som jag skickar in omvandlas på ett sådant sätt att den är säker för SQL Server att
ta emot. Ingen SQL Injection alltså.
&lt;/p&gt;
&lt;p&gt;
Hade IDG förstått vikten av att använda parametrar i sin kod hade &lt;a href="http://www.idg.se/2.1085/1.155230"&gt;DET
HÄR&lt;/a&gt; aldrig hänt :)
&lt;/p&gt;
&lt;a href="http://intressant.se/intressant"&gt;Intressant?&lt;/a&gt;
&lt;br&gt;
Andra bloggar om &lt;a href="http://bloggar.se/om/SQL+Server"&gt;SQL Server&lt;/a&gt;, &lt;a href="http://bloggar.se/om/SQL+Injection"&gt;SQL
Injection&lt;/a&gt;, &lt;a href="http://bloggar.se/om/S&amp;auml;kerhet"&gt;Säkerhet&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Dators&amp;auml;kerhet"&gt;Datorsäkerhet&lt;/a&gt;</description>
      <comments>http://www.underlandet.com/SqlServer/CommentView,guid,33163bb2-47ae-42ec-98ad-e0b5f2ca9792.aspx</comments>
      <category>Säkerhet</category>
    </item>
    <item>
      <trackback:ping>http://www.underlandet.com/SqlServer/Trackback.aspx?guid=b1f37b63-c4ca-45a1-844e-8096d2d6bf78</trackback:ping>
      <pingback:server>http://www.underlandet.com/SqlServer/pingback.aspx</pingback:server>
      <pingback:target>http://www.underlandet.com/SqlServer/PermaLink,guid,b1f37b63-c4ca-45a1-844e-8096d2d6bf78.aspx</pingback:target>
      <dc:creator>Magnus Ahlkvist</dc:creator>
      <wfw:comment>http://www.underlandet.com/SqlServer/CommentView,guid,b1f37b63-c4ca-45a1-844e-8096d2d6bf78.aspx</wfw:comment>
      <wfw:commentRss>http://www.underlandet.com/SqlServer/SyndicationService.asmx/GetEntryCommentsRss?guid=b1f37b63-c4ca-45a1-844e-8096d2d6bf78</wfw:commentRss>
      <title>F&amp;ouml;rs&amp;ouml;k och f&amp;aring;nga</title>
      <guid isPermaLink="false">http://www.underlandet.com/SqlServer/PermaLink,guid,b1f37b63-c4ca-45a1-844e-8096d2d6bf78.aspx</guid>
      <link>http://www.underlandet.com/SqlServer/2008/03/27/FoumlrsoumlkOchFaringnga.aspx</link>
      <pubDate>Thu, 27 Mar 2008 05:54:06 GMT</pubDate>
      <description>&lt;p&gt;
En för mig välkommen nyhet som introducerades i SQL Server 2005 är felhantering genom
TRY/CATCH.
&lt;/p&gt;
&lt;p&gt;
Innan TRY/CATCH såg felhantering typiskt ut något i den här stilen (lite förenklat):
&lt;/p&gt;
&lt;blockquote&gt;&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;
&lt;span style="font-size: 10pt; color: green; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;?xml:namespace prefix = o /&gt;--create
table tabell (fält varchar(10))&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;
&lt;/p&gt;
&lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;
&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; @error &lt;span style="color: blue"&gt;int&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;SET&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; @error&lt;span style="color: gray"&gt;=&lt;/span&gt;0&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;BEGIN&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;TRAN&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;INTO&lt;/span&gt; tabell &lt;span style="color: gray"&gt;(&lt;/span&gt;fält&lt;span style="color: gray"&gt;)&lt;/span&gt; &lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: red"&gt;'abcde12345abcde12345'&lt;/span&gt;&lt;span style="color: gray"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;
&lt;br&gt;
SET&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; @error&lt;span style="color: gray"&gt;=&lt;/span&gt;&lt;span style="color: fuchsia"&gt;@@error&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;IF&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; @error&lt;span style="color: gray"&gt;&amp;gt;&lt;/span&gt;0&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;BEGIN&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;PRINT&lt;/span&gt; @error&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;ROLLBACK&lt;/span&gt; &lt;span style="color: blue"&gt;TRAN&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;GOTO&lt;/span&gt; PROC_EXIT&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;END&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;INSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;INTO&lt;/span&gt; tabell &lt;span style="color: gray"&gt;(&lt;/span&gt;fält&lt;span style="color: gray"&gt;)&lt;/span&gt; &lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: red"&gt;'abcdefghijabcdefghij'&lt;/span&gt;&lt;span style="color: gray"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;
&lt;br&gt;
SET&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; @error&lt;span style="color: gray"&gt;=&lt;/span&gt;&lt;span style="color: fuchsia"&gt;@@error&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;IF&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; @error&lt;span style="color: gray"&gt;&amp;gt;&lt;/span&gt;0&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;BEGIN&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;PRINT&lt;/span&gt; @error&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;ROLLBACK&lt;/span&gt; &lt;span style="color: blue"&gt;TRAN&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;GOTO&lt;/span&gt; PROC_EXIT&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;END&lt;br&gt;
&lt;br&gt;
I&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;NSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;INTO&lt;/span&gt; tabell &lt;span style="color: gray"&gt;(&lt;/span&gt;fält&lt;span style="color: gray"&gt;)&lt;/span&gt; &lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: red"&gt;'12345678901234567890'&lt;/span&gt;&lt;span style="color: gray"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;
&lt;br&gt;
SET&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; @error&lt;span style="color: gray"&gt;=&lt;/span&gt;&lt;span style="color: fuchsia"&gt;@@error&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;IF&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; @error&lt;span style="color: gray"&gt;&amp;gt;&lt;/span&gt;0&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;BEGIN&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;PRINT&lt;/span&gt; @error&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;ROLLBACK&lt;/span&gt; &lt;span style="color: blue"&gt;TRAN&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;GOTO&lt;/span&gt; PROC_EXIT&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;END&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;COMMIT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;TRAN&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;PROC_EXIT&lt;span style="color: gray"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Med TRY/CATCH är det kortare och i min mening betydligt mer lättförståligt:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;
&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;BEGIN&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;TRY&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;BEGIN&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;TRAN&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;I&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;NSERT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;INTO&lt;/span&gt; tabell &lt;span style="color: gray"&gt;(&lt;/span&gt;fält&lt;span style="color: gray"&gt;)&lt;/span&gt; &lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: red"&gt;'12345678901234567890'&lt;/span&gt;&lt;span style="color: gray"&gt;)&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;INSERT&lt;/span&gt; &lt;span style="color: blue"&gt;INTO&lt;/span&gt; tabell &lt;span style="color: gray"&gt;(&lt;/span&gt;fält&lt;span style="color: gray"&gt;)&lt;/span&gt; &lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: red"&gt;'abcdefghijabcdefghij'&lt;/span&gt;&lt;span style="color: gray"&gt;)&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;INSERT&lt;/span&gt; &lt;span style="color: blue"&gt;INTO&lt;/span&gt; tabell &lt;span style="color: gray"&gt;(&lt;/span&gt;fält&lt;span style="color: gray"&gt;)&lt;/span&gt; &lt;span style="color: blue"&gt;VALUES&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: red"&gt;'abcde12345abcde12345'&lt;/span&gt;&lt;span style="color: gray"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;
&lt;br&gt;
COMMIT&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;TRAN&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;END&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;TRY&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;BEGIN&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;CATCH&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;IF&lt;/span&gt; &lt;span style="color: fuchsia"&gt;@@TRANCOUNT&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;gt;&lt;/span&gt;0&lt;br&gt;
&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;ROLLBACK&lt;/span&gt; &lt;span style="color: blue"&gt;TRAN&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue"&gt;PRINT&lt;/span&gt; ERROR_MESSAGE&lt;span style="color: gray"&gt;()&lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: blue; font-family: 'Courier New'; mso-no-proof: yes"&gt;END&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: 'Courier New'; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;CATCH&lt;o:p&gt;&lt;/o:p&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt; 
&lt;p class="MsoNormal"&gt;
En avgörande skillnad finns mellan "gamla" och "nya" sättet att felhantera: Med TRY/CATCH
kastas inga fel till klienten, så det kan definitivt vara läge att slänga in en RAISERROR
i sitt CATCH-block. 
&lt;/p&gt;
&lt;a href="http://intressant.se/intressant"&gt;Intressant?&lt;/a&gt;
&lt;br&gt;
Andra bloggar om &lt;a href="http://bloggar.se/om/SQL+Server"&gt;SQL Server&lt;/a&gt;, &lt;a href="http://bloggar.se/om/SQL+Server+2005"&gt;SQL
Server 2005&lt;/a&gt;, &lt;a href="http://bloggar.se/om/Felhantering"&gt;Felhantering&lt;/a&gt;</description>
      <comments>http://www.underlandet.com/SqlServer/CommentView,guid,b1f37b63-c4ca-45a1-844e-8096d2d6bf78.aspx</comments>
      <category>Felhantering</category>
      <category>SQL Server 2005</category>
    </item>
  </channel>
</rss>