Zur Navigation

Normalisierung von Datenbanktabellen [2]

am Beispiel von Datenbanktabellen für ein Wörterbuch

11 Jörg

Aber das heißt schon falls der Primärschlüssel aus nur einer Spalte besteht, dann ist die Regel automatisch immer erfüllt?

Wenn sich die übrigen Felder vollständig auf diesen beziehen. In dem von dir erwähnten Kapitel von Wikibooks sind ja Beispiele aufgeführt, u.a. dieses:

Aus den Verträgen werden alle Angaben des Vertragspartners entfernt und in eine Tabelle Versicherungsnehmer übertragen. Der Primärschlüssel besteht nur noch aus der Spalte Vertrag. Die Spalte Kundennummer ist nur noch ein Fremdschlüssel als Verweis auf die neue Tabelle Versicherungsnehmer.

Also wird nicht nur der Primärschlüssel vereinfacht, indem die Spalte Kundennummer zum Fremdschlüssel wird, auch die dazugehörigen Datenfelder müssen natürlich in die neue Tabelle ausgelagert werden. Wenn ersteres der Fall ist, letzteres aber nicht, dann ist die Tabelle nicht vollständig normalisiert.

Außerdem:

http://www.php-faq.de/q-mysql-eignung.html

Das spricht wohl ganz klar für eher weniger und dafür viel größeren Tabellen.

Der Artikel nimmt Bezug auf die Anzahl von Datensätzen. Mit einer Normalisierung reduzierst du nicht die Anzahl der Datensätze, sondern die der Datenfelder (in der Ausgangstabelle).

14.11.2015 16:06

12 Ranma (Gast)


Also wird nicht nur der Primärschlüssel vereinfacht, indem die Spalte Kundennummer zum Fremdschlüssel wird, auch die dazugehörigen Datenfelder müssen natürlich in die neue Tabelle ausgelagert werden. Wenn ersteres der Fall ist, letzteres aber nicht, dann ist die Tabelle nicht vollständig normalisiert.

Vollständig heißt, dann ist auch schon die fünfte Regel (also die dritte Normalform) erfüllt?

Wenn Informationen, die sich auf einen bestimmten Schlüssel beziehen, nicht in der selben Tabelle stehen wie der Schlüssel, dann sind sie nichtmehr geordnet. Dann könnte man sie sowieso nicht wiederfinden...


Der Artikel nimmt Bezug auf die Anzahl von Datensätzen. Mit einer Normalisierung reduzierst du nicht die Anzahl der Datensätze, sondern die der Datenfelder (in der Ausgangstabelle).

Bei der Planung der Tabellen muß ich beides berücksichtigen. Es ist sicherlich nicht besonders sinnvoll, erst einen Teil der Bedingungen zu berücksichtigen und danach alles nochmal zu ändern, weil ein anderer Teil der Bedingungen nicht berücksichtigt ist. So gesehen hätte ich mich auch vorher um die Normalisierung kümmern sollen, nur wollte ich erstmal wissen, ob ich überhaupt mit MySQL klarkomme.

Außerdem steht im Wikibook der Hinweis, kleine Tabellen sind zu bevorzugen. Das bezieht sich dort nur auf die Anzahl der Spalten, aber ist nicht so eindeutig formuliert.

In der SQL-Syntax steht manchmal FOREIGN KEY, aber das ist nicht das, was hier mit Fremdschlüssel (Kana_id und Kanji_id im Beitrag #6) gemeint ist? Weil Kana_id und Kanji_id sind eigentlich nur Inhalte von Datenbankfeldern und der PHP-FAQ-Artikel sagt, daß MySQL keine Fremdschlüssel prüft, während andere Datenbanken das tun...
Ranma

15.11.2015 03:47

13 Jörg

Zitat von Ranma
Also wird nicht nur der Primärschlüssel vereinfacht, indem die Spalte Kundennummer zum Fremdschlüssel wird, auch die dazugehörigen Datenfelder müssen natürlich in die neue Tabelle ausgelagert werden. Wenn ersteres der Fall ist, letzteres aber nicht, dann ist die Tabelle nicht vollständig normalisiert.

Vollständig heißt, dann ist auch schon die fünfte Regel (also die dritte Normalform) erfüllt?

Nein, der Umkehrschluss gilt hier nicht :) es handelt sich um eine von mehreren notwendigen Bedingungen, nicht um eine hinreichende Bedingung.

Wenn Informationen, die sich auf einen bestimmten Schlüssel beziehen, nicht in der selben Tabelle stehen wie der Schlüssel, dann sind sie nichtmehr geordnet. Dann könnte man sie sowieso nicht wiederfinden...

Ich dachte hier eher an Fälle, in denen der Schlüssel gar nicht vorhanden ist. Man muss halt auch schauen, welche Datenfelder man einem (noch nicht vorhandenen) Schlüssel zuordnen und dann auslagern kann.

In der SQL-Syntax steht manchmal FOREIGN KEY, aber das ist nicht das, was hier mit Fremdschlüssel (Kana_id und Kanji_id im Beitrag #6) gemeint ist?

Man kann auf diese Fremdschlüssel einen FOREIGN KEY Constraint anwenden, vorausgesetzt die betreffende Engine verfügt über dieses Feature.

Mit MyIsam geht das meines Wissens nicht, mit InnoDB dagegen schon.

16.11.2015 14:55

14 Ranma (Gast)

Die zweite Regel und die fünfte Regel scheinen mir inzwischen so ziemlich das Gleiche zu verlangen. Jedenfalls sollten sie beide erfüllt sein, sofern man Werte nur noch über deren jeweiligen Schlüssel einander zuordnet.

Aber was mache ich mit längeren Eintragen folgender Art?


'Aus dem Leben eines Taugenichts' (von Eichendorff / Werktitel) [lit.]    	'The Life of a Good-for-Nothing' (by Eichendorff / work title)

'Beim Bau der Chinesischen Mauer' (von Kafka / Werktitel) [lit.]	'The Great Wall of China' (by Kafka / work title)

zwischen zwei Möglichkeiten schwanken          	to be unable to decide between two possibilities

zwischen zwei Stühlen sitzen [übtr.]	            to sit on the fence; to have fallen between two stools [fig.]

Zwischenabrechnung {f} [fin.]	interim financial statement

Zerlege ich die in einzelne Wörter und bilde dann in einer weiteren Tabelle für Beispiele mit deren Primärschlüsseln Sätze aus Zahlen? Würde ich das dann auch mit dem letzten der fünf Einträge machen?

Ich befürchte auch fehlerhafte Zuordnungen dadurch, daß die Zuordnungen von Übersetzungen fast nie eineindeutig sind. (Google kann nichtmal die eigenen „Übersetzungen“ rückübersetzen.)

Ferner ist mir noch nicht klar, in welche Tabelle zusätzliche Anmerkungen kommen, wenn Deutsch und Fremdsprache auf verschiedene Tabellen verteilt sind. Dazu Beispiele aus meiner Chinesisch-Tabelle:


506 	呵	呵	a1 	Umschreibung der Silbe “A” in ausländischen Namen	NULL	NULL

504 	腌	腌	a1 	gebundenes Morphem in 腌臜: unsauber   	Dialekt, u.E., S	醃臜 腌臜 -- unsauber

510 	阿巴丹	阿巴丹	a1 ba1 dan1 	Abadan  	u.E., Eig, Geo	NULL

495 	A片	A片	A pian4 	Pornofilm, Film für Erwachsene  	A=Adults, u.E.	NULL

In den Spalten stehen:
1. Primärschlüssel, nachträglich eingefügt.
2. traditionelle chinesische Schriftzeichen.
3. von den Kommunisten reformierte chinesische Schriftzeichen. (Sie sind in den Beispielen zufällig gleichgeblieben, es wurden nur „komplizierte“ Schriftzeichen „vereinfacht“.)
4. Pinyin, also die von der chinesischen Regierung abgesegnete Umschrift, die zugleich über die Aussprache Auskunft gibt.
5. Deutsche Übersetzung.
6. Anmerkungen, welcher Art auch immer.
7. Beispiele, die bei manchen Begriffen in die Übersetzungen geschrieben waren, aber meistens ein leerer Eintrag.

Bei #506 ist eigentlich schon merkwürdig, daß als Übersetzung etwas da steht, das eigentlich besser in die Anmerkungen paßt. Aber dann wäre die Übersetzung leer gewesen und es gäbe keinen Eintrag. Also schon in der Liste nicht, ich habe nichts verändert. Das hätte in einer Tabelle nur für Deutsch doch garkeinen Sinn?

#504 zeigt ein deutsches Wort in der Anmerkung, aber kein Chinesisches, daher könnte es sinnvoller sein, die Anmerkung in der Tabelle für Chinesisch unterzubringen. Es ist eine Erklärung für deutsche Benutzer und würde auf der deutschen Seite nichtmal stimmen. Es gibt dann aber wiederum in anderen Einträgen Anmerkungen auf Chinesisch. Die müßten dann in die Tabelle für Deutsch. Dafür müßte mein Skript die jeweils in der Spalte verwendete Sprache erkennen können!

Nur Abkürzungen würden die Tabellen für ein mehrsprachiges Wörterbuch viel geeigneter machen, während ausführlichere Anmerkungen und auch die Abkürzungen manchmal aus dem Deutschen und manchmal aus dem Englischen die Tabellen eher für ein nur zweisprachiges Wörterbuch geeignet machen. Die Anmerkungen für #510 müßten in beide Tabellen. Vielleicht in eine eigene Tabelle, aber wie gesagt würden manche Anmerkungen, wie die von #504 (die für Chinesisch oder für die Kombination stimmt) eigentlich nicht mehr stimmen.

Die Anmerkung von #495 verrät, daß der chinesische Begriff aus einem Englischem abgeleitet ist. Auf den deutschen trifft das nicht zu. Für den deutschen Begriff ist die Anmerkung unnötig. Beim chinesischen Begriff würde man sich zunächst über den lateinischen Buchstaben wundern und den ohne die Anmerkung möglicherweise für einen fehlerhaften Eintrag halten.

Wie müßten die Spalten auf weitere Tabellen verteilt werden? Ich bin mir lediglich sicher, daß die zweite, dritte und vierte Spalte in einer Tabelle für Chinesisch zusammengehalten werden sollten... (Obwohl sie auch nicht eineindeutig sind, wie der Vergleich der Aussprache in der vierten Spalte von #504 und #506 zeigt.)
Ranma

18.11.2015 03:00

15 Jörg

Zerlege ich die in einzelne Wörter und bilde dann in einer weiteren Tabelle für Beispiele mit deren Primärschlüsseln Sätze aus Zahlen? Würde ich das dann auch mit dem letzten der fünf Einträge machen?

Was die Semantik anbelangt, ist der Ausdruck 'zwischen zwei Stühlen sitzen' wohl atomar. Wenn man den Ausdruck in die einzelnen Bestandteile zerlegt, geht die metaphorische Bedetung verloren. Vielleicht kann man hier vom Lexem im weiteren Sinne reden, welches auch Phrasen mit einschließen kann:

https://de.wikipedia.org/wiki/Lexem#Lexem_im_weiteren_Sinn

Bei der Chinesisch-Tabelle würde ich auch sagen, dass man die Anmerkungen in einer separaten Spalte unterbringen sollte, wobei die Übersetzung dann den Wert NULL erhält. Das Problem hierbei ist wohl, dass es kein Kriterium gibt, anhand dessen man automatisiert eine Übersetzung von einer Anmerkung unterscheiden kann.

18.11.2015 21:11

16 Ranma (Gast)

Noch ein paar Beispieleinträge:


Caesium {n}; Cesium {n} (Zäsium) /Cs/ [chem.]		caesium [Br.]; cesium [Am.]

Calcium (Kalzium) {n} /Ca/ [chem.]		calcium

Californium (Kalifornium) {n} /Cf/ [chem.]		californium

Chile {n} /CL/ (Kfz: /RCH/) [geogr.]		Chile

Praktisch jedes Sonderzeichen wird in mehr als einer Funktion verwendet. Besonders unsinnig finde ich es, Alternativen zum Teil per ; abzutrennen und zum Teil in runden Klammern hinzuzufügen. Sogar die eckigen Klammern sind auf der deutschen Seite auf alle Alternativen bezogen, auf der englischen nur auf die durch ; abgetrennten Teile. Das ist aber nicht spezifisch für die Seiten, was noch ginge, sondern spezifisch für einzelne Einträge. Ich gewinne langsam den Eindruck, daß die Einträge so aufgebaut sind, daß sie sich nicht atomisieren lassen.

Aber falls ich es so ließe, dann müßte hinterher mein Wörterbuchprogramm doch irgendwie noch damit klarkommen.

In der Datei gab es übrigens noch :: und | als Trennzeichen. Deshalb hatte ich erstmal die Einträge so weit zerlegt wie das einfach war, um das hinter mich zu bringen. Aber jetzt brauche ich deswegen passende Anweisungen, um die Zeichenketten, die schon in der Datenbank sind, noch weiterzubehandeln. In SQL gibt es passende. Sie tun allerdings nicht immer das, was ich mir von ihnen erwarte. Vor allem INSTR() soll eigentlich die Funktionen mehrere PHP-Anweisungen auf sich vereinen, aber ich kann nur einzelne Zeichen damit finden. Hole ich die einzelnen Einträge wieder aus der Datenbank, dann kann ich sie mit PHP weiterbearbeiten. Das dauert nur sehr lange. Bedingungen gleich in der Query werden mit einem WHERE-Teil angegeben, aber dadurch werden immer möglichst viele Einträge gefunden. Also möglichst viel auf einmal verarbeitet. Welche Möglichkeit ist besser? Am besten fände ich eine Schleifenkonstruktion in SQL, die alle Einträge nacheinander abarbeitet. Das wäre kaum eine Umstellung von der gewohnten Vorgehensweise, aber ginge sehr viel schneller...
Ranma

21.11.2015 06:00

17 Jörg

Aber jetzt brauche ich deswegen passende Anweisungen, um die Zeichenketten, die schon in der Datenbank sind, noch weiterzubehandeln. In SQL gibt es passende. Sie tun allerdings nicht immer das, was ich mir von ihnen erwarte. Vor allem INSTR() soll eigentlich die Funktionen mehrere PHP-Anweisungen auf sich vereinen, aber ich kann nur einzelne Zeichen damit finden. Hole ich die einzelnen Einträge wieder aus der Datenbank, dann kann ich sie mit PHP weiterbearbeiten.

Wie schauen denn die PHP-Anweisungen konkret aus, die du durch SQL-Code ersetzen möchtest? und wie ein Datensatz, der damit gefunden bzw. bearbeitet werden soll?

21.11.2015 14:07 | geändert: 21.11.2015 14:07

18 Ranma (Gast)

Da bin ich mir noch nicht sicher. Die Verwendung von Sonderzeichen in mehreren unterschiedlichen Bedeutungen in den Einträgen macht die Sache etwas knifflig. Alle jene Sonderzeichen, die in Klammern jeglicher Art stehen, erstmal komplett zu verschonen, wäre ein guter Anfang. Ich würde das über strpos() lösen, also alles zwischen der Position von '(' und der Position von ')' ausnehmen, wenn die Klammern nicht auch geschachtelt auftreten würden...

Darüber hinaus bin ich bei allen Listen auf nichtgeschlossene Klammern gestoßen. Auch das macht es schwieriger. Also muß ich wohl erstmal ein Muster finden, das funktioniert. SQL beherrscht wohl viel weniger Reguläre Ausdrücke als PHP, die dabei helfen könnten?
Ranma

22.11.2015 06:05

19 Jörg

Benötigst du die String- bzw. Regex-Funktionen im SELECT- oder im WHERE-Statement? ersteres lässt sich denke auch recht unproblematisch in den PHP-Code auslagern. In dem Fall geht es ja nur darum, die zurückgegebenen Felder nachzubearbeiten.

23.11.2015 14:01

20 Ranma (Gast)

Die Box zur direkten Eingabe von SQL-Anweisungen in phpMyAdmin ist erstaunlich idiotensicher. Ich habe festgestellt, daß ich da höchstens mal noch ein, zwei Syntaxfehler entfernen muß, aber dann macht MySQL genau das, was ich mir vorgestellt hatte. Das geht sogar sehr schnell. TRIM() oder SUBSTRING_INDEX() sind vergleichbaren Funktionen in PHP überlegen. Mir fehlen vor allem Funktionen wie substr_count() um die Anzahl von Klammern in einem String zu bestimmen und so feststellen zu können, ob die Klammern geschlossen sind und welche Zeichenketten sich darin befinden. Natürlich kommen auch Klammern innerhalb von Klammern vor oder eingeklammerte Ausdrücke sowohl am Anfang als auch am Ende eines Eintrages.

Weiterhin bekomme ich es nicht hin, daß Informationen aus einer Tabelle geholt und in eine andere Tabelle eingetragen werden. Bei dem Versuch beschwerte sich MySQL darüber, daß mehr als ein PRIMARY KEY vorhanden wäre.
Ranma

25.11.2015 08:34