{"id":55001493,"date":"2024-08-01T00:00:00","date_gmt":"2024-08-01T09:53:20","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1493"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Mehrwertige_Felder_mit_Wertliste_loswerden","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/","title":{"rendered":"Mehrwertige Felder mit Wertliste loswerden"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg02.met.vgwort.de\/na\/962a5efa84634ca0aa946ec3fea3dbfa\" width=\"1\" height=\"1\" alt=\"\"><b>Mehrwertige Felder sind eine Erfindung von Microsoft, um den Umgang mit Datenkonstrukten, bei denen f&uuml;r ein Feld mehrere Werte ausgew&auml;hlt werden k&ouml;nnen, zu vereinfachen. In einem mehrwertigen Feld k&ouml;nnen wir aus einer Liste von Werten, die entweder aus einer Wertliste oder aus einer anderen Tabelle stammen, keinen, einen oder mehrere Eintr&auml;ge ausw&auml;hlen. Aus einer verkn&uuml;pfen Tabelle mehrere Werte zuordnen? Das h&ouml;rt sich ja eigentlich nach dem Einsatzzweck einer m:n-Beziehung an. Genau das bildet Microsoft intern ab. Allerdings funktioniert das nur innerhalb des Access-Biotops. Sollen die Daten einmal zum SQL Server oder einer anderen Datenbank wandern, wird es kompliziert. Hier k&ouml;nnen wir solche Konstrukte n&auml;mlich nicht mehr einfach abbilden &#8211; wir m&uuml;ssen diese also ersetzen. Wie wir die mehrwertigen Felder loswerden, zeigen wir in diesem Beitrag.<\/b><\/p>\n<p>Microsoft hat in Access 2010 einige Neuerungen geliefert, die in Zusammenhang mit den gleichzeitig ver&ouml;ffentlichen sogenannten Webdaten standen. Neben den mehrwertigen Feldern sind das zum Beispiel die Anlagefelder. Wobei die Anlagefelder, wenn man sie richtig nutzt, zumindest noch einigerma&szlig;en sinnvoll sind. 1:1 zum SQL Server &uuml;bertragen k&ouml;nnen wir diese jedoch ebenfalls nicht. Das ist allerdings Thema eines anderen Beitrags.<\/p>\n<p>In diesem Beitrag wollen wir uns die mehrwertigen Felder ansehen. Davon gibt es grob zwei Ausf&uuml;hrungen:<\/p>\n<ul>\n<li>Als Erstes mehrwertige Felder, die ihre Daten aus einer Wertliste beziehen und nicht aus einer Tabelle oder Abfrage. Das hei&szlig;t, dass eine per Semikolon getrennte Liste von Eintr&auml;gen vorliegt, aus denen der Benutzer keinen, einen oder mehrere Eintr&auml;ge ausw&auml;hlen kann.<\/li>\n<li>Als Zweites sehen wir die mehrwertigen Verkn&uuml;pfungen, bei denen ein Nachschlagefeld auf Basis einer anderen Tabelle oder Abfrage erstellt wurde, f&uuml;r das wir keinen, einen oder mehrere Eintr&auml;ge je Datensatz ausw&auml;hlen k&ouml;nnen. Wir haben also prinzipiell eine 1:n-Beziehung, bei der Access intern eine m:n-Beziehung zwischenschaltet.<\/li>\n<\/ul>\n<p>Beide sind praktisch, bis man mal einen der Eintr&auml;ge aus der Liste entfernt &#8211; diese bleiben n&auml;mlich in der Auswahl erhalten. In diesem Beitrag schauen wir uns zun&auml;chst an, was geschieht, wenn wir erstgenannten Felder zum SQL Server migrieren wollen und wie wir das Datenmodell und die enthaltenen Daten korrekt zum SQL Server migrieren.<\/p>\n<h2>Probleme bei Verwendung in SQL Server und Co.<\/h2>\n<p>Richtig problematisch wird es jedoch, wenn wir Tabellen mit solchen Feldern zum SQL Server migrieren wollen. Warum das der Fall ist, zeigen wir gleich nach dem Erstellen der Beispiele f&uuml;r diesen Beitrag.<\/p>\n<h2>Beispiel mehrwertige Wertliste: Produkte und Kategorien<\/h2>\n<p>Zu Beispielzwecken legen wir eine Tabelle namens <b>tblProdukte <\/b>an, welche die folgenden drei Felder enth&auml;lt:<\/p>\n<ul>\n<li><b>ProduktID<\/b>: Prim&auml;rsch&uuml;sselfeld der Tabelle<\/li>\n<li><b>Produktname<\/b>: Name des Produkts<\/li>\n<li><b>Kategorien<\/b>: Feld mit den Kategorien des Produkts<\/li>\n<\/ul>\n<p>F&uuml;r den Datentyp des dritten Feldes w&auml;hlen wir <b>Nachschlage-Assistent&#8230; <\/b>aus (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_001.png\" alt=\"Anlegen eines Nachschlagefeldes\" width=\"424,5589\" height=\"376,5319\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Anlegen eines Nachschlagefeldes<\/span><\/b><\/p>\n<p>Im Assistenten f&uuml;hren wir folgende Schritte durch:<\/p>\n<ul>\n<li>Schritt 1: Auswahl von <b>Ich m&ouml;chte selbst Werte in die Liste eingeben<\/b><\/li>\n<li>Schritt 2: Anzahl der Spalten bleibt <b>1<\/b><\/li>\n<li>Schritt 3: Beschriftung beibehalten, Option <b>Nur Listeneintr&auml;ge <\/b>aktivieren, Option <b>Mehrere Werte zulassen <\/b>aktivieren (siehe Bild 2).<\/li>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_002.png\" alt=\"Einstellen der Nachschlagefeld-Eigenschaften\" width=\"549,559\" height=\"370,5597\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Einstellen der Nachschlagefeld-Eigenschaften<\/span><\/b><\/p>\n<\/ul>\n<p>Danach k&ouml;nnen wir f&uuml;r das Feld <b>Kategorien<\/b> in den Eigenschaften unter <b>Nachschlagen <\/b>die gew&uuml;nschten Kategorien durch Semikola separiert f&uuml;r die Eigenschaft <b>Datensatzherkunft<\/b> eingeben (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_003.png\" alt=\"Hinzuf&uuml;gen der Eintr&auml;ge\" width=\"424,5589\" height=\"240,4909\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Hinzuf&uuml;gen der Eintr&auml;ge<\/span><\/b><\/p>\n<p>Wenn wir wollen, dass der Benutzer die Werte selbst &auml;ndern kann, stellen wir noch die Eigenschaft <b>Wertlistenbearbeitung zulassen <\/b>auf den Wert <b>Ja <\/b>ein.<\/p>\n<h2>Mehrwertige Wertliste im Formular<\/h2>\n<p>Wenn wir ein neues Formular mit dieser Tabelle als Datensatzquelle ausstatten und die drei Felder hinzuf&uuml;gen, sehen wir das Ergebnis aus Bild 4. In diesem Fall ist die Wertlistenbearbeitung aktiviert, was wir an der Schaltfl&auml;che erkennen, die beim &Ouml;ffnen der Liste eingeblendet wird.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_004.png\" alt=\"Einsatz der mehrwertigen Wertliste im Formular\" width=\"424,5589\" height=\"334,6523\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Einsatz der mehrwertigen Wertliste im Formular<\/span><\/b><\/p>\n<h2>Analyse der Daten<\/h2>\n<p>Bevor wir pr&uuml;fen, was beim Migrieren der mehrwertigen Wertliste zum SQL Server passiert, schauen wir uns an, was diese Felder eigentlich speichern. Zun&auml;chst einmal betrachten wir den im Feld <b>Kategorien <\/b>des ersten Datensatzes gespeicherten Wert. Dazu nutzen wir die <b>DLookup<\/b>-Funktion, die folgendes Ergebnis liefert:<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> DLookup(\"Kategorien\", \"tblProdukte\")\r\nKategorie 1; Kategorie 3<\/pre>\n<p>Au&szlig;erdem schauen wir uns noch an, wie die zugrunde liegenden Daten aussehen. Dazu lesen wir die Eigenschaft <b>RowSource <\/b>des Kombinationsfeldes aus:<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> CurrentDb.TableDefs(\"tblProdukte\").Fields(\"Kategorien\").Properties(\"RowSource\")\r\n\"Kategorie 1\";\"Kategorie 2\";\"Kategorie 3\";\"Kategorie 4\"<\/pre>\n<p>Wir erhalten also zwei Listen, von denen die erste nur die selektierten Eintr&auml;ge enth&auml;lt.<\/p>\n<h2>Migration dieser Tabelle zum SQL Server<\/h2>\n<p>Nun migrieren wir diese Tabelle mit dem SQL Server Migration Assistant in eine neue Datenbank im SQL Server &#8211; mehr dazu im Beitrag <b>Access und SQL Server: Der Migrations-Assistent <\/b>(<b>www.access-im-unternehmen.de\/18<\/b>).<\/p>\n<p>Dazu gehen wir nach dem Starten des SSMA wie folgt vor:<\/p>\n<ul>\n<li>Wir legen mit <b>File|New Project&#8230; <\/b>ein neues Projekt namens <b>MehrwertigeWertlisten<\/b> an.<\/li>\n<li>Wir w&auml;hlen mit dem Befehl <b>Add Databases <\/b>die Beispieldatenbank dieses Beitrags aus.<\/li>\n<li>Im Bereich <b>Access Metadata Explorer <\/b>selektieren wir die zu migrierende Tabelle <b>tblProdukte <\/b>(siehe Bild 5).<\/li>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_005.png\" alt=\"Zu migrierende Tabelle ausw&auml;hlen\" width=\"424,5589\" height=\"269,0866\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Zu migrierende Tabelle ausw&auml;hlen<\/span><\/b><\/p>\n<li>Nun klicken wir auf <b>Connect to SQL Server <\/b>und verbinden uns mit der SQL Server-Instanz, auf der wir die Datenbank anlegen wollen. F&uuml;r <b>Database<\/b> geben wir den Namen der zu erstellenden Datenbank an, hier <b>MehrwertigeWertlisten <\/b>(siehe Bild 6). Gegebenenfalls erscheint eine Meldung, dass die Datenbank noch nicht vorhanden ist und die fragt, ob die Datenbank angelegt werden soll. Dies best&auml;tigen wir.<\/li>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_006.png\" alt=\"Verbinden mit der noch anzulegenden Datenbank\" width=\"424,5589\" height=\"384,8218\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Verbinden mit der noch anzulegenden Datenbank<\/span><\/b><\/p>\n<li>Damit wird die Datenbank bereits angelegt, wovon wir uns im SQL Server Management Studio &uuml;berzeugen k&ouml;nnen (siehe Bild 7).<\/li>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_007.png\" alt=\"Die neue Datenbank ist bereits erstellt.\" width=\"424,5589\" height=\"357,9614\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Die neue Datenbank ist bereits erstellt.<\/span><\/b><\/p>\n<li>Dann markieren wir den Eintrag mit dem Namen der zu migrierenden Datenbank im Bereich <b>Access Metadata Explorer<\/b>.<\/li>\n<li>Schlie&szlig;lich rufen wir den Befehl <b>Convert, Load and Migrate <\/b>auf.<\/li>\n<li>Die Migration beginnt und es erscheint der Dialog <b>Synchronize with the Database<\/b>. Diesen Dialog k&ouml;nnen wir mit <b>Ok <\/b>direkt wieder schlie&szlig;en.<\/li>\n<li>Danach folgt der Dialog <b>Convert, Load and Migrate<\/b>. Dieser weist auf einen Fehler bei der Konvertierung hin (siehe Bild 8).<\/li>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_008.png\" alt=\"Es gibt einen Fehler.\" width=\"524,559\" height=\"176,7957\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Es gibt einen Fehler.<\/span><\/b><\/p>\n<li>Ein Klick auf diesen Link zeigt Details zum Fehler an. Der Datentyp <b>Complex Text <\/b>wird nicht unterst&uuml;tzt (siehe Bild 9).<\/li>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_009.png\" alt=\"Ein Datentyp wird nicht unterst&uuml;tzt.\" width=\"524,559\" height=\"154,6274\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Ein Datentyp wird nicht unterst&uuml;tzt.<\/span><\/b><\/p>\n<li>Schlie&szlig;lich k&ouml;nnen wir uns im SQL Server Management Studio das Ergebnis anschauen.<\/li>\n<\/ul>\n<p>In diesem Fall sehen wir, dass das Feld <b>Kategorien<\/b> zwar migriert wurde.<\/p>\n<p>Allerdings finden wir hier ein Feld mit dem Datentyp <b>varchar(8000)<\/b> vor. Das Feld enth&auml;lt lediglich die f&uuml;r die jeweiligen Produkte ausgew&auml;hlten Kategorien. Die verf&uuml;gbaren Kategorien sind hier nicht mehr zu sehen (siehe Bild 10).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_010.png\" alt=\"Das Ergebnis der Migration\" width=\"649,559\" height=\"297,4767\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Das Ergebnis der Migration<\/span><\/b><\/p>\n<p>Und da die meisten Tabelleneigenschaften, vor allem aber die zum Thema Nachschlagefelder, nicht zum SQL Server &uuml;bertragen werden, k&ouml;nnen wir nicht damit rechnen, dass die vollst&auml;ndige Liste der verf&uuml;gbaren Kategorien irgendwo im SQL Server zu finden ist.<\/p>\n<p>Wenn wir die zum SQL Server migrierte Tabelle <b>tblProdukte <\/b>nun per ODBC-Verkn&uuml;pfung in die Beispieldatenbank einbinden, sehen wir dort im Feld <b>Kategorien <\/b>zwar noch die gleichen Werte, die auch in der urspr&uuml;nglichen Tabelle enthalten waren, aber wir k&ouml;nnen diese nicht mehr selektieren.<\/p>\n<p>Auch wenn wir eine Kopie des Beispielformulars von oben anlegen und dieses mit der verkn&uuml;pften Tabelle <b>dbo_tblProdukte<\/b> versehen, sehen wir dort zwar die Liste der markierten Eintr&auml;ge. Wenn wir die Liste jedoch &ouml;ffnen, finden wir keine M&ouml;glichkeit mehr, mehr als einen Eintrag auszuw&auml;hlen (siehe Bild 11).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_011.png\" alt=\"Bei der migrierten und neu verkn&uuml;pften Tabelle werden die Kontrollk&auml;stchen f&uuml;r die Kategorien nicht mehr angezeigt.\" width=\"424,5589\" height=\"298,6028\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 11: Bei der migrierten und neu verkn&uuml;pften Tabelle werden die Kontrollk&auml;stchen f&uuml;r die Kategorien nicht mehr angezeigt.<\/span><\/b><\/p>\n<h2>Mehrwertige Wertlisten korrekt migrieren<\/h2>\n<p>Nun schauen wir uns an, wie wir diese mehrwertigen Wertlisten so migrieren k&ouml;nnen, dass die gew&uuml;nschten Daten vom SQL Server bereitgestellt werden und auch zugewiesen werden k&ouml;nnen. Es f&uuml;hrt dabei kein Weg daran vorbei, die Daten, die sich im Feld <b>Kategorien <\/b>der Tabelle <b>tblProdukte <\/b>befinden, in eine eigene Tabelle namens <b>tblKategorien <\/b>auszulagern. Diese weisen wir allerdings nicht der Eigenschaft <b>Datensatzherkunft <\/b>des Feldes <b>Kategorien <\/b>der Tabelle <b>tblProdukte <\/b>zu.<\/p>\n<p>Dies w&auml;re nur sinnvoll, wenn nur eine Kategorie je Produkt ausgew&auml;hlt werden soll. Die Ausgangssituation ist jedoch, dass wir jedem Produkt eine, keine oder mehrere Kategorien zuweisen k&ouml;nnen. Um dies zu realisieren, ben&ouml;tigen wir also auch noch eine Verkn&uuml;pfungstabelle zum Herstellen einer m:n-Beziehung. Diese nennen wir <b>tblProdukteKategorien<\/b>.<\/p>\n<p>In weiteren Schritten sind zun&auml;chst die Eintr&auml;ge der Wertliste des Feldes <b>Kategorien <\/b>in die Tabelle <b>tblKategorien <\/b>zu &uuml;bertragen. Und zu guter Letzt &uuml;bertragen wir noch die ausgew&auml;hlten Werte in die Verkn&uuml;pfungstabelle <b>tblProdukteKategorien<\/b>.<\/p>\n<p>Damit sind wir leider noch nicht am Ende der Migrationsarbeiten angelangt. Die einfache Darstellung aus dem mehrwertigen Feld mit der Anzeige aller Eintr&auml;ge, die man einfach per Kontrollk&auml;stchen selektieren kann, gibt es so f&uuml;r m:n-Beziehungen leider nicht.<\/p>\n<p>Also werden wir in weiteren Beitr&auml;gen Alternativen dazu vorstellen &#8211; siehe <b>m:n-Daten wie im mehrwertigen Feld selektieren <\/b>(<b>www.access-im-unternehmen.de\/1424<\/b>).<\/p>\n<h2>Von der mehrwertigen Wertliste zur m:n-Beziehung<\/h2>\n<p>Wir gehen in diesen Schritten vor:<\/p>\n<ul>\n<li>Tabelle f&uuml;r die Kategorien erstellen<\/li>\n<li>Verkn&uuml;pfungstabelle erstellen<\/li>\n<li>Wertliste in Tabelle f&uuml;r Kategorien &uuml;bertrage<\/li>\n<li>Gew&auml;hlte Werte in Verkn&uuml;pfungstabelle schreiben<\/li>\n<li>Mehrwertiges Feld <b>Kategorien <\/b>l&ouml;schen<\/li>\n<\/ul>\n<h2>Erstellen der Tabelle tblKategorien<\/h2>\n<p>Diese Tabelle enth&auml;lt nur zwei Felder &#8211; das Prim&auml;rschl&uuml;sselfeld <b>KategorieID <\/b>und das Feld <b>Kategorie<\/b>. F&uuml;r dieses legen wir einen eindeutigen Index fest, damit jede Kategorie nur einmal eingetragen werden kann (siehe Bild 12).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_012.png\" alt=\"Tabelle zum Speichern der Kategorien\" width=\"499,5589\" height=\"339,2067\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 12: Tabelle zum Speichern der Kategorien<\/span><\/b><\/p>\n<h2>Erstellen der Tabelle tblProdukteKategorien<\/h2>\n<p>Die Tabelle <b>tblProdukteKategorien <\/b>soll die Verkn&uuml;pfung jedes Eintrags der Tabelle <b>tblProdukte <\/b>mit jedem Eintrag der Tabelle <b>tblKategorien <\/b>erlauben.<\/p>\n<p>Dazu f&uuml;gen wir dieser Tabelle zun&auml;chst ein Prim&auml;rschl&uuml;sselfeld namens <b>ProduktKategorieID <\/b>hinzu. Au&szlig;erdem legen wir zwei Fremdschl&uuml;sselfelder an. Das erste hei&szlig;t <b>ProduktID <\/b>und erm&ouml;glicht die Angabe des Produkts eines Datensatzes, das zweite hei&szlig;t <b>KategorieID <\/b>und soll das Zuweisen einer Kategorie erlauben.<\/p>\n<p>F&uuml;r die beiden Felder <b>ProduktID <\/b>und <b>KategorieID <\/b>legen wir au&szlig;erdem einen zusammengesetzten, eindeutigen Index an (siehe Bild 13).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_013.png\" alt=\"Verkn&uuml;pfungstabelle zwischen den Tabellen tblProdukte und tblKategorien\" width=\"649,559\" height=\"395,1923\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 13: Verkn&uuml;pfungstabelle zwischen den Tabellen tblProdukte und tblKategorien<\/span><\/b><\/p>\n<p>Da diese Tabelle direkt zum SQL Server migriert werden soll, der bekannterma&szlig;en solche Eigenschaften wie die zum Realisieren von Nachschlagefeldern in Access nicht erlaubt, brauchen wir uns gar nicht erst die M&uuml;he zu machen, die Fremdschl&uuml;sselfelder als Nachschlagefelder einzurichten.<\/p>\n<h2>Einrichten der Beziehungen<\/h2>\n<p>Damit kommen wir zu den Beziehungen, die wir &uuml;ber das Beziehungen-Fenster anlegen. Dazu ziehen wir die drei Tabellen <b>tblProdukte<\/b>, <b>tblProdukteKategorien <\/b>und <b>tblKategorien <\/b>in das Beziehungen-Fenster. Die Beziehung zwischen der Tabelle <b>tblProdukte <\/b>und <b>tblProdukteKategorien <\/b>erzeugen wir, indem wir das Feld <b>ProduktID <\/b>von der Tabelle <b>tblProdukte <\/b>auf das gleichnamige Feld der Tabelle <b>tblProdukteKategorien <\/b>ziehen. Im nun erscheinenden Dialog <b>Beziehungen bearbeiten <\/b>aktivieren wir die Option <b>Mit referentieller Integrit&auml;t<\/b>. Au&szlig;erdem aktivieren wir die Option <b>L&ouml;schweitergabe an verwandte Datens&auml;tze<\/b>.<\/p>\n<p>Damit sorgen wir daf&uuml;r, dass wenn wir ein Produkt l&ouml;schen, auch die Verkn&uuml;pfungen zu den jeweiligen Kategorien aus der Tabelle <b>tblProdukteKategorien <\/b>entfernt werden.<\/p>\n<p>Den gleichen Schritt f&uuml;hren wir f&uuml;r die Beziehung zwischen den Tabellen <b>tblKategorien <\/b>und <b>tblProdukteKategorien <\/b>durch. Hier ziehen wir das Feld <b>KategorieID <\/b>von <b>tblKategorien <\/b>auf das Feld <b>KategorieID <\/b>der Tabelle <b>tblProdukteKategorien<\/b>.<\/p>\n<p>Neben der Option <b>Mit referentieller Integrit&auml;t <\/b>aktivieren keine weitere Option &#8211; insbesondere nicht die Option <b>L&ouml;schweitergabe an verwandte Datens&auml;tze<\/b>.<\/p>\n<p>So verhindern wir, dass Kategorien aus der Tabelle <b>tblKategorien <\/b>gel&ouml;scht werden k&ouml;nnen, die bereits einem Produkt zugeordnet sind (siehe Bild 14).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_014.png\" alt=\"Anlegen der Verkn&uuml;pfungen zwischen den Tabellen\" width=\"624,559\" height=\"418,8437\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 14: Anlegen der Verkn&uuml;pfungen zwischen den Tabellen<\/span><\/b><\/p>\n<h2>&Uuml;bertragen der Kategorien in die Tabelle tblKategorien<\/h2>\n<p>Nun wollen wir alle Kategorien aus der Wertliste des Feldes <b>Kategorien <\/b>der Tabelle <b>tblProdukte <\/b>in die Tabelle <b>tblKategorien <\/b>&uuml;bertragen. Dazu haben wir dieser Tabelle einige weitere Produkte samt Kategorien hinzugef&uuml;gt (siehe Bild 15). Die Eintr&auml;ge der Wertliste des Feldes <b>Kategorien <\/b>k&ouml;nnen wir per DAO-Zugriff auf die jeweilige Eigenschaft des Feldes ermitteln. Wir erhalten eine Liste, deren Eintr&auml;ge durch Semikola voneinander getrennt sind:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_015.png\" alt=\"Zu &uuml;bertragende Daten\" width=\"424,5589\" height=\"152,6139\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 15: Zu &uuml;bertragende Daten<\/span><\/b><\/p>\n<pre>\"Kategorie 1\";\"Kategorie 2\";\"Kategorie 3\";\"Kategorie 4\"<\/pre>\n<p>Um diese jeweils als neuen Datensatz zur Tabelle <b>tblKategorien <\/b>hinzuzuf&uuml;gen, nutzen wir die VBA-Prozedur aus Listing 1.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>KategorienInTabelle()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>strKategorien<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strKategorieArray()<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngKategorie<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strKategorie<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     strKategorien = db.TableDefs(\"tblProdukte\").Fields(\"Kategorien\").Properties(\"RowSource\")\r\n     strKategorieArray = <span style=\"color:blue;\">Split<\/span>(strKategorien, \";\")\r\n     For lngKategorie = <span style=\"color:blue;\">LBound<\/span>(strKategorieArray) To <span style=\"color:blue;\">UBound<\/span>(strKategorieArray)\r\n         strKategorie = strKategorieArray(lngKategorie)\r\n         db.Execute \"INSERT INTO tblKategorien(Kategorie) VALUES(\" & strKategorie & \")\", dbFailOnError\r\n     <span style=\"color:blue;\">Next<\/span> lngKategorie\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: &Uuml;bertragen der Kategorien<\/span><\/b><\/p>\n<p>Diese liest den Inhalt der Wertliste des Feldes <b>Kategorien <\/b>der Tabelle <b>tblProdukte <\/b>in die Variable <b>strKategorien <\/b>ein. Dann erzeugt sie daraus mit der <b>Split<\/b>-Methode ein Array, das sie mit der Variablen <b>strKategorieArray <\/b>referenziert.<\/p>\n<p>Die Elemente dieses Arrays durchlaufen wir in einer <b>For&#8230;Next<\/b>-Schleife &uuml;ber alle Elemente des Arrays, wobei wir den ersten und den letzten Index mit den Funktionen <b>LBound <\/b>und <b>UBound <\/b>ermitteln.<\/p>\n<p>In dieser Schleife f&uuml;hren wir eine <b>INSERT INTO<\/b>-Anweisung aus, die den aktuellen Wert des Arrays in einen neuen Datensatz der Tabelle <b>tblKategorien <\/b>eintr&auml;gt.<\/p>\n<p>Diese SQL-Anweisung hat eine Besonderheit gegen&uuml;ber anderen Beispielen, in denen wir Texte in ein Textfeld einer Tabelle eintragen. Normalerweise w&uuml;rden wir die Variable wie folgt in Hochkommata einfassen, da wir damit einen Text zum Feld hinzuf&uuml;gen wollen:<\/p>\n<pre>db.Execute \"INSERT INTO tblKategorien(Kategorie) VALUES(''\" & strKategorie & \"'')\", dbFailOnError<\/pre>\n<p>Wie wir weiter oben gesehen haben, enth&auml;lt die Eigenschaft Wertliste die einzelnen Kategorien bereits als in Anf&uuml;hrungszeichen eingefasste Eintr&auml;ge. Wir m&uuml;ssen in diesem Fall also auf die Hochkommata verzichten, da wir sonst Werte wie <b>&#8222;Kategorie 1&#8220; <\/b>in der Tabelle vorfinden w&uuml;rden.<\/p>\n<p>Nachdem wir die Prozedur ausgef&uuml;hrt haben, sieht die Tabelle <b>tblKategorien <\/b>wie in Bild 16 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_016.png\" alt=\"Gef&uuml;llte Tabelle mit Kategorien\" width=\"424,5589\" height=\"187,5479\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 16: Gef&uuml;llte Tabelle mit Kategorien<\/span><\/b><\/p>\n<h2>Abfangen doppelter Kategorien<\/h2>\n<p>Es kann an dieser Stelle passieren, dass die Datenbank Kategorien doppelt enth&auml;lt. Dies w&uuml;rde bei der obigen Prozedur zu einem Fehler f&uuml;hren, wenn diese versucht, der Tabelle <b>tblKategorien <\/b>einen neuen Datensatz hinzuzuf&uuml;gen, der im Feld <b>Kategorie <\/b>einen Wert enth&auml;lt, der bereits in der Tabelle enthalten ist. Der Grund ist, dass wir weiter oben einen eindeutigen Index f&uuml;r das Feld <b>Kategorie <\/b>der Tabelle <b>tblKategorien <\/b>definiert haben. Der Versuch, einen bereits vorhandenen Wert nochmals hinzuzuf&uuml;gen, resultiert im Fehler <b>3022<\/b>. Diesen k&ouml;nnen wir jedoch durch Einschlie&szlig;en der <b>db.Execute<\/b>-Anweisung in die folgenden Zeilen verhindern:<\/p>\n<pre>On Error Resume <span style=\"color:blue;\">Next<\/span>\r\ndb.Execute ...\r\nOn Error Goto 0<\/pre>\n<p>Dadurch unterbinden wir allerdings auch Meldungen, die durch andere Fehler entstehen. Es kann zum Beispiel sein, dass sich irgendwie ein Hochkomma in einen Kategorienamen eingeschlichen hat. Um dadurch ausgel&ouml;ste Fehler zu verhindern, verdoppeln wir eventuell auftauchende Hochkommata vorher wie folgt:<\/p>\n<pre>strKategorie = <span style=\"color:blue;\">Replace<\/span>(strKategorie, \"''\", \"''''\")<\/pre>\n<h2>&Uuml;bertragen der zugeordneten Kategorien in die Tabelle tblProdukteKategorien<\/h2>\n<p>Nun wollen wir die eigentlichen Inhalte des Feldes <b>Kategorien <\/b>in die Tabelle <b>tblProdukteKategorien <\/b>&uuml;bertragen. Wie wir weiter oben gesehen haben, k&ouml;nnen wir per <b>DLookup <\/b>leicht auf die Liste der zugeordneten Werte zugreifen:<\/p>\n<pre>  DLookup(\"Kategorien\", \"tblProdukte\")\r\nKategorie 1; Kategorie 3<\/pre>\n<p>Wenn wir allerdings per DAO-Recordset auf den Inhalt des entsprechenden Feldes zugreifen wollen, erhalten wir einen Fehler (siehe Bild 17).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_017.png\" alt=\"Fehler beim Zugriff auf die Kategorien\" width=\"649,559\" height=\"350,2817\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 17: Fehler beim Zugriff auf die Kategorien<\/span><\/b><\/p>\n<p>Lassen wir uns hier den Typ von <b>rst!Kategorien <\/b>im Direktbereich ausgeben, erhalten wir:<\/p>\n<pre>  Typename(rst!Kategorien)\r\nField3<\/pre>\n<p>Das hei&szlig;t, dass Access beim Zugriff &uuml;ber <b>DLookup <\/b>wohl noch die Daten zusammenstellt, die intern gespeichert werden. Also gehen wir davon aus, dass wir auf die so gespeicherten Elemente auf &auml;hnliche Weise zugreifen k&ouml;nnen, wie es auch bei Anlagefeldern ist &#8211; hier finden wir innerhalb des Anlagefeldes ein Recordset vor, aus dem wir die tats&auml;chlichen Werte des Anlagefeldes auslesen k&ouml;nnen. Bei den mehrwertigen Feldern ist dies allerdings etwas einfacher als bei Anlagefeldern.<\/p>\n<p>Wir nutzen dazu die Prozedur aus Listing 2. Diese &ouml;ffnet ein Recordset auf Basis der Tabelle <b>tblProdukte<\/b> und referenziert dieses mit der Variablen <b>rst<\/b>. Dieses durchl&auml;uft die Prozedur anschlie&szlig;end in einer <b>Do While<\/b>-Schleife.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>KategoriezuordnungenInTabelle()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strKategorie<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>fld3<span style=\"color:blue;\"> As <\/span>DAO.Field3\r\n     <span style=\"color:blue;\">Dim <\/span>rstKategorien<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>lngProduktID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngKategorieID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT ProduktID, Kategorien FROM tblProdukte\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         lngProduktID = rst!ProduktID\r\n         <span style=\"color:blue;\">Set<\/span> fld3 = rst!Kategorien\r\n         <span style=\"color:blue;\">Set<\/span> rstKategorien = fld3.Value\r\n         <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstKategorien.EOF\r\n             strKategorie = rstKategorien!Value\r\n             lngKategorieID = Nz(DLookup(\"KategorieID\", \"tblKategorien\", \"Kategorie = ''\" & strKategorie & \"''\"), 0)\r\n             <span style=\"color:blue;\">If <\/span>lngKategorieID = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 If <span style=\"color:blue;\">MsgBox<\/span>(\"Kategorie ''\" & strKategorie & \"'' noch nicht vorhanden. Anlegen?\", vbYesNo + vbExclamation, _\r\n                         \"Fehlende Kategorie\") = vbYes Then\r\n                     strKategorie = <span style=\"color:blue;\">Replace<\/span>(strKategorie, \"''\", \"''''\")\r\n                     db.Execute \"INSERT INTO tblKategorien(Kategorie) VALUES(''\" & strKategorie & \"'')\", dbFailOnError\r\n                     lngKategorieID = db.OpenRecordset(\"SELECT @@IDENTITY\").Fields(0)\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngKategorieID = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n                 db.Execute \"INSERT INTO tblProdukteKategorien(ProduktID, KategorieID) VALUES(\" & lngProduktID _\r\n                     & \", \" & lngKategorieID & \")\", dbFailOnError\r\n                 <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             rstKategorien.Move<span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Loop<\/span>\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: &Uuml;bertragen der Zuordnung der Kategorien zu den Produkten<\/span><\/b><\/p>\n<p>Darin erfasst sie den Prim&auml;rsch&uuml;sselwert des aktuellen Produkts mit der Variablen <b>lngProduktID<\/b>. Dann referenziert sie das Feld <b>Kategorien <\/b>mit der Variablen <b>fld3<\/b>, dessen Inhalt der Eigenschaft <b>Value <\/b>dann von einem weiteren Recordset namens <b>rstKategorien <\/b>erfasst wird.<\/p>\n<p>Auch dieses Recordset durchlaufen wir in einer <b>Do While<\/b>-Schleife und erhalten so Zugriff auf jeden einzelnen Eintrag der <b>Kategorien<\/b>-Wertliste.<\/p>\n<p>Wir lesen den Wert der Kategorie aus dem Feld <b>Value <\/b>in die Variable <b>strKategorie <\/b>ein. Dann holen wir uns aus der Tabelle <b>tblKategorien<\/b>, die ja bereits alle Kategorien enth&auml;lt, den Prim&auml;rschl&uuml;sselwert dieser Kategorie und speichern ihn mit <b>lngKategorieID<\/b>.<\/p>\n<p>Es kann jedoch sein, dass eine Kategorie, obwohl sie einem Produkt zugeordnet ist, nicht in der Tabelle <b>tblKategorien <\/b>enthalten ist. Wie kann das geschehen? Das beschreiben wir weiter unten. Jedenfalls landet dann mithilfe der <b>Nz<\/b>-Funktion der Wert <b>0 <\/b>in der Variablen <b>lngKategorieID<\/b>. Ist <b>lngKategorieID <\/b>nach diesem Schritt <b>0<\/b>, fragen wir den Benutzer, ob die benannte Kategorie aus <b>strKategorie <\/b>in der Tabelle <b>tblKategorien <\/b>angelegt werden soll. Ist das gew&uuml;nscht, schreibt die folgende <b>INSERT INTO<\/b>-Anweisung den fehlenden Datensatz in die Tabelle <b>tblKategorien<\/b> und liest den Prim&auml;rschl&uuml;sselwert des neuen Datensatzes in die Variable <b>lngKategorieID <\/b>ein.<\/p>\n<p>Ist <b>lngKategorieID <\/b>danach nicht <b>0<\/b>, wird ein neuer Datensatz in der Tabelle <b>tblProdukteKategorien <\/b>angelegt und somit eine neue Verkn&uuml;pfung von Produkten und Kategorien.<\/p>\n<p>Auf diese Weise werden alle Produkte und Kategorien durchlaufen und entsprechende Datens&auml;tze in der Tabelle <b>tblProdukteKategorien <\/b>angelegt.<\/p>\n<p>Ein beispielhaftes Ergebnis der Zuordnung von Produkten zu Kategorien in der Tabelle <b>tblProdukteKategorien <\/b>sehen wir in Bild 18.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_018.png\" alt=\"Zuordnung von Produkten zu Kategorien\" width=\"424,5589\" height=\"309,928\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 18: Zuordnung von Produkten zu Kategorien<\/span><\/b><\/p>\n<h2>Wie k&ouml;nnen Kategorien verlorengehen?<\/h2>\n<p>Oben haben wir Code in die Prozedur eingebaut f&uuml;r den Fall, dass wir im Feld <b>Kategorien <\/b>der Tabelle <b>tblProdukte <\/b>eine Kategorie finden, die nicht in der Tabelle <b>tblKategorien <\/b>vorhanden ist.<\/p>\n<p>Wie aber kann es &uuml;berhaupt dazu kommen, dass eine Kategorie verlorengeht? Das demonstrieren wir wie folgt. Wir legen einen neuen Datensatz namens <b>Produkt 5 <\/b>in der Tabelle <b>tblProdukte <\/b>an.<\/p>\n<p>Dann &ouml;ffnen wir das Auswahlfeld <b>Kategorien <\/b>und klicken unten auf die Schaltfl&auml;che zum Bearbeiten der Eintr&auml;ge.<\/p>\n<p>Dies &ouml;ffnet den Dialog <b>Listenelemente bearbeiten<\/b>, dem wir eine neue Kategorie namens <b>Kategorie 5 <\/b>hinzuf&uuml;gen (siehe Bild 19).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_019.png\" alt=\"Neue Kategorie f&uuml;r ein Produkt\" width=\"424,5589\" height=\"407,8732\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 19: Neue Kategorie f&uuml;r ein Produkt<\/span><\/b><\/p>\n<p>Wir schlie&szlig;en den Dialog wieder und f&uuml;gen dem Eintrag <b>Produkt 5 <\/b>die Kategorie <b>Kategorie 5<\/b> hinzu (siehe Bild 20).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_020.png\" alt=\"Zuweisen der neuen Kategorie\" width=\"424,5589\" height=\"317,1526\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 20: Zuweisen der neuen Kategorie<\/span><\/b><\/p>\n<p>Jetzt kommt der entscheidende Schritt, der auch ein Grund ist, warum man mehrwertige Felder wie dieses nicht nutzen sollte: Wie &ouml;ffnen nochmals den Dialog zum Bearbeiten der Kategorien und l&ouml;schen den Eintrag <b>Kategorie 5 <\/b>wieder (siehe Bild 21).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_04\/pic_1493_021.png\" alt=\"Wir l&ouml;schen die neue Kategorie wieder.\" width=\"349,5589\" height=\"332,6252\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 21: Wir l&ouml;schen die neue Kategorie wieder.<\/span><\/b><\/p>\n<p>Wenn wir nun die Liste f&uuml;r eines der &uuml;brigen Produkte &ouml;ffnen, dem wir <b>Kategorie 5 <\/b>nicht zugeordnet haben, sehen wir diesen Eintrag nicht in der Auswahl. Wenn wir jedoch die Liste der Kategorien f&uuml;r <b>Produkt 5 <\/b>&ouml;ffnen, ist <b>Kategorie 5 <\/b>dort noch vorhanden.<\/p>\n<p>W&uuml;rden wir so zuerst die Kategorien aus der Wertliste des Feldes <b>Kategorien <\/b>in die Tabelle <b>tblKategorien <\/b>&uuml;bertragen, w&uuml;rden dort die vier Eintr&auml;ge <b>Kategorie 1<\/b>, <b>Kategorie 2<\/b>, <b>Kategorie 3 <\/b>und <b>Kategorie 4 <\/b>landen.<\/p>\n<p><b>Kategorie 5<\/b>, die noch dem Produkt <b>Produkt 5 <\/b>zugeordnet ist, landet jedoch nicht dort &#8211; au&szlig;er, wir f&uuml;gen sie durch die Spezialbehandlung, die wir in der Prozedur eingef&uuml;gt haben, nachtr&auml;glich hinzu.<\/p>\n<p>Danach k&ouml;nnen wir die drei Tabellen ohne Probleme in eine SQL Server-Datenbank migrieren und das Access-Frontend mit diesen Tabellen verkn&uuml;pfen.<\/p>\n<p>Sofern wir das urspr&uuml;ngliche mehrwertige Feld <b>Kategorien <\/b>noch nicht aus der Tabelle <b>tblProdukte <\/b>entfernt haben, erscheint zwar nach wie vor die Fehlermeldung, aber diese k&ouml;nnen wir nun ignorieren. Der Ordnung halber sollten wir aber, nachdem wir die Daten aus diesem Feld in die beiden Tabellen <b>tblKategorien <\/b>und <b>tblProdukteKategorien <\/b>exportiert haben, entfernen.<\/p>\n<h2>Flexible einsetzbare Prozeduren<\/h2>\n<p>Fehlt nur noch, dass Sie diese Prozeduren einsetzen k&ouml;nnen, um Ihre eigenen mehrwertigen Felder in richtige Beziehungen umzuwandeln. Den Aufwand, diese Funktionen nun an die bei Ihnen oder bei Ihrem Kunden vorhandene Tabelle mit mehrwertigem Feld anzupassen, ist hoch und fehleranf&auml;llig. Dann bauen wir lieber gleich zwei passende Prozeduren. Au&szlig;erdem statten wir diese Prozeduren gleich noch mit einem Extra aus: Sie nehmen Ihnen auch noch das Erstellen der Lookup-Tabelle und der Verkn&uuml;pfungstabelle ab.  Die erste Prozedur hei&szlig;t <b>MehrwertigeWertlisteInTabelle <\/b>und wird wie folgt aufgerufen:<\/p>\n<pre>MehrwertigeWertlisteInTabelle \"tblProdukte\", \"Kategorien\", \"tblKategorien\", \"KategorieID\", \"Kategorie\"<\/pre>\n<p>Sie ist in Listing 3 abgebildet. Gegen&uuml;ber der Prozedur <b>KategorienInTabelle <\/b>enth&auml;lt sie noch zwei Anweisungen, die gleich noch die Tabelle zum Aufnehmen der Daten der Wertliste des mehrwertigen Feldes erstellt. Die zweite Prozedur hei&szlig;t <b>MehrwertigeWertlistenzuordnungInTabelle <\/b>und erwartet die Namen der ganzen beteiligten Tabellen und Felder als Parameter &#8211; wie in diesem Aufruf:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>MehrwertigeWertlisteInTabelle(strBasistabelle<span style=\"color:blue;\"> As String<\/span>, strBasisfeld<span style=\"color:blue;\"> As String<\/span>, _\r\n         strLookuptabelle<span style=\"color:blue;\"> As String<\/span>, strLookupPK<span style=\"color:blue;\"> As String<\/span>, strLookupfeld<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>strWerte<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strWertArray()<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngWert<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strWert<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     db.Execute \"CREATE TABLE \" & strLookuptabelle & \"(\" & strLookupPK & \" AUTOINCREMENT PRIMARY KEY, \" _\r\n         & strLookupfeld & \" Text(255) NOT NULL);\", dbFailOnError\r\n     db.Execute \"CREATE UNIQUE INDEX idx\" & strLookupfeld & \" ON \" & strLookuptabelle & \" (\" & strLookupfeld _\r\n         & \");\", dbFailOnError\r\n     strWerte = db.TableDefs(strBasistabelle).Fields(strBasisfeld).Properties(\"RowSource\")\r\n     strWertArray = <span style=\"color:blue;\">Split<\/span>(strWerte, \";\")\r\n     For lngWert = <span style=\"color:blue;\">LBound<\/span>(strWertArray) To <span style=\"color:blue;\">UBound<\/span>(strWertArray)\r\n         strWert = strWertArray(lngWert)\r\n         strWert = <span style=\"color:blue;\">Replace<\/span>(strWert, \"''\", \"''''\")\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         db.Execute \"INSERT INTO \" & strLookuptabelle & \"(\" & strLookupfeld & \") VALUES(\" & strWert & \")\", dbFailOnError\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> lngWert\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Lookuptabelle f&uuml;r die Werte des mehrwertigen Feldes erstellen und f&uuml;llen<\/span><\/b><\/p>\n<pre>MehrwertigeWertlistenzuordnungInTabelle \"tblProdukte\", \"ProduktID\", \"Kategorien\", \"tblKategorien\", \"KategorieID\", \"Kategorie\", \"tblProdukteKategorien\", \"ProduktKategorieID\", \"ProduktID\", \"KategorieID\"<\/pre>\n<p>Sie legt die Verkn&uuml;pfungstabelle an und stellt gleich noch die beiden Beziehungen zu der urspr&uuml;nglichen Tabelle und der neu erstellten Lookuptabelle her. Dazu m&uuml;ssen wir ausnahmsweise das ADODB-<b>Connection<\/b>-Objekt mit seiner <b>Execute<\/b>-Methode nutzen, da wir mit DAO-<b>Execute <\/b>keine L&ouml;sch- und Aktualisierungsweitergabe definieren k&ouml;nnen. Diese Prozedur finden Sie in Listing 4.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>MehrwertigeWertlistenzuordnungInTabelle(strBasistabelle<span style=\"color:blue;\"> As String<\/span>, strPKBasistabelle<span style=\"color:blue;\"> As String<\/span>, _\r\n         strLookupfeld<span style=\"color:blue;\"> As String<\/span>, strLookuptabelle<span style=\"color:blue;\"> As String<\/span>, strLookuptabellePK<span style=\"color:blue;\"> As String<\/span>, strLookuptabelleWert<span style=\"color:blue;\"> As <\/span>_\r\n         String, strMNTabelle<span style=\"color:blue;\"> As String<\/span>, strMNPK<span style=\"color:blue;\"> As String<\/span>, strMFK<span style=\"color:blue;\"> As String<\/span>, strNFK<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database, rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n     <span style=\"color:blue;\">Dim <\/span>strLookupwert<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>fld3<span style=\"color:blue;\"> As <\/span>DAO.Field3\r\n     <span style=\"color:blue;\">Dim <\/span>rstLookupwerte<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>lngPKID<span style=\"color:blue;\"> As Long<\/span>, lngLookupPKID<span style=\"color:blue;\"> As Long<\/span>, strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> cnn = CurrentProject.Connection\r\n     cnn.Execute \"CREATE TABLE \" & strMNTabelle & \"(\" & strMNPK & \" AUTOINCREMENT PRIMARY KEY, \" & strMFK _\r\n         & \" LONG NOT NULL, \" & strNFK & \" LONG NOT NULL);\"\r\n     cnn.Execute \"ALTER TABLE \" & strMNTabelle & \" ADD CONSTRAINT fk_\" & strMFK & \" FOREIGN KEY (\" & strMFK _\r\n         & \") REFERENCES \" & strBasistabelle & \" (\" & strPKBasistabelle & \") ON DELETE CASCADE;\"\r\n     cnn.Execute \"ALTER TABLE \" & strMNTabelle & \" ADD CONSTRAINT fk_\" & strNFK & \" FOREIGN KEY (\" & strNFK _\r\n         & \") REFERENCES \" & strLookuptabelle & \" (\" & strNFK & \") ON DELETE NO ACTION;\"\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT \" & strPKBasistabelle & \", \" & strLookupfeld & \" FROM \" & strBasistabelle, _\r\n         dbOpenDynaset)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         lngPKID = rst(strPKBasistabelle)\r\n         <span style=\"color:blue;\">Set<\/span> fld3 = rst(strLookupfeld)\r\n         <span style=\"color:blue;\">Set<\/span> rstLookupwerte = fld3.Value\r\n         <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstLookupwerte.EOF\r\n             strLookupwert = rstLookupwerte!Value\r\n             lngLookupPKID = Nz(DLookup(strLookuptabellePK, strLookuptabelle, strLookuptabelleWert & \" = ''\" _\r\n                 & strLookupwert & \"''\"), 0)\r\n             <span style=\"color:blue;\">If <\/span>lngLookupPKID = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 If <span style=\"color:blue;\">MsgBox<\/span>(\"Wert ''\" & strLookupwert & \"'' noch nicht vorhanden. Anlegen?\", vbYesNo + vbExclamation, _\r\n                         \"Fehlender Wert\") = vbYes Then\r\n                     strLookupwert = <span style=\"color:blue;\">Replace<\/span>(strLookupwert, \"''\", \"''''\")\r\n                     db.Execute \"INSERT INTO \" & strLookuptabelle & \"(\" & strLookuptabelleWert & \") VALUES(''\" _\r\n                         & strLookupwert & \"'')\", dbFailOnError\r\n                     lngLookupPKID = db.OpenRecordset(\"SELECT @@IDENTITY\").Fields(0)\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngLookupPKID = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n                 db.Execute \"INSERT INTO \" & strMNTabelle & \"(\" & strMFK & \", \" & strNFK & \") VALUES(\" & lngPKID _\r\n                     & \", \" & lngLookupPKID & \")\", dbFailOnError\r\n                 <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             rstLookupwerte.Move<span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Loop<\/span>\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Erstellen und F&uuml;llen der Verkn&uuml;pfungstabelle f&uuml;r die m:n-Beziehung zwischen der Ausgangstabelle und der neuen Lookuptabelle<\/span><\/b><\/p>\n<h2>Anderes Beispiel: Fahrzeuge und Ausstattungen<\/h2>\n<p>Wir haben noch eine Tabelle <b>tblFahrzeuge <\/b>mit dem mehrwertigen Feld <b>Ausstattungen <\/b>in der Beispieldatenbank vorbereitet. Mit dem folgenden Aufruf erstellen und f&uuml;llen wir die Tabelle <b>tblAusstattungen<\/b>:<\/p>\n<pre>MehrwertigeWertlisteInTabelle \"tblFahrzeuge\", \"Ausstattungen\", \"tblAusstattungen\", \"AusstattungID\", \"Ausstattung\"<\/pre>\n<p>Und diese legt die Verkn&uuml;pfungstabelle an:<\/p>\n<pre>MehrwertigeWertlistenzuordnungInTabelle \"tblFahrzeuge\", \"FahrzeugID\", \"Ausstattungen\", \"tblAusstattungen\", \"AusstattungID\", \"Ausstattung\", \"tblFahrzeugeAusstattungen\", \"FahrzeugAusstattungID\", \"FahrzeugID\", \"AusstattungID\"<\/pre>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Eine wichtige Erkenntnis ist: Wer gar nicht erst mehrwertige Felder auf Basis von Wertlisten in seine Tabellen integriert, spart sich sp&auml;testens bei der Migration zum SQL Server einige Arbeit. Aber auch die M&ouml;glichkeit, Daten aus der als Datensatzherkunft verwendeten Wertliste entfernen zu k&ouml;nnen, w&auml;hrend dieser Wert noch im entsprechenden Feld verbleiben kann, ist irritierend. Dem sollte man sich besser nicht aussetzen, wenn man nicht R&uuml;ckfragen von Benutzern erhalten m&ouml;chte, warum ein Wert in dem einen Datensatz vorhanden ist, im anderen aber gar nicht zur Auswahl steht.<\/p>\n<p>Allerdings gibt es auch einen wichtigen Grund, warum Entwickler &uuml;berhaupt mit Feldern wie dem mehrwertigen Feld arbeiten: Der Benutzer kann damit sehr einfach &uuml;ber Kontrollk&auml;stchen die Eintr&auml;ge der Wertliste aus- und wieder abw&auml;hlen. Dies ist sonst nicht so einfach zu realisieren. Wir wollen jedoch in einem weiteren Beitrag namens <b>m:n-Daten wie im mehrwertigen Feld selektieren <\/b>(<b>www.access-im-unternehmen.de\/1424<\/b>) eine M&ouml;glichkeit dazu vorstellen.<\/p>\n<p>Hier haben wir jedoch erst einmal gezeigt, wie man bereits angelegte und gegebenenfalls mit vielen Daten gef&uuml;llte mehrwertige Felder auf Basis von Wertlisten in eine g&auml;ngige Struktur zum Verwalten von Daten in m:n-Beziehungen umwandeln kann.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>MehrwertigeFelderLoswerden.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/B6BD241A-3C43-49E0-952B-94995801C662\/aiu_1493.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mehrwertige Felder sind eine Erfindung von Microsoft, um den Umgang mit Datenkonstrukten, bei denen f&uuml;r ein Feld mehrere Werte ausgew&auml;hlt werden k&ouml;nnen, zu vereinfachen. In einem mehrwertigen Feld k&ouml;nnen wir aus einer Liste von Werten, die entweder aus einer Wertliste oder aus einer anderen Tabelle stammen, keinen, einen oder mehrere Eintr&auml;ge ausw&auml;hlen. Aus einer verkn&uuml;pfen Tabelle mehrere Werte zuordnen? Das h&ouml;rt sich ja eigentlich nach dem Einsatzzweck einer m:n-Beziehung an. Genau das bildet Microsoft intern ab. Allerdings funktioniert das nur innerhalb des Access-Biotops. Sollen die Daten einmal zum SQL Server oder einer anderen Datenbank wandern, wird es kompliziert. Hier k&ouml;nnen wir solche Konstrukte n&auml;mlich nicht mehr einfach abbilden &#8211; wir m&uuml;ssen diese also ersetzen. Wie wir die mehrwertigen Felder loswerden, zeigen wir in diesem Beitrag.<\/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,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662024,66042024,44000021],"tags":[],"class_list":["post-55001493","post","type-post","status-publish","format-standard","hentry","category-662024","category-66042024","category-Tabellen_und_Datenmodellierung"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Mehrwertige Felder mit Wertliste loswerden - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Mehrwertige Felder mit Wertliste loswerden\" \/>\n<meta property=\"og:description\" content=\"Mehrwertige Felder sind eine Erfindung von Microsoft, um den Umgang mit Datenkonstrukten, bei denen f&uuml;r ein Feld mehrere Werte ausgew&auml;hlt werden k&ouml;nnen, zu vereinfachen. In einem mehrwertigen Feld k&ouml;nnen wir aus einer Liste von Werten, die entweder aus einer Wertliste oder aus einer anderen Tabelle stammen, keinen, einen oder mehrere Eintr&auml;ge ausw&auml;hlen. Aus einer verkn&uuml;pfen Tabelle mehrere Werte zuordnen? Das h&ouml;rt sich ja eigentlich nach dem Einsatzzweck einer m:n-Beziehung an. Genau das bildet Microsoft intern ab. Allerdings funktioniert das nur innerhalb des Access-Biotops. Sollen die Daten einmal zum SQL Server oder einer anderen Datenbank wandern, wird es kompliziert. Hier k&ouml;nnen wir solche Konstrukte n&auml;mlich nicht mehr einfach abbilden - wir m&uuml;ssen diese also ersetzen. Wie wir die mehrwertigen Felder loswerden, zeigen wir in diesem Beitrag.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2024-08-01T09:53:20+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg02.met.vgwort.de\/na\/962a5efa84634ca0aa946ec3fea3dbfa\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"23\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Mehrwertige Felder mit Wertliste loswerden\",\"datePublished\":\"2024-08-01T09:53:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/\"},\"wordCount\":3863,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/962a5efa84634ca0aa946ec3fea3dbfa\",\"articleSection\":[\"2024\",\"4\\\/2024\",\"Tabellen und Datenmodellierung\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/\",\"name\":\"Mehrwertige Felder mit Wertliste loswerden - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/962a5efa84634ca0aa946ec3fea3dbfa\",\"datePublished\":\"2024-08-01T09:53:20+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/962a5efa84634ca0aa946ec3fea3dbfa\",\"contentUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/962a5efa84634ca0aa946ec3fea3dbfa\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mehrwertige_Felder_mit_Wertliste_loswerden\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Mehrwertige Felder mit Wertliste loswerden\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Mehrwertige Felder mit Wertliste loswerden - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/","og_locale":"de_DE","og_type":"article","og_title":"Mehrwertige Felder mit Wertliste loswerden","og_description":"Mehrwertige Felder sind eine Erfindung von Microsoft, um den Umgang mit Datenkonstrukten, bei denen f&uuml;r ein Feld mehrere Werte ausgew&auml;hlt werden k&ouml;nnen, zu vereinfachen. In einem mehrwertigen Feld k&ouml;nnen wir aus einer Liste von Werten, die entweder aus einer Wertliste oder aus einer anderen Tabelle stammen, keinen, einen oder mehrere Eintr&auml;ge ausw&auml;hlen. Aus einer verkn&uuml;pfen Tabelle mehrere Werte zuordnen? Das h&ouml;rt sich ja eigentlich nach dem Einsatzzweck einer m:n-Beziehung an. Genau das bildet Microsoft intern ab. Allerdings funktioniert das nur innerhalb des Access-Biotops. Sollen die Daten einmal zum SQL Server oder einer anderen Datenbank wandern, wird es kompliziert. Hier k&ouml;nnen wir solche Konstrukte n&auml;mlich nicht mehr einfach abbilden - wir m&uuml;ssen diese also ersetzen. Wie wir die mehrwertigen Felder loswerden, zeigen wir in diesem Beitrag.","og_url":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/","og_site_name":"Access im Unternehmen","article_published_time":"2024-08-01T09:53:20+00:00","og_image":[{"url":"http:\/\/vg02.met.vgwort.de\/na\/962a5efa84634ca0aa946ec3fea3dbfa","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"23\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Mehrwertige Felder mit Wertliste loswerden","datePublished":"2024-08-01T09:53:20+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/"},"wordCount":3863,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/#primaryimage"},"thumbnailUrl":"http:\/\/vg02.met.vgwort.de\/na\/962a5efa84634ca0aa946ec3fea3dbfa","articleSection":["2024","4\/2024","Tabellen und Datenmodellierung"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/","url":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/","name":"Mehrwertige Felder mit Wertliste loswerden - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/#primaryimage"},"thumbnailUrl":"http:\/\/vg02.met.vgwort.de\/na\/962a5efa84634ca0aa946ec3fea3dbfa","datePublished":"2024-08-01T09:53:20+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/#primaryimage","url":"http:\/\/vg02.met.vgwort.de\/na\/962a5efa84634ca0aa946ec3fea3dbfa","contentUrl":"http:\/\/vg02.met.vgwort.de\/na\/962a5efa84634ca0aa946ec3fea3dbfa"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Mehrwertige_Felder_mit_Wertliste_loswerden\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Mehrwertige Felder mit Wertliste loswerden"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001493","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55001493"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001493\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001493"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001493"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001493"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}