Tabellenexistenz in Datenbanken überprüfen
Geschrieben von: Christoph Wille Im Normalfall weiß man, wenn man mit einer Datenbank arbeitet, welche Tabellen in ihr enthalten sind. Andererseits gibt es aber Anwendungsfälle, wo man erst zur Laufzeit auf eine Datenbank connected, und dann dynamisch herausfinden muß, welche Tabellen es gibt, oder überprüfen muß, ob eine spezielle Tabelle existiert. Heute stelle ich diverse Varianten vor, wie man feststellen kann, ob eine Tabelle in einer Datenbank enthalten ist. Das Auflisten aller Tabellen ist, wie sich zeigt, immer nur der Spezialfall der Suche nach einer Tabelle (oder anders herum, je nach dem, wie man das Problem betrachtet). Sei es wie es sei, ich demonstriere die verschiedenen Wege für SQL Server und Access, beginnend mit SQL Server. In SQL ServerIn SQL Server ist die Sache sehr einfach, wenn man weiß, wo man nachsehen muß. Die berühmte "allwissende Müllhalde" ist in SQL Server die Tabelle namens sysobjects - in dieser sind alle Objekte einer Datenbank vermerkt. Jedes dieser Objekte hat einen Typ, und der Typ der Tabellen zugeordnet ist, ist U. Das nun folgende Beispiel alltables_sql.asp zeigt, wie man sich alle Tabellen in einer SQL Server Datenbank auflisten lassen kann: <% strConnStr = "Provider=SQLOLEDB;Data Source=strangelove;Initial Catalog=Northwind;..." strTableStmt = "select * from sysobjects where type='U'" Set rs = Server.CreateObject("ADODB.Recordset") rs.Open strTableStmt, strConnStr While Not rs.EOF Response.Write rs.Fields("name").Value & "<br>" & vbCrlf rs.MoveNext Wend rs.Close Set rs = Nothing %> Damit hätten wir alle Tabellen aufgelistet, die es gibt. Nun müssen wir diesen Code nur noch modifizieren - und etwas leichter wiederverwendbar machen - damit wir die Existenz oder Nichtexistenz einer einzelnen Tabelle nachweisen. Dies erledigt das nun folgende Script tableexists_sql.asp. <% Option Explicit%> <script language="vbscript" runat="server"> Function TableExistsSql(ByVal strConnStr, ByVal strTable) Dim strSQL, rs, nCount strSQL = "select count(*) from sysobjects where type='U' AND name='" & _ strTable & "'" Set rs = Server.CreateObject("ADODB.Recordset") rs.Open strSQL, strConnStr nCount = rs.Fields(0).Value rs.Close Set rs = Nothing TableExistsSql = False If (1 = nCount) Then TableExistsSql = True End Function </script> <% Dim strConnStr strConnStr = "Provider=SQLOLEDB;Data Source=strangelove;Initial Catalog=Northwind;..." Response.Write TableExistsSql(strConnStr, "Customers") %> Die Funktion TableExistsSql kann man in ein zentrales Include geben, um eine leichte Wiederverwendbarkeit zu erzielen. In Access - mit BordmittelnSQL Server war quasi "aufgelegt". In Access wird's unter Umständen schon etwas verzwickter, außer man kennt zufälligerweise die "Untiefen" des Systems. Die angesprochene Untiefe ist das Faktum, daß Access seine Objekte ebenfalls in Tabellen verwaltet, diese allerdings versteckt sind. Man muß diese erst in Tools / Options zu Tage fördern: Und dann hat man plötzlich etliche zusätzliche Tabellen im Datenbankfenster (simple.mdb ist im heutigen Download enthalten): Der Name MSysObjects sieht doch bereits verdächtig nach dem aus, was wir suchen. Und tatsächlich - diese Tabelle enthält alle Objekte inklusive Tabellen, und Tabellen haben hier den Typ 1. Also müssen wir unseren Code nur geringfügig modifizieren - zuerst alltables_access.asp: <% strConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & Server.MapPath("simple.mdb") strTableStmt = "select * from MSysObjects where type=1" Set rs = Server.CreateObject("ADODB.Recordset") rs.Open strTableStmt, strConnStr While Not rs.EOF Response.Write rs.Fields("name").Value & "<br>" & vbCrlf rs.MoveNext Wend rs.Close Set rs = Nothing %> Die Sache hat nur einen Schönheitsfehler, der uns bei der Ausführung des Scripts schnell aufgezeigt wird: Microsoft JET Database Engine error '80040e09' Record(s) cannot be read; no read permission on 'MSysObjects'. /aspheute/findtable/alltables_access.asp, line 8 Im Vergleich zu SQL Server ist die Tabelle sogar gegen Zugriff durch den Admin (sa-Äquivalent in Access) gesperrt. Eine kurze Visite in Tools / Security / User and Group Permissions ist notwendig - wir müssen uns (dem Admin) die Read Data Rechte erlauben: Und jetzt funktioniert unser Script klaglos. Somit können wir auch unser Script zum Auffinden einer einzelnen Tabelle anpassen (tableexists_access.asp): <% Option Explicit%> <script language="vbscript" runat="server"> Function TableExistsAccess(ByVal strConnStr, ByVal strTable) Dim strSQL, rs, nCount strSQL = "select count(*) from MSysObjects where Type=1 AND Name='" & _ strTable & "'" Set rs = Server.CreateObject("ADODB.Recordset") rs.Open strSQL, strConnStr nCount = rs.Fields(0).Value rs.Close Set rs = Nothing TableExistsAccess = False If (1 = nCount) Then TableExistsAccess = True End Function </script> <% Dim strConnStr strConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & Server.MapPath("simple.mdb") Response.Write TableExistsAccess(strConnStr, "TestTable") %> Einzig der SQL String wurde geändert, sonst funktioniert alles gleich wie für SQL Server. Praktisch. In Access mit ADOXEs heißt, es führen mehrere Wege nach Rom. Für das Überprüfen der Tabellenexistenz stimmt das - man kann dies auch mit ADOX (ADO Extensions for Data Definition Language and Security) bewerkstelligen. Dieses Mal erspare ich uns den Umweg über das Auflisten aller Tabellen (das kann jeder selbst über die Tables Collection nachholen), und starte sogleich mit tableexists_adox.asp: <% Option Explicit%> <script language="vbscript" runat="server"> Function TableExistsADOX(ByVal strConnStr, ByVal strTable) Dim cat, tbl Set cat = Server.CreateObject("ADOX.Catalog") cat.ActiveConnection = strConnStr On Error Resume Next Set tbl = cat.Tables.Item(strTable) TableExistsADOX = True If Err.Number <> 0 Then TableExistsADOX = False End If Set cat = Nothing End Function </script> <% Dim strConnStr strConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & Server.MapPath("simple.mdb") Response.Write TableExistsADOX(strConnStr, "TestTable") %> Ich greife mit cat.Tables.Item(strTable) direkt in die Tables Collection hinein, um mir eine Referenz auf die gewünschte Tabelle zu holen. Die Frage ist, was passiert, wenn diese nicht existiert - es wird ein Fehler ausgelöst: ADOX.Tables error '800a0cc1' Item cannot be found in the collection corresponding to the requested name or ordinal. /aspheute/findtable/tableexists_adox.asp, line 9 Genau deshalb verwende ich das On Error Resume Next Statement - wird kein Fehler ausgelöst, existiert die Tabelle - kommt ein Fehler, war keine Tabelle dieses Namens in der Datenbank auffindbar. Diese Information verwende ich, um den Rückgabewert der Funktion zu belegen. SchlußbemerkungWas ist jetzt der bessere Weg um die Tabellenexistenz abzufragen? Nun, in SQL Server stellt sich die Frage nicht, und in Access ist der Weg über ADOX sicherlich der des geringsten Widerstands, da man die Originaldatenbank nicht modifizieren muß. Download des CodesKlicken Sie hier, um den Download zu starten. Verwandte Artikel
ADO Component Checker Tool Wenn Sie jetzt Fragen haben...Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten. Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.
Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.
©2000-2006 AspHeute.com |