{"id":55000516,"date":"2026-08-01T00:00:00","date_gmt":"2026-10-13T20:20:14","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=516"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"TSQL_Teil_1_Von_JetSQL_zu_TSQL","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/","title":{"rendered":"T-SQL, Teil 1: Von Jet-SQL zu T-SQL"},"content":{"rendered":"<p><b>Die Abfrage l&auml;uft in Access seit Jahren fehlerfrei &#8211; bis die Tabellen auf den SQL Server umziehen. Pl&ouml;tzlich liefert <b>Format<\/b> im Gruppierungsausdruck eine Fehlermeldung, <b>Like &#8220;M*&#8221;<\/b> findet keinen einzigen Datensatz, und ein Aufruf von <b>Nz<\/b> endet mit der Meldung, der Server kenne diese Funktion nicht. Wer Access mit einem SQL Server als Backend betreibt, kommt fr&uuml;her oder sp&auml;ter nicht mehr um T-SQL herum, die Abfragesprache des Servers. Der erste Teil dieser Reihe zeigt, wo sich T-SQL von dem SQL unterscheidet, das wir aus Access kennen, und wie wir T-SQL direkt aus Access heraus ausf&uuml;hren.<\/b><\/p>\n<h2>Was diese Reihe vorhat<\/h2>\n<p>Access spricht seine eigene SQL-Mundart, oft noch Jet-SQL genannt, obwohl die Jet-Engine l&auml;ngst von der ACE-Engine abgel&ouml;st wurde. Solange wir mit Access-Tabellen arbeiten, spielt der Unterschied keine Rolle. Sobald das Backend auf einem SQL Server liegt, &auml;ndert sich die Lage: Eine Access-Abfrage auf verkn&uuml;pfte Tabellen schickt Access nicht einfach an den Server. Access &uuml;bersetzt sie &uuml;ber den ODBC-Treiber so weit wie m&ouml;glich in T-SQL und erledigt den Rest selbst &#8211; nachdem es die ben&ouml;tigten Daten vom Server geholt hat. Was dabei schiefgehen kann, sehen wir weiter unten an echten Fehlermeldungen.<\/p>\n<p>Die folgenden Teile dieser Reihe f&uuml;hren durch die Sprache T-SQL. Jeder Teil geht von einer Technik aus, die wir in Access beherrschen, und zeigt das Gegenst&uuml;ck im SQL Server: von <b>SELECT<\/b> &uuml;ber <b>UPDATE<\/b> und <b>MERGE<\/b>, Sichten, gespeicherte Prozeduren und Trigger bis zu Indizes und Berechtigungen. Dieser erste Teil legt das Fundament. Wir richten die Beispieldatenbank ein, lernen <b>SQL Server Management Studio<\/b> kennen, vergleichen die wichtigsten Unterschiede der beiden Dialekte und f&uuml;hren T-SQL aus Access und aus VBA heraus aus.<\/p>\n<h2>Die Beispieldatenbank -Bestellverwaltung_TSQL<\/h2>\n<p>Als Beispiel dient durch die ganze Reihe eine kleine Bestellverwaltung: Kunden bestellen bei einem H&auml;ndler f&uuml;r Lebensmittel, B&uuml;robedarf und Technik, Mitarbeiter betreuen die Bestellungen, Lieferanten beliefern das Sortiment. Die Datenbank hei&szlig;t <b>Bestellverwaltung_TSQL<\/b> und besteht aus diesen Tabellen:<\/p>\n<ul>\n<li><b>tblKategorien:<\/b> die Warengruppen als zweistufige Hierarchie, &uuml;ber das Fremdschl&uuml;sselfeld <b>OberKategorieID<\/b> auf sich selbst verwiesen<\/li>\n<li><b>tblLieferanten:<\/b> sieben Lieferanten aus Deutschland, &Ouml;sterreich und der Schweiz<\/li>\n<li><b>tblProdukte:<\/b> drei&szlig;ig Produkte mit Preis, Lagerbestand, dem Ja\/Nein-Feld <b>Auslaufartikel<\/b> und einer optionalen Beschreibung<\/li>\n<li><b>tblKunden:<\/b> zweiunddrei&szlig;ig Kunden, teils Firmen, teils Privatpersonen, mit leeren Feldern und Sonderzeichen in den Namen<\/li>\n<li><b>tblMitarbeiter:<\/b> acht Mitarbeiter, &uuml;ber <b>VorgesetzterID<\/b> ebenfalls hierarchisch verkn&uuml;pft<\/li>\n<li><b>tblBestellstatus:<\/b> die f&uuml;nf Bearbeitungsstufen einer Bestellung<\/li>\n<li><b>tblBestellungen:<\/b> 330 Bestellungen von Januar 2024 bis September 2026<\/li>\n<li><b>tblBestelldetails:<\/b> die 825 Positionen der Bestellungen<\/li>\n<\/ul>\n<p>Die Namen folgen einer festen Konvention: Tabellen beginnen mit <b>tbl<\/b>, der Prim&auml;rschl&uuml;ssel einer Tabelle hei&szlig;t wie die Tabelle in der Einzahl mit angeh&auml;ngtem <b>ID<\/b> (etwa <b>ProduktID<\/b> in <b>tblProdukte<\/b>), und Fremdschl&uuml;sselfelder tragen denselben Namen wie das Feld, auf das sie verweisen (<b>KategorieID<\/b> in <b>tblProdukte<\/b> verweist auf <b>tblKategorien<\/b>).<\/p>\n<p>Das Skript <b>Bestellverwaltung_TSQL.sql<\/b> aus dem Download legt die Datenbank samt Daten an. Wir f&uuml;hren es in <b>SQL Server Management Studio<\/b> (kurz SSMS) auf einer lokalen <b>SQL Server Express<\/b>-Instanz aus.<\/p>\n<p>Es l&ouml;scht eine vorhandene Datenbank gleichen Namens und erzeugt sie neu. Danach zeigt der Objekt-Explorer die acht Tabellen (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_516_001.png\" alt=\"Die Tabellen der Datenbank Bestellverwaltung_TSQL im Objekt-Explorer von SSMS\" width=\"425\" height=\"337,5\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Die Tabellen der Datenbank Bestellverwaltung_TSQL im Objekt-Explorer von SSMS<\/span><\/b><\/p>\n<p>Das Access-Frontend <b>SQLServer_EinstiegVonJetSQLZuTSQL.accdb<\/b> enth&auml;lt die acht Tabellen als Verkn&uuml;pfungen mit den Namen <b>dbo_tblKategorien<\/b>, <b>dbo_tblKunden<\/b> und so weiter. Wie man solche Verkn&uuml;pfungen von Hand oder per VBA anlegt, haben wir im Beitrag <b>SQL Server: Tabellen per VBA verkn&uuml;pfen<\/b> (<b>www.vbentwickler.de\/485<\/b>) gezeigt.<\/p>\n<h2>Das erste SELECT in SSMS<\/h2>\n<p>Ein Abfragefenster &ouml;ffnen wir in SSMS mit <b>Neue Abfrage<\/b>. Wichtig ist die Datenbank, gegen die die Anweisung l&auml;uft: Sie steht in der Auswahlliste links neben dem Ausf&uuml;hren-Schalter. Alternativ stellen wir der Anweisung ein <b>USE Bestellverwaltung_TSQL<\/b> voran. Die folgende Abfrage liefert die ersten drei Kunden, alphabetisch nach Nachnamen sortiert:<\/p>\n<pre>SELECT TOP (3) KundeID, Firma, Nachname, Ort\r\nFROM dbo.tblKunden\r\nORDER BY Nachname;<\/pre>\n<p>Fast alles daran kennen wir aus Access. Neu ist <b>dbo<\/b>: Das ist das Schema, zu dem die Tabelle geh&ouml;rt. Jedes Objekt im SQL Server liegt in einem Schema, und wenn wir nichts anderes angelegt haben, hei&szlig;t es <b>dbo<\/b>. Das Semikolon am Ende empfiehlt Microsoft f&uuml;r jede Anweisung, und wir setzen es hier konsequent. Mit <b>F5<\/b> oder dem Schalter <b>Ausf&uuml;hren<\/b> erscheint das Ergebnis im Ergebnisbereich (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_516_002.png\" alt=\"Das erste SELECT im Abfragefenster von SSMS, darunter das Ergebnis\" width=\"600\" height=\"265,909\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Das erste SELECT im Abfragefenster von SSMS, darunter das Ergebnis<\/span><\/b><\/p>\n<p>Ein Wort zu <b>GO<\/b>: In SSMS-Skripten sto&szlig;en wir st&auml;ndig auf diese Zeile. <b>GO<\/b> ist kein T-SQL-Befehl, sondern ein Trennzeichen f&uuml;r SSMS und das Kommandozeilenwerkzeug <b>sqlcmd<\/b>.<\/p>\n<p>Es teilt ein Skript in einzelne Stapel (Batches), die nacheinander an den Server gehen. Das Skript der Beispieldatenbank nutzt es zum Beispiel, damit die Datenbank angelegt ist, bevor das erste <b>CREATE TABLE<\/b> an sie gerichtet wird. In Pass-Through-Abfragen, die wir weiter unten kennenlernen, geh&ouml;rt <b>GO<\/b> nicht hinein.<\/p>\n<h2>Zeichenketten und Platzhalter<\/h2>\n<p>Der auff&auml;lligste Unterschied zeigt sich schon bei einem Textkriterium. In Access fassen wir Text in doppelte Anf&uuml;hrungszeichen und verwenden <b>*<\/b> und <b>?<\/b> als Platzhalter.<\/p>\n<p>Die Abfrage nach Kunden aus K&ouml;ln, deren Nachname mit S beginnt, lautet in der SQL-Ansicht einer Access-Abfrage so:<\/p>\n<pre>SELECT KundeID, Vorname, Nachname, Ort\r\nFROM dbo_tblKunden\r\nWHERE Ort = \"K&ouml;ln\" AND Nachname Like \"S*\";<\/pre>\n<p>In T-SQL stehen Zeichenketten in einfachen Anf&uuml;hrungszeichen, und die Platzhalter hei&szlig;en <b>%<\/b> f&uuml;r beliebig viele Zeichen und <b>_<\/b> f&uuml;r genau ein Zeichen. Au&szlig;erdem setzen wir vor Texte, die Umlaute oder andere Unicode-Zeichen enthalten k&ouml;nnen, das Pr&auml;fix <b>N<\/b>.<\/p>\n<p>Es kennzeichnet das Literal als Unicode-Text (<b>nvarchar<\/b>) und verhindert, dass ein Zeichen durch die Zeichensatzumsetzung verloren geht. Die T-SQL-Fassung der Abfrage sieht so aus:<\/p>\n<pre>SELECT KundeID, Vorname, Nachname, Ort\r\nFROM dbo.tblKunden\r\nWHERE Ort = N'K&ouml;ln' AND Nachname LIKE N'S%';<\/pre>\n<p>Die doppelten Anf&uuml;hrungszeichen sind in T-SQL nicht verboten, aber sie bedeuten etwas anderes: Bei eingeschaltetem <b>QUOTED_IDENTIFIER<\/b> &#8211; das ist die Voreinstellung in SSMS und beim ODBC-Treiber &#8211; kennzeichnen sie einen Objektnamen, so wie bei Access die eckigen Klammern. Ein <b>&#8220;K&ouml;ln&#8221;<\/b> sucht der Server deshalb als Spaltennamen. Wie die Fehlermeldung dazu aussieht, sehen wir im Abschnitt &uuml;ber Pass-Through-Abfragen.<\/p>\n<p>Ein Apostroph im Text verdoppeln wir. Der Kunde Sean O&#8217;Brien findet sich so:<\/p>\n<pre>SELECT KundeID, Vorname, Nachname\r\nFROM dbo.tblKunden\r\nWHERE Nachname = N'O''Brien';<\/pre>\n<p>Besonders t&uuml;ckisch ist der Platzhalter <b>*<\/b>. Er l&ouml;st keinen Fehler aus, er ist in T-SQL schlicht ein gew&ouml;hnliches Zeichen. Die Abfrage <b>WHERE Nachname LIKE N&#8217;M*&#8217;<\/b> sucht daher nach Nachnamen, die genau auf M* enden, und liefert null Datens&auml;tze, statt Meier und M&uuml;ller zu finden. Wer Abfragen aus Access &uuml;bernimmt, sollte jedes <b>Like<\/b> auf diese Platzhalter hin pr&uuml;fen.<\/p>\n<h2>Datumswerte<\/h2>\n<p>In Access schreiben wir Datumsliterale in Rautezeichen und im amerikanischen Format: <b>#9\/15\/2026#<\/b>. T-SQL kennt diese Schreibweise nicht.<\/p>\n<p>Der Server beantwortet sie mit der Meldung <b>Falsche Syntax in der N&auml;he von &#8220;#&#8221;<\/b>. Ein Datum steht in T-SQL als Zeichenkette in einfachen Anf&uuml;hrungszeichen, und damit es unabh&auml;ngig von den Spracheinstellungen des Servers richtig gelesen wird, schreiben wir es als <b>&#8216;20260915&#8217;<\/b> (Jahr, Monat, Tag ohne Trennzeichen).<\/p>\n<p>Die zweite Falle betrifft die Uhrzeit. Die Spalte <b>Bestelldatum<\/b> in <b>tblBestellungen<\/b> hat den Datentyp <b>datetime2(0)<\/b> und speichert Datum und Uhrzeit. Die Bestellung vom 15. September 2026 ist um 11:30:00 Uhr eingegangen. Eine Abfrage mit Gleichheit auf den Tag findet sie daher nicht, denn <b>&#8216;20260915&#8217;<\/b> bedeutet Mitternacht. Drei Wege, die Bestellungen eines Tages zu z&auml;hlen, vergleicht Listing 1.<\/p>\n<pre>SELECT COUNT(*) FROM dbo.tblBestellungen\r\nWHERE Bestelldatum = '20260915';\r\nSELECT COUNT(*) FROM dbo.tblBestellungen\r\nWHERE Bestelldatum &gt;= '20260915' AND Bestelldatum &lt; '20260916';\r\nSELECT COUNT(*) FROM dbo.tblBestellungen\r\nWHERE CAST(Bestelldatum AS date) = '20260915';<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Drei Wege, die Bestellungen eines Tages zu z&auml;hlen<\/span><\/b><\/p>\n<p>Die erste Abfrage liefert 0, die zweite und die dritte liefern 1. Die zweite Schreibweise, ein halboffenes Intervall, ist die Standardl&ouml;sung: Sie vergleicht das Feld unver&auml;ndert mit Grenzwerten und l&auml;sst dem Server damit alle M&ouml;glichkeiten, einen Index zu nutzen.<\/p>\n<p>Die dritte ist bequemer zu lesen, wandelt aber den Feldinhalt um &#8211; bei anderen Umwandlungen als dem Schnitt auf das Datum kann der Server dann keinen Index mehr verwenden, wie wir im Teil &uuml;ber Indizes sehen werden.<\/p>\n<h2>NULL und das Verketten von Texten<\/h2>\n<p>Mit <b>NULL<\/b> verh&auml;lt sich T-SQL grunds&auml;tzlich wie Access: Ein Vergleich mit <b>NULL<\/b> ist weder wahr noch falsch. Das Kriterium <b>WHERE Firma = NULL<\/b> liefert deshalb nie einen Datensatz, die Frage nach leeren Feldern lautet <b>WHERE Firma IS NULL<\/b>. In der Beispieldatenbank sind bei sechzehn Kunden keine Firmen hinterlegt &#8211; die Privatkunden. Die Abfrage mit <b>= NULL<\/b> z&auml;hlt 0, die Abfrage mit <b>IS NULL<\/b> z&auml;hlt 16.<\/p>\n<p>Interessanter wird es beim Zusammensetzen von Texten. In Access gibt es zwei Operatoren: <b>&#038;<\/b> verkettet und behandelt <b>Null<\/b> als leeren Text, <b>+<\/b> verkettet und gibt <b>Null<\/b> zur&uuml;ck, wenn ein Teil <b>Null<\/b> ist. T-SQL hat nur <b>+<\/b>, und der verh&auml;lt sich wie das <b>+<\/b> in Access. Hinzu kommt die Funktion <b>CONCAT<\/b>, die <b>NULL<\/b> wie einen leeren Text behandelt. Wir wollen Kunden als &#8220;M&uuml;ller (M&uuml;ller B&uuml;robedarf GmbH)&#8221; anzeigen, Privatkunden dagegen nur mit dem Nachnamen. Listing 2 zeigt drei Varianten.<\/p>\n<pre>SELECT TOP (4)\r\n    Nachname + N' (' + Firma + N')'                  AS MitPlus,\r\n    CONCAT(Nachname, N' (', Firma, N')')             AS MitConcat,\r\n    Nachname + ISNULL(N' (' + Firma + N')', N'')     AS Sauber\r\nFROM dbo.tblKunden\r\nORDER BY KundeID;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Drei Varianten, Nachname und Firma zu verketten<\/span><\/b><\/p>\n<p>Bei Privatkunden liefert die erste Spalte <b>NULL<\/b>, die zweite den unsch&ouml;nen Text &#8220;Schmidt ()&#8221; mit leeren Klammern, und erst die dritte Spalte ist richtig: Weil ein <b>+<\/b> mit <b>NULL<\/b> wieder <b>NULL<\/b> ergibt, ist der gesamte Klammerausdruck <b>NULL<\/b>, wenn die Firma fehlt, und <b>ISNULL<\/b> ersetzt ihn durch einen leeren Text. Dieses Muster kennen Access-Entwickler schon, in Access schreiben wir es als <b>Nachname &#038; (&#8221; (&#8221; + Firma + &#8220;)&#8221;)<\/b>.<\/p>\n<h2>Ja\/Nein, Zahlen und Datentypen<\/h2>\n<p>F&uuml;r die Felder unserer Tabellen m&uuml;ssen wir wissen, welcher Access-Datentyp welchem SQL-Server-Typ entspricht. Die wichtigsten Zuordnungen:<\/p>\n<ul>\n<li><b>AutoWert:<\/b> <b>int<\/b> mit <b>IDENTITY<\/b><\/li>\n<li><b>Zahl (Long Integer):<\/b> <b>int<\/b><\/li>\n<li><b>Zahl (Integer):<\/b> <b>smallint<\/b><\/li>\n<li><b>W&auml;hrung:<\/b> <b>money<\/b> oder, besser kontrollierbar, <b>decimal(9,2)<\/b><\/li>\n<li><b>Ja\/Nein:<\/b> <b>bit<\/b><\/li>\n<li><b>Kurzer Text:<\/b> <b>nvarchar(n)<\/b><\/li>\n<li><b>Langer Text:<\/b> <b>nvarchar(max)<\/b><\/li>\n<li><b>Datum\/Uhrzeit:<\/b> <b>date<\/b> f&uuml;r reine Datumswerte, <b>datetime2<\/b> f&uuml;r Datum mit Uhrzeit<\/li>\n<\/ul>\n<p>Die Definition einer Tabelle liest der Server in Systemsichten aus. Die Abfrage aus Listing 3 zeigt die Spalten von <b>tblProdukte<\/b> mit Typ, L&auml;nge und der Angabe, ob <b>NULL<\/b> erlaubt ist.<\/p>\n<pre>SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH AS Laenge, IS_NULLABLE\r\nFROM INFORMATION_SCHEMA.COLUMNS\r\nWHERE TABLE_NAME = N'tblProdukte'\r\nORDER BY ORDINAL_POSITION;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Die Spalten der Tabelle tblProdukte mit Datentyp und NULL-Zul&auml;ssigkeit<\/span><\/b><\/p>\n<p>Das Ergebnis sehen wir in Bild 3.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_516_003.png\" alt=\"Die Spalten von tblProdukte; bei Beschreibung steht die L&auml;nge -1 f&uuml;r nvarchar(max)\" width=\"500\" height=\"304,4693\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Die Spalten von tblProdukte; bei Beschreibung steht die L&auml;nge -1 f&uuml;r nvarchar(max)<\/span><\/b><\/p>\n<p>Das Feld <b>Auslaufartikel<\/b> ist ein <b>bit<\/b>, in Access das Ja\/Nein-Feld. Dort ist <b>Wahr<\/b> der Wert <b>-1<\/b>, in T-SQL ist ein gesetztes <b>bit<\/b> die <b>1<\/b>. Das hat konkrete Folgen: Die Bedingung <b>WHERE Auslaufartikel = -1<\/b>, aus Access gewohnt, liefert in T-SQL keinen Fehler, aber auch keinen Datensatz.<\/p>\n<p>Die Bedingung <b>WHERE Auslaufartikel = True<\/b> scheitert mit dem Fehler <b>Ung&uuml;ltiger Spaltenname &#8220;True&#8221;<\/b>, denn T-SQL kennt kein <b>True<\/b>. Richtig ist <b>WHERE Auslaufartikel = 1<\/b>. Auch <b>IIF(Auslaufartikel, &#8230;)<\/b> funktioniert nicht, weil ein <b>bit<\/b> in T-SQL kein Wahrheitswert ist; dort muss ein Vergleich stehen.<\/p>\n<h2>Funktionen: Was aus Access bleibt<\/h2>\n<p>Viele Funktionen, die wir in Access-Abfragen verwenden, stammen aus VBA und gibt es im SQL Server nicht. Die Datenbank-Engine kennt daf&uuml;r eigene Gegenst&uuml;cke. Eine erste &Uuml;bersicht:<\/p>\n<ul>\n<li><b>Nz:<\/b> <b>ISNULL<\/b> oder <b>COALESCE<\/b>; <b>COALESCE<\/b> akzeptiert mehr als zwei Argumente und ist Standard-SQL<\/li>\n<li><b>Iif:<\/b> <b>IIF<\/b> in der Schreibweise von T-SQL (der Vergleich muss ausdr&uuml;cklich stehen) oder die allgemeinere <b>CASE WHEN &#8230; THEN &#8230; ELSE &#8230; END<\/b>-Anweisung<\/li>\n<li><b>Format:<\/b> <b>FORMAT<\/b> f&uuml;r Zahlen und Datumswerte, bei gro&szlig;en Mengen langsamer als <b>CONVERT<\/b> mit Stilnummer<\/li>\n<li><b>Date\/Now:<\/b> <b>CAST(GETDATE() AS date)<\/b> beziehungsweise <b>GETDATE<\/b> oder <b>SYSDATETIME<\/b><\/li>\n<li><b>Left\/Mid\/Len:<\/b> <b>LEFT<\/b>, <b>SUBSTRING<\/b> und <b>LEN<\/b>; <b>Mid<\/b> entspricht <b>SUBSTRING<\/b> mit Startposition und L&auml;nge<\/li>\n<li><b>InStr:<\/b> <b>CHARINDEX<\/b>; die Parameter stehen in umgekehrter Reihenfolge (gesuchter Text zuerst)<\/li>\n<li><b>DateAdd\/DateDiff:<\/b> <b>DATEADD<\/b> und <b>DATEDIFF<\/b>; der Datumsteil steht ohne Anf&uuml;hrungszeichen, etwa <b>DATEDIFF(DAY, Bestelldatum, Lieferdatum)<\/b><\/li>\n<li><b>Year\/Month\/Day:<\/b> gleichnamige Funktionen<\/li>\n<li><b>DLookup\/DSum\/DCount:<\/b> gibt es nicht; wir ersetzen sie durch Unterabfragen oder Verkn&uuml;pfungen, davon handelt der dritte Teil<\/li>\n<\/ul>\n<p>Ein Beispiel mit drei dieser Funktionen zeigt Listing 4: die ersten vier Produkte mit Beschreibung, Auslauf-Kennzeichen und formatiertem Preis.<\/p>\n<pre>SELECT TOP (4)\r\n    Produkt,\r\n    ISNULL(Beschreibung, N'(keine)')            AS Beschreibung,\r\n    IIF(Auslaufartikel = 1, N'ja', N'nein')     AS Auslauf,\r\n    FORMAT(Einzelpreis, 'N2', 'de-DE')          AS Preis,\r\n    Lagerbestand\r\nFROM dbo.tblProdukte\r\nORDER BY ProduktID;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Die Funktionen ISNULL, IIF und FORMAT in einer Abfrage<\/span><\/b><\/p>\n<p>Das Ergebnis steht in Bild 4. Das dritte Argument von <b>FORMAT<\/b> legt die Kultur fest und damit Dezimalkomma und Tausenderpunkt unabh&auml;ngig von der Spracheinstellung des Servers.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_516_004.png\" alt=\"Die Produktliste mit ISNULL, IIF und FORMAT im Ergebnisraster von SSMS\" width=\"700\" height=\"119,6774\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Die Produktliste mit ISNULL, IIF und FORMAT im Ergebnisraster von SSMS<\/span><\/b><\/p>\n<h2>Warum Access-Abfragen auf SQL-Server-Tabellen scheitern k&ouml;nnen<\/h2>\n<p>Eine Abfrage wie die in Listing 5, die wir in Access f&uuml;r unsere Auswertung der Monatsums&auml;tze 2026 anlegen w&uuml;rden, ist reines Access-SQL auf den verkn&uuml;pften Tabellen.<\/p>\n<pre>SELECT Format([b].[Bestelldatum],\"yyyy-mm\") AS Monat,\r\n       Sum([d].[Menge]*[d].[Einzelpreis]*(1-[d].[Rabatt])) AS Umsatz\r\nFROM dbo_tblBestellungen AS b INNER JOIN dbo_tblBestelldetails AS d\r\n     ON b.BestellungID = d.BestellungID\r\nWHERE b.Bestelldatum &gt;= #1\/1\/2026# AND b.BestellstatusID &lt;&gt; 5\r\nGROUP BY Format([b].[Bestelldatum],\"yyyy-mm\")\r\nORDER BY Format([b].[Bestelldatum],\"yyyy-mm\");<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Monatsums&auml;tze 2026 in Access-SQL<\/span><\/b><\/p>\n<p>Sie steht als <b>qryMonatsumsatzJet<\/b> im Frontend der Beispieldatenbank.<\/p>\n<p>Gegen eine reine Access-Tabelle w&uuml;rde die Abfrage sofort funktionieren. Auf den verkn&uuml;pften SQL-Server-Tabellen &ouml;ffnet sie sich mit einer Fehlermeldung (siehe Bild 5).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_516_005.png\" alt=\"Access &ouml;ffnet die Abfrage qryMonatsumsatzJet auf den verkn&uuml;pften Tabellen nicht\" width=\"500\" height=\"344,2624\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Access &ouml;ffnet die Abfrage qryMonatsumsatzJet auf den verkn&uuml;pften Tabellen nicht<\/span><\/b><\/p>\n<p>Der Grund liegt in den Datentypen: Access bindet die Spalte <b>Bestelldatum<\/b>, die im Server ein <b>datetime2(0)<\/b> ist, als <b>Datum\/Uhrzeit, erweitert<\/b> ein, und mit diesem Typ kommt die Funktion <b>Format<\/b> in einem Gruppierungsausdruck nicht zurecht.<\/p>\n<p>Ersetzen wir sie durch <b>Year<\/b> und <b>Month<\/b>, l&auml;uft die Abfrage. Auch die Dezimalfelder bergen &Uuml;berraschungen: Die Summe <b>Sum(Menge*Einzelpreis*(1-Rabatt))<\/b> &uuml;ber alle Positionen ohne Gruppierung scheitert mit der Meldung <b>Staffelung des Dezimalwerts f&uuml;hrte zu Datenk&uuml;rzung<\/b>, und erst mit <b>CCur<\/b> um den Ausdruck herum liefert Access ein Ergebnis. Solche Umwege kosten Zeit, und sie sind von Fall zu Fall verschieden.<\/p>\n<p>Das ist die Stelle, an der sich T-SQL lohnt: Statt die Abfrage so lange zu verbiegen, bis Access sie versteht, schicken wir sie an den Server, der sie ohne Umwege ausf&uuml;hrt.<\/p>\n<h2>Pass-Through-Abfragen in Access<\/h2>\n<p>Eine <b>Pass-Through-Abfrage<\/b> reicht ihren Text unver&auml;ndert an den Server weiter. Access pr&uuml;ft nichts, &uuml;bersetzt nichts, es nimmt nur das Ergebnis entgegen. Wir legen sie &uuml;ber <b>Erstellen\/Abfrageentwurf<\/b> an, schlie&szlig;en das Dialogfeld <b>Tabelle anzeigen<\/b> und w&auml;hlen im Tab <b>Abfrageentwurf<\/b> den Schalter <b>Pass-Through<\/b>. Danach tragen wir die T-SQL-Anweisung in die SQL-Ansicht ein. F&uuml;r die Monatsums&auml;tze lautet sie wie in Listing 6.<\/p>\n<pre>SELECT FORMAT(b.Bestelldatum, 'yyyy-MM') AS Monat,\r\n       SUM(d.Menge * d.Einzelpreis * (1 - d.Rabatt)) AS Umsatz\r\nFROM dbo.tblBestellungen b\r\n     INNER JOIN dbo.tblBestelldetails d ON d.BestellungID = b.BestellungID\r\nWHERE b.Bestelldatum &gt;= '20260101' AND b.BestellstatusID &lt;&gt; 5\r\nGROUP BY FORMAT(b.Bestelldatum, 'yyyy-MM')\r\nORDER BY Monat;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Monatsums&auml;tze 2026 in T-SQL<\/span><\/b><\/p>\n<p>Damit Access wei&szlig;, wohin es die Anweisung schicken soll, m&uuml;ssen wir die Eigenschaft <b>ODBC-Verbindung<\/b> im Eigenschaftenblatt der Abfrage f&uuml;llen (siehe Bild 6).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_516_006.png\" alt=\"Die Pass-Through-Abfrage ptMonatsumsatz im Entwurf, mit der Eigenschaft ODBC-Verbindung im Eigenschaftenblatt\" width=\"700\" height=\"259,5694\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Die Pass-Through-Abfrage ptMonatsumsatz im Entwurf, mit der Eigenschaft ODBC-Verbindung im Eigenschaftenblatt<\/span><\/b><\/p>\n<p>Sie enth&auml;lt Treiber, Server, Datenbank und die Art der Anmeldung, in unserem Fall wie in Listing 7.<\/p>\n<pre>ODBC;DRIVER={ODBC Driver 18 for SQL Server};SERVER=.\\SQLEXPRESS;\r\nDATABASE=Bestellverwaltung_TSQL;Trusted_Connection=Yes;TrustServerCertificate=Yes;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Die ODBC-Verbindungszeichenfolge f&uuml;r SQL Server Express<\/span><\/b><\/p>\n<p>In der Eigenschaft steht die Zeichenfolge in einer einzigen Zeile. <b>Trusted_Connection=Yes<\/b> meldet uns mit dem Windows-Konto an, <b>TrustServerCertificate=Yes<\/b> akzeptiert das Zertifikat des lokalen Servers. Beim Treiber 18 ist die Verschl&uuml;sselung standardm&auml;&szlig;ig eingeschaltet, ohne diese Angabe scheitert die Verbindung bei einem Server ohne vertrauensw&uuml;rdiges Zertifikat. Bei einem Server im Produktivbetrieb geh&ouml;rt ein g&uuml;ltiges Zertifikat auf den Server, nicht die Abk&uuml;rzung in die Zeichenfolge.<\/p>\n<p>Die Abfrage liefert jetzt die Monatsums&auml;tze als normales Datenblatt (siehe Bild 7).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_516_007.png\" alt=\"Das Ergebnis der Pass-Through-Abfrage ptMonatsumsatz\" width=\"349,9999\" height=\"346,6019\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Das Ergebnis der Pass-Through-Abfrage ptMonatsumsatz<\/span><\/b><\/p>\n<p>F&uuml;r die Arbeit mit Pass-Through-Abfragen sollten wir zwei Eigenschaften im Hinterkopf behalten. Das Ergebnis ist immer schreibgesch&uuml;tzt, weil Access keine Verbindung zu einer Tabelle hat, in die es zur&uuml;ckschreiben k&ouml;nnte.<\/p>\n<p>Und es gibt keine Parameter: Wer Kriterien einf&uuml;gen m&ouml;chte, muss den Text der Anweisung vor dem Ausf&uuml;hren zusammensetzen. Genau das erledigen wir im n&auml;chsten Abschnitt in VBA.<\/p>\n<p>F&uuml;r Aktionsabfragen, die nichts zur&uuml;ckliefern (<b>UPDATE<\/b>, <b>DELETE<\/b>), setzen wir die Eigenschaft <b>Datens&auml;tze zur&uuml;ckgeben<\/b> auf <b>Nein<\/b>.<\/p>\n<h2>T-SQL aus VBA zusammensetzen<\/h2>\n<p>In VBA erzeugen wir Pass-Through-Abfragen mit einem tempor&auml;ren <b>QueryDef<\/b> ohne Namen. Das Muster steckt in wenigen kleinen Funktionen im Modul <b>mdlTSQLEinstiegBeispiele<\/b>.<\/p>\n<p>Zuerst die Hilfsfunktionen f&uuml;r Literale, die die Unterschiede aus den vorigen Abschnitten in sich aufnehmen: <b>SqlText<\/b> verdoppelt Apostrophe, setzt das <b>N<\/b>-Pr&auml;fix und macht aus <b>Null<\/b> das T-SQL-Schl&uuml;sselwort <b>NULL<\/b>, <b>SqlDatum<\/b> liefert ein sprachunabh&auml;ngiges Datumsliteral (siehe Listing 8).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>SqlText(varWert<span style=\"color:blue;\"> As Variant<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">If <\/span>IsNull(varWert)<span style=\"color:blue;\"> Then<\/span>\r\n        SqlText = \"NULL\"\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        SqlText = \"N'\" & <span style=\"color:blue;\">Replace<\/span>(CStr(varWert), \"'\", \"''\") & \"'\"\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span>\r\n<span style=\"color:blue;\">Public Function <\/span>SqlDatum(varWert<span style=\"color:blue;\"> As Variant<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">If <\/span>IsNull(varWert)<span style=\"color:blue;\"> Then<\/span>\r\n        SqlDatum = \"NULL\"\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        SqlDatum = \"'\" & Format(varWert, \"yyyymmdd\") & \"'\"\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Die Hilfsfunktionen SqlText und SqlDatum<\/span><\/b><\/p>\n<p>Beide Funktionen nehmen einen <b>Variant<\/b> entgegen, damit auch ein leeres Feld aus einem Recordset unbeschadet durchkommt. Die Funktion <b>SqlDatum<\/b> gibt bewusst nur das Datum zur&uuml;ck; wer die Uhrzeit braucht, nimmt die Schwesterfunktion <b>SqlDatumZeit<\/b>, die ein Literal im ISO-Format <b>&#8216;2026-09-05T14:30:05&#8217;<\/b> liefert. Mit ihnen bauen wir den Text einer Pass-Through-Abfrage und f&uuml;hren ihn &uuml;ber die zweite Gruppe von Funktionen aus, die in Listing 9 stehen.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>PassThroughOeffnen(strSQL<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>qdf<span style=\"color:blue;\"> As <\/span>DAO.QueryDef\r\n    <span style=\"color:blue;\">Set<\/span> qdf = CurrentDb.CreateQueryDef(\"\")\r\n    qdf.Connect = cstrVerbindung\r\n    qdf.SQL = strSQL\r\n    qdf.ReturnsRecords = <span style=\"color:blue;\">True<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> PassThroughOeffnen = qdf.OpenRecordset(dbOpenSnapshot, dbSQLPassThrough)\r\n<span style=\"color:blue;\">End Function<\/span>\r\n<span style=\"color:blue;\">Public Function <\/span>PassThroughWert(strSQL<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Variant<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Set<\/span> rst = PassThroughOeffnen(strSQL)\r\n    <span style=\"color:blue;\">If <\/span>rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n        PassThroughWert = Null\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        PassThroughWert = rst.Fields(0).Value\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    rst.Close\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 9: PassThroughOeffnen und PassThroughWert<\/span><\/b><\/p>\n<p><b>PassThroughOeffnen<\/b> legt eine <b>QueryDef<\/b> mit dem Namen <b>&#8220;&#8221;<\/b> an. Das ist in DAO der Hinweis, dass die Abfrage nur im Arbeitsspeicher existiert und nicht in der Datenbank gespeichert wird.<\/p>\n<p>Die Eigenschaft <b>Connect<\/b> nimmt die Verbindungszeichenfolge aus der Konstante <b>cstrVerbindung<\/b> im Kopf des Moduls auf, die wir bei Bedarf auf den eigenen Server anpassen. <b>dbSQLPassThrough<\/b> im Aufruf von <b>OpenRecordset<\/b> stellt sicher, dass Access den Text nicht doch selbst verarbeitet. <b>PassThroughWert<\/b> ist die kleine Schwester: Sie liefert nur den ersten Wert der ersten Zeile und eignet sich f&uuml;r Z&auml;hlungen und Nachschlagewerte.<\/p>\n<p>Mit diesen Bausteinen schreiben wir Funktionen wie <b>BestellungenEinesTages<\/b> und <b>KundenZaehlen<\/b> aus Listing 10. Die erste z&auml;hlt die Bestellungen eines Tages und nutzt das halboffene Intervall aus dem Abschnitt &uuml;ber Datumswerte.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>BestellungenEinesTages(datTag<span style=\"color:blue;\"> As Date<\/span>)<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n    strSQL = \"SELECT COUNT(*) FROM dbo.tblBestellungen WHERE Bestelldatum &gt;= \" & SqlDatum(datTag) & _\r\n             \" AND Bestelldatum &lt; \" & SqlDatum(datTag + 1)\r\n    BestellungenEinesTages = Nz(PassThroughWert(strSQL), 0)\r\n<span style=\"color:blue;\">End Function<\/span>\r\n<span style=\"color:blue;\">Public Function <\/span>KundenZaehlen(strAnfang<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n    strSQL = \"SELECT COUNT(*) FROM dbo.tblKunden WHERE Nachname LIKE \" & SqlText(strAnfang & \"%\")\r\n    KundenZaehlen = Nz(PassThroughWert(strSQL), 0)\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 10: BestellungenEinesTages und KundenZaehlen<\/span><\/b><\/p>\n<p>Im Direktbereich liefert <b>Debug.Print BestellungenEinesTages(#9\/15\/2026#)<\/b> die 1, <b>Debug.Print KundenZaehlen(&#8220;O&#8217;Brien&#8221;)<\/b> ebenfalls die 1 &#8211; der Apostroph geht dank <b>SqlText<\/b> ohne Beanstandung durch.<\/p>\n<p>Ein Stolperstein bleibt: Das Prozentzeichen im Suchbegriff wirkt als Platzhalter. <b>KundenZaehlen(&#8220;%&#8221;)<\/b> z&auml;hlt alle zweiunddrei&szlig;ig Kunden. F&uuml;r eine Suchfunktion, die Benutzereingaben entgegennimmt, m&uuml;ssen wir diese Zeichen entweder maskieren oder die Suche an eine gespeicherte Prozedur mit Parametern &uuml;bergeben, wie wir es im Teil &uuml;ber Prozeduren zeigen.<\/p>\n<p>Das gilt umso mehr, als eine zusammengesetzte Anweisung generell angreifbar ist: Wer Eingaben ungepr&uuml;ft in den SQL-Text &uuml;bernimmt, &ouml;ffnet die T&uuml;r f&uuml;r SQL-Injection. <b>SqlText<\/b> entsch&auml;rft das f&uuml;r Text, indem es Apostrophe verdoppelt, ersetzt aber keine Parameter. F&uuml;r alles, was Benutzer frei eingeben, sind gespeicherte Prozeduren mit Parametern die bessere Wahl (siehe die Beitr&auml;ge <b>ADODB: Gespeicherte Prozeduren ausf&uuml;hren<\/b> (<b>www.vbentwickler.de\/503<\/b>), und <b>ADODB: Gespeicherte Prozeduren einfach aufrufen<\/b> (<b>www.vbentwickler.de\/505<\/b>).<\/p>\n<h2>Fehlermeldungen des Servers lesen<\/h2>\n<p>L&auml;uft eine Pass-Through-Abfrage in einen Fehler, meldet VBA nur: <b>ODBC-Aufruf fehlgeschlagen.<\/b> Das ist die Antwort von Access, nicht die des Servers. Die eigentliche Meldung steckt in der Auflistung <b>DBEngine.Errors<\/b>. Die Funktion in Listing 11 sammelt sie ein, schneidet die Pr&auml;fixe des Treibers in eckigen Klammern ab und gibt die Meldungen als Text zur&uuml;ck:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>PassThroughFehler(strSQL<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>varDummy<span style=\"color:blue;\"> As Variant<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>errFehler<span style=\"color:blue;\"> As <\/span>DAO.Error\r\n    <span style=\"color:blue;\">Dim <\/span>strText<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> ErrHandler\r\n    varDummy = PassThroughWert(strSQL)\r\n    <span style=\"color:blue;\">Exit Function<\/span>\r\nErrHandler:\r\n    For Each errFehler In DBEngine.Errors\r\n        strText = errFehler.Description\r\n        <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Left<\/span>(strText, 1) = \"[\"\r\n            strText = <span style=\"color:blue;\">Mid<\/span>(strText, <span style=\"color:blue;\">InStr<\/span>(strText, \"]\") + 1)\r\n        <span style=\"color:blue;\">Loop<\/span>\r\n        PassThroughFehler = PassThroughFehler & strText & \" \"\r\n    <span style=\"color:blue;\">Next<\/span> errFehler\r\n    PassThroughFehler = <span style=\"color:blue;\">Trim<\/span>(PassThroughFehler)\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(PassThroughFehler) = 0<span style=\"color:blue;\"> Then<\/span> PassThroughFehler = Err.Description\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 11: PassThroughFehler liefert die Meldungen des Servers<\/span><\/b><\/p>\n<p>Damit lassen sich die Stolpersteine dieses Beitrags vorf&uuml;hren: Wir &uuml;bergeben der Funktion Anweisungen mit Access-Syntax und lassen uns die Antworten des Servers im Direktbereich zeigen. Listing 12 &uuml;bergibt dazu vier Anweisungen mit Access-Syntax.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>FehlermeldungenZeigen()\r\n    <span style=\"color:blue;\">Debug.Print<\/span> PassThroughFehler( _\r\n        \"SELECT COUNT(*) FROM dbo.tblBestellungen WHERE Bestelldatum &gt; #9\/15\/2026#\")\r\n    <span style=\"color:blue;\">Debug.Print<\/span> PassThroughFehler(\"SELECT Format(Einzelpreis, \"\"0.00\"\") FROM dbo.tblProdukte\")\r\n    <span style=\"color:blue;\">Debug.Print<\/span> PassThroughFehler(\"SELECT Nz(Beschreibung, 'x') FROM dbo.tblProdukte\")\r\n    <span style=\"color:blue;\">Debug.Print<\/span> PassThroughFehler( _\r\n        \"SELECT COUNT(*) FROM dbo.tblProdukte WHERE Auslaufartikel = True\")\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 12: Die Prozedur FehlermeldungenZeigen &uuml;bergibt dem Server Access-Syntax<\/span><\/b><\/p>\n<p>Die Antworten stehen in Bild 8. Die Meldungen sind deutlich genauer als das, was Access von sich aus zeigt: <b>Falsche Syntax in der N&auml;he von &#8220;#&#8221;<\/b>, <b>Ung&uuml;ltiger Spaltenname &#8220;0.00&#8221;<\/b>, <b>Nz wird nicht als Name einer integrierten Funktion erkannt<\/b> und <b>Ung&uuml;ltiger Spaltenname &#8220;True&#8221;<\/b>. Hinter dem ersten und dem vierten Fehler stecken die Gewohnheiten, die wir aus Access mitbringen. Beim zweiten Fehler greift die Regel, dass doppelte Anf&uuml;hrungszeichen einen Objektnamen kennzeichnen &#8211; der Server sucht eine Spalte namens <b>0.00<\/b>.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_516_008.png\" alt=\"Die Fehlermeldungen des Servers nach dem Aufruf von FehlermeldungenZeigen im Direktbereich\" width=\"700\" height=\"95,27776\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Die Fehlermeldungen des Servers nach dem Aufruf von FehlermeldungenZeigen im Direktbereich<\/span><\/b><\/p>\n<h2>Das Testmodul<\/h2>\n<p>Alle Beispiele des Beitrags laufen im Modul <b>mdlTSQLEinstiegBeispiele<\/b>. Damit Text und Beispieldatenbank &uuml;bereinstimmen, gibt es das Modul <b>mdlTSQLEinstiegTests<\/b>. Es ruft jede Funktion mit echten Werten auf und vergleicht das Ergebnis mit dem erwarteten. Die Hilfsprozedur <b>Pruefe<\/b> aus Listing 13 vergleicht beide Werte als Text und protokolliert das Ergebnis, daneben steht ein typischer Test.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Pruefe(strBezeichnung<span style=\"color:blue;\"> As String<\/span>, varIst<span style=\"color:blue;\"> As Variant<\/span>, varSoll<span style=\"color:blue;\"> As Variant<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>strIst<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strSoll<span style=\"color:blue;\"> As String<\/span>\r\n    strIst = TextFassung(varIst)\r\n    strSoll = TextFassung(varSoll)\r\n    mlngTests = mlngTests + 1\r\n    <span style=\"color:blue;\">If <\/span>StrComp(strIst, strSoll, vbBinaryCompare) = 0<span style=\"color:blue;\"> Then<\/span>\r\n        Protokoll \"OK     \" & strBezeichnung\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        mlngFehler = mlngFehler + 1\r\n        Protokoll \"FEHLER \" & strBezeichnung & \": Ist &lt;\" & strIst & \"&gt;, Soll &lt;\" & strSoll & \"&gt;\"\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Public Sub <\/span>TestSqlText()\r\n    Pruefe \"SqlText einfach\", SqlText(\"Schmidt\"), \"N'Schmidt'\"\r\n    Pruefe \"SqlText Apostroph\", SqlText(\"O'Brien\"), \"N'O''Brien'\"\r\n    Pruefe \"SqlText Null\", SqlText(Null), \"NULL\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 13: Die Hilfsprozedur Pruefe und ein Test f&uuml;r SqlText<\/span><\/b><\/p>\n<p>Die Einstiegsprozedur <b>AlleTestsAusfuehren<\/b> ruft alle Testprozeduren nacheinander auf und schreibt zum Schluss eine Bilanz in den Direktbereich (siehe Bild 9).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_516_009.png\" alt=\"Das Testprotokoll von AlleTestsAusfuehren im Direktbereich\" width=\"450,0003\" height=\"588,293\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Das Testprotokoll von AlleTestsAusfuehren im Direktbereich<\/span><\/b><\/p>\n<p>Die Tests pr&uuml;fen unter anderem auch, dass die Abfrage mit Gleichheit auf den Tag nichts findet, dass <b>LIKE N&#8217;M*&#8217;<\/b> null Datens&auml;tze liefert und dass die Syntax aus Access tats&auml;chlich zu Fehlern f&uuml;hrt. F&uuml;r die Tests ben&ouml;tigen wir die Datenbank <b>Bestellverwaltung_TSQL<\/b> auf der Instanz <b>.SQLEXPRESS<\/b> und die verkn&uuml;pfte Tabelle <b>dbo_tblKunden<\/b>.<\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>T-SQL ist kein fremder Dialekt, sondern ein naher Verwandter des Access-SQL, der sich an wenigen, aber einschneidenden Stellen unterscheidet: Zeichenketten in einfachen Anf&uuml;hrungszeichen mit <b>N<\/b>-Pr&auml;fix, Platzhalter <b>%<\/b> und <b>_<\/b>, Datumsliterale als <b>&#8216;20260915&#8217;<\/b>, <b>bit<\/b> mit der <b>1<\/b> statt <b>-1<\/b> und ein eigener Satz an Funktionen.<\/p>\n<p>Pass-Through-Abfragen bringen T-SQL direkt in Access und umgehen die &Uuml;bersetzung durch den ODBC-Treiber, die bei <b>datetime2<\/b> und <b>decimal<\/b> an ihre Grenzen st&ouml;&szlig;t. Die Hilfsfunktionen <b>SqlText<\/b> und <b>SqlDatum<\/b> sorgen daf&uuml;r, dass aus VBA zusammengesetzte Anweisungen den Unterschieden gerecht werden.<\/p>\n<p>Im n&auml;chsten Teil der Reihe, <b>SELECT in der Praxis<\/b>, nehmen wir uns die Abfragen vor, die wir t&auml;glich brauchen: verschiedene <b>JOIN<\/b>-Typen, <b>GROUP BY<\/b> und <b>HAVING<\/b>, <b>TOP<\/b> und <b>OFFSET\/FETCH<\/b> und die Gegenst&uuml;cke zu den Access-Funktionen, die wir hier nur gestreift haben. Wer vorab mit den gespeicherten Prozeduren aus Access arbeiten will, findet die passenden Beitr&auml;ge unter <b>ADODB: Gespeicherte Prozeduren ausf&uuml;hren <\/b>(<b>www.vbentwickler.de\/503<\/b>), <b>ADODB: Access-Wrapper f&uuml;r gespeicherte Prozeduren <\/b>(<b>www.vbentwickler.de\/505<\/b>) und <b>ADODB: Formulare mit gespeicherten Prozeduren <\/b>(<b>www.vbentwickler.de\/506<\/b>).<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>Bestellverwaltung_TSQL.sql<\/p>\n<p>SQLServer_EinstiegVonJetSQLZuTSQL.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/424859FB-F05C-4284-B622-6BBF245672FC\/vbe_516.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Die Abfrage l&auml;uft in Access seit Jahren fehlerfrei &#8211; bis die Tabellen auf den SQL Server umziehen. Pl&ouml;tzlich liefert Format im Gruppierungsausdruck eine Fehlermeldung, Like &#8220;M*&#8221; findet keinen einzigen Datensatz, und ein Aufruf von Nz endet mit der Meldung, der Server kenne diese Funktion nicht. Wer Access mit einem SQL Server als Backend betreibt, kommt fr&uuml;her oder sp&auml;ter nicht mehr um T-SQL herum, die Abfragesprache des Servers. Der erste Teil dieser Reihe zeigt, wo sich T-SQL von dem SQL unterscheidet, das wir aus Access kennen, und wie wir T-SQL direkt aus Access heraus ausf&uuml;hren.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662026,66042026,44000023,44000006,44000028],"tags":[],"yst_prominent_words":[],"class_list":["post-55000516","post","type-post","status-publish","format-standard","hentry","category-662026","category-66042026","category-PowerApps","category-SQL_Server_und_Co","category-Word_programmieren"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"Die Abfrage l\u00e4uft in Access seit Jahren fehlerfrei - bis die Tabellen auf den SQL Server umziehen. Pl\u00f6tzlich liefert Format im Gruppierungsausdruck eine Fehlermeldung, Like &quot;M*&quot; findet keinen einzigen Datensatz, und ein Aufruf von Nz endet mit der Meldung, der Server kenne diese Funktion nicht. Wer Access mit einem SQL Server als Backend betreibt, kommt fr\u00fcher oder sp\u00e4ter nicht mehr um T-SQL herum, die Abfragesprache des Servers. Der erste Teil dieser Reihe zeigt, wo sich T-SQL von dem SQL unterscheidet, das wir aus Access kennen, und wie wir T-SQL direkt aus Access heraus ausf\u00fchren.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Andr\u00e9 Minhorst\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Visual Basic Entwickler - Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"T-SQL, Teil 1: Von Jet-SQL zu T-SQL - Visual Basic Entwickler\" \/>\n\t\t<meta property=\"og:description\" content=\"Die Abfrage l\u00e4uft in Access seit Jahren fehlerfrei - bis die Tabellen auf den SQL Server umziehen. Pl\u00f6tzlich liefert Format im Gruppierungsausdruck eine Fehlermeldung, Like &quot;M*&quot; findet keinen einzigen Datensatz, und ein Aufruf von Nz endet mit der Meldung, der Server kenne diese Funktion nicht. Wer Access mit einem SQL Server als Backend betreibt, kommt fr\u00fcher oder sp\u00e4ter nicht mehr um T-SQL herum, die Abfragesprache des Servers. Der erste Teil dieser Reihe zeigt, wo sich T-SQL von dem SQL unterscheidet, das wir aus Access kennen, und wie wir T-SQL direkt aus Access heraus ausf\u00fchren.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-10-13T20:20:14+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"-001-11-30T00:00:00+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"T-SQL, Teil 1: Von Jet-SQL zu T-SQL - Visual Basic Entwickler\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Die Abfrage l\u00e4uft in Access seit Jahren fehlerfrei - bis die Tabellen auf den SQL Server umziehen. Pl\u00f6tzlich liefert Format im Gruppierungsausdruck eine Fehlermeldung, Like &quot;M*&quot; findet keinen einzigen Datensatz, und ein Aufruf von Nz endet mit der Meldung, der Server kenne diese Funktion nicht. Wer Access mit einem SQL Server als Backend betreibt, kommt fr\u00fcher oder sp\u00e4ter nicht mehr um T-SQL herum, die Abfragesprache des Servers. Der erste Teil dieser Reihe zeigt, wo sich T-SQL von dem SQL unterscheidet, das wir aus Access kennen, und wie wir T-SQL direkt aus Access heraus ausf\u00fchren.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#blogposting\",\"name\":\"T-SQL, Teil 1: Von Jet-SQL zu T-SQL - Visual Basic Entwickler\",\"headline\":\"T-SQL, Teil 1: Von Jet-SQL zu T-SQL\",\"author\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"..\\\/fileadmin\\\/_temp_\\\/2026_04\\\/pic_516_001.png\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#articleImage\"},\"datePublished\":\"2026-08-01T00:00:00+00:00\",\"dateModified\":\"-0001-11-30T00:00:00+00:00\",\"inLanguage\":\"de-DE\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#webpage\"},\"articleSection\":\"2026, 4\\\/2026, PowerApps, SQL Server und Co., Word programmieren\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/vbentwickler.de\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/#listItem\",\"name\":\"2026\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/#listItem\",\"position\":2,\"name\":\"2026\",\"item\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/4\\\/2026\\\/#listItem\",\"name\":\"4\\\/2026\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/4\\\/2026\\\/#listItem\",\"position\":3,\"name\":\"4\\\/2026\",\"item\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/4\\\/2026\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#listItem\",\"name\":\"T-SQL, Teil 1: Von Jet-SQL zu T-SQL\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/#listItem\",\"name\":\"2026\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#listItem\",\"position\":4,\"name\":\"T-SQL, Teil 1: Von Jet-SQL zu T-SQL\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/4\\\/2026\\\/#listItem\",\"name\":\"4\\\/2026\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#organization\",\"name\":\"Datenbankentwickler\",\"description\":\"Das Magazin f\\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/cropped-header_vbe-1.png\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#organizationLogo\",\"width\":664,\"height\":225},\"image\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#organizationLogo\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/\",\"name\":\"Andr\\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Andr\\u00e9 Minhorst\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#webpage\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/\",\"name\":\"T-SQL, Teil 1: Von Jet-SQL zu T-SQL - Visual Basic Entwickler\",\"description\":\"Die Abfrage l\\u00e4uft in Access seit Jahren fehlerfrei - bis die Tabellen auf den SQL Server umziehen. Pl\\u00f6tzlich liefert Format im Gruppierungsausdruck eine Fehlermeldung, Like \\\"M*\\\" findet keinen einzigen Datensatz, und ein Aufruf von Nz endet mit der Meldung, der Server kenne diese Funktion nicht. Wer Access mit einem SQL Server als Backend betreibt, kommt fr\\u00fcher oder sp\\u00e4ter nicht mehr um T-SQL herum, die Abfragesprache des Servers. Der erste Teil dieser Reihe zeigt, wo sich T-SQL von dem SQL unterscheidet, das wir aus Access kennen, und wie wir T-SQL direkt aus Access heraus ausf\\u00fchren.\",\"inLanguage\":\"de-DE\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\"},\"datePublished\":\"2026-08-01T00:00:00+00:00\",\"dateModified\":\"-0001-11-30T00:00:00+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#website\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/\",\"name\":\"Datenbankentwickler\",\"description\":\"Das Magazin f\\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.\",\"inLanguage\":\"de-DE\",\"publisher\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"T-SQL, Teil 1: Von Jet-SQL zu T-SQL - Visual Basic Entwickler","description":"Die Abfrage l\u00e4uft in Access seit Jahren fehlerfrei - bis die Tabellen auf den SQL Server umziehen. Pl\u00f6tzlich liefert Format im Gruppierungsausdruck eine Fehlermeldung, Like \"M*\" findet keinen einzigen Datensatz, und ein Aufruf von Nz endet mit der Meldung, der Server kenne diese Funktion nicht. Wer Access mit einem SQL Server als Backend betreibt, kommt fr\u00fcher oder sp\u00e4ter nicht mehr um T-SQL herum, die Abfragesprache des Servers. Der erste Teil dieser Reihe zeigt, wo sich T-SQL von dem SQL unterscheidet, das wir aus Access kennen, und wie wir T-SQL direkt aus Access heraus ausf\u00fchren.","canonical_url":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#blogposting","name":"T-SQL, Teil 1: Von Jet-SQL zu T-SQL - Visual Basic Entwickler","headline":"T-SQL, Teil 1: Von Jet-SQL zu T-SQL","author":{"@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author"},"publisher":{"@id":"https:\/\/vbentwickler.de\/#organization"},"image":{"@type":"ImageObject","url":"..\/fileadmin\/_temp_\/2026_04\/pic_516_001.png","@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#articleImage"},"datePublished":"2026-08-01T00:00:00+00:00","dateModified":"-0001-11-30T00:00:00+00:00","inLanguage":"de-DE","mainEntityOfPage":{"@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#webpage"},"isPartOf":{"@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#webpage"},"articleSection":"2026, 4\/2026, PowerApps, SQL Server und Co., Word programmieren"},{"@type":"BreadcrumbList","@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/#listItem","position":1,"name":"Home","item":"https:\/\/vbentwickler.de\/","nextItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/#listItem","name":"2026"}},{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/#listItem","position":2,"name":"2026","item":"https:\/\/vbentwickler.de\/category\/2026\/","nextItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/#listItem","name":"4\/2026"},"previousItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/#listItem","position":3,"name":"4\/2026","item":"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/","nextItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#listItem","name":"T-SQL, Teil 1: Von Jet-SQL zu T-SQL"},"previousItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/#listItem","name":"2026"}},{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#listItem","position":4,"name":"T-SQL, Teil 1: Von Jet-SQL zu T-SQL","previousItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/#listItem","name":"4\/2026"}}]},{"@type":"Organization","@id":"https:\/\/vbentwickler.de\/#organization","name":"Datenbankentwickler","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.","url":"https:\/\/vbentwickler.de\/","logo":{"@type":"ImageObject","url":"https:\/\/vbentwickler.de\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png","@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#organizationLogo","width":664,"height":225},"image":{"@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#organizationLogo"}},{"@type":"Person","@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author","url":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","width":96,"height":96,"caption":"Andr\u00e9 Minhorst"}},{"@type":"WebPage","@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#webpage","url":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/","name":"T-SQL, Teil 1: Von Jet-SQL zu T-SQL - Visual Basic Entwickler","description":"Die Abfrage l\u00e4uft in Access seit Jahren fehlerfrei - bis die Tabellen auf den SQL Server umziehen. Pl\u00f6tzlich liefert Format im Gruppierungsausdruck eine Fehlermeldung, Like \"M*\" findet keinen einzigen Datensatz, und ein Aufruf von Nz endet mit der Meldung, der Server kenne diese Funktion nicht. Wer Access mit einem SQL Server als Backend betreibt, kommt fr\u00fcher oder sp\u00e4ter nicht mehr um T-SQL herum, die Abfragesprache des Servers. Der erste Teil dieser Reihe zeigt, wo sich T-SQL von dem SQL unterscheidet, das wir aus Access kennen, und wie wir T-SQL direkt aus Access heraus ausf\u00fchren.","inLanguage":"de-DE","isPartOf":{"@id":"https:\/\/vbentwickler.de\/#website"},"breadcrumb":{"@id":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/#breadcrumblist"},"author":{"@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author"},"creator":{"@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author"},"datePublished":"2026-08-01T00:00:00+00:00","dateModified":"-0001-11-30T00:00:00+00:00"},{"@type":"WebSite","@id":"https:\/\/vbentwickler.de\/#website","url":"https:\/\/vbentwickler.de\/","name":"Datenbankentwickler","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.","inLanguage":"de-DE","publisher":{"@id":"https:\/\/vbentwickler.de\/#organization"}}]},"og:locale":"de_DE","og:site_name":"Visual Basic Entwickler - Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.","og:type":"article","og:title":"T-SQL, Teil 1: Von Jet-SQL zu T-SQL - Visual Basic Entwickler","og:description":"Die Abfrage l\u00e4uft in Access seit Jahren fehlerfrei - bis die Tabellen auf den SQL Server umziehen. Pl\u00f6tzlich liefert Format im Gruppierungsausdruck eine Fehlermeldung, Like &quot;M*&quot; findet keinen einzigen Datensatz, und ein Aufruf von Nz endet mit der Meldung, der Server kenne diese Funktion nicht. Wer Access mit einem SQL Server als Backend betreibt, kommt fr\u00fcher oder sp\u00e4ter nicht mehr um T-SQL herum, die Abfragesprache des Servers. Der erste Teil dieser Reihe zeigt, wo sich T-SQL von dem SQL unterscheidet, das wir aus Access kennen, und wie wir T-SQL direkt aus Access heraus ausf\u00fchren.","og:url":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/","og:image":"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png","og:image:secure_url":"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png","article:published_time":"2026-10-13T20:20:14+00:00","article:modified_time":"-001-11-30T00:00:00+00:00","twitter:card":"summary_large_image","twitter:title":"T-SQL, Teil 1: Von Jet-SQL zu T-SQL - Visual Basic Entwickler","twitter:description":"Die Abfrage l\u00e4uft in Access seit Jahren fehlerfrei - bis die Tabellen auf den SQL Server umziehen. Pl\u00f6tzlich liefert Format im Gruppierungsausdruck eine Fehlermeldung, Like &quot;M*&quot; findet keinen einzigen Datensatz, und ein Aufruf von Nz endet mit der Meldung, der Server kenne diese Funktion nicht. Wer Access mit einem SQL Server als Backend betreibt, kommt fr\u00fcher oder sp\u00e4ter nicht mehr um T-SQL herum, die Abfragesprache des Servers. Der erste Teil dieser Reihe zeigt, wo sich T-SQL von dem SQL unterscheidet, das wir aus Access kennen, und wie wir T-SQL direkt aus Access heraus ausf\u00fchren.","twitter:image":"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png"},"aioseo_meta_data":{"post_id":"55000516","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"limit_modified_date":false,"created":"2026-10-13 18:21:50","updated":"2026-10-13 18:21:50","ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/vbentwickler.de\/\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/vbentwickler.de\/category\/2026\/\" title=\"2026\">2026<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/\" title=\"4\/2026\">4\/2026<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tT-SQL, Teil 1: Von Jet-SQL zu T-SQL\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/vbentwickler.de\/"},{"label":"2026","link":"https:\/\/vbentwickler.de\/category\/2026\/"},{"label":"4\/2026","link":"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/"},{"label":"T-SQL, Teil 1: Von Jet-SQL zu T-SQL","link":"https:\/\/vbentwickler.de\/TSQL_Teil_1_Von_JetSQL_zu_TSQL\/"}],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000516","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000516"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000516\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000516"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000516"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000516"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000516"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}