Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Datenbank Primary Key (https://www.delphipraxis.net/152544-datenbank-primary-key.html)

JoltinJoe 26. Jun 2010 13:14

Datenbank: Firebird • Version: 2.1.2.18118-0 • Zugriff über: InterBase

Datenbank Primary Key
 
Hey ;)

Ich beschäftige mich zur Zeit mit Datenbanken und habe hier auch einiges über Primary Key und doppelten Einträgen gelesen, jedoch bleibt jetzt noch eine Frage offen:

In wie fern ist der Primary Key gut um Duplikate auszuschließen: (FELD1 soll keine Duplikate enthalten)

Ich lege den PK auf das Feld1. Jetzt füge ich den Wert "TEST" hinzu. Danach füge ich den Wert "test" hinzu. Beide Werte wurden erfolgreich hinzugefügt. Nur wenn ich erneut versuche "TEST" oder "test" hinzuzufügen dann bekomme ich eine Fehlermeldung auf Grund des Duplikats. Wie kann ich das ganze Case Insensitive gestalten ? Ich möchte das mein DBMS keinen Unterschied zwischen Groß- und Kleinschreibung macht.

Code:
CREATE TABLE MYTABLE(FELD1 varchar(30) PRIMARY KEY, FELD2 varchar(30));
bYe :)

rapante 26. Jun 2010 13:21

AW: Datenbank Primary Key
 
Moin,
das Thema wird auch gerade hier diskutiert.
Da ist bestimmt eine Lösung für dich dabei.

JoltinJoe 26. Jun 2010 13:24

AW: Datenbank Primary Key
 
Das Thema habe ich bereits gelesen und nein, ehrlich gesagt finde ich da keine Lösung für mich.

DeddyH 26. Jun 2010 13:31

AW: Datenbank Primary Key
 
Das kommt auch nicht in Frage?

JoltinJoe 26. Jun 2010 13:35

AW: Datenbank Primary Key
 
Das hört sich irgendwie nach "Workaround" an und du selber sagst ja das es ab FB 2.1 nicht mehr notwendig ist... Also will ich nicht zu Anfang schon tricksen ;)

Ich könnte auch einfach meine Einträge auf ein Niveau bringen bevor ich sie hinzufüge aber das wäre auch nur ein Workaround ..


bYe :)

DeddyH 26. Jun 2010 13:40

AW: Datenbank Primary Key
 
Nunja, andererseits nehme ich persönlich lieber einen zuverlässig funktionierenden Workaround, als tagelang nach einer "sauberen" Lösung zu suchen. Außerdem würde ich persönlich kein VarChar-Feld als PK definieren (obwohl das natürlich nicht verboten oder verwerflich ist), sondern immer ein künstliches Feld, das per Generator-/Trigger-Paar automatisch befüllt wird. Aber das ist sicher Ansichtssache.

JoltinJoe 26. Jun 2010 13:44

AW: Datenbank Primary Key
 
Hmm naja also ich möchte in diesem Feld keine Duplicates also hab ich das als PK definiert.

Kann man einem Feld nicht eine Case Eigenschaft verpassen ?

DeddyH 26. Jun 2010 13:55

AW: Datenbank Primary Key
 
Vielleicht hilft Dir dieser Thread weiter.

JoltinJoe 26. Jun 2010 14:32

AW: Datenbank Primary Key
 
Hm ich dachte der Expression Index spielt nur bei einer Abfrage eine Rolle ? Ich frage ja nicht ab ob Duplicates vorhanden sind, das macht das DBMS von selber. ..Oder hab ich das falsch verstanden ?

fkerber 26. Jun 2010 15:11

AW: Datenbank Primary Key
 
Hi!

Du kannst auch Duplikate verhindern, ohne dass es sich bei diesem Feld um den PK handelt.
Das Zauberwort ist UNIQUE.
Vor allem kannst du auch mehrere UNIQUE-Felder haben, aber nur einen PK. Aber auch UNIQUE ist von Haus aus case-sensitive.


Grüße, Frederic

JoltinJoe 26. Jun 2010 16:44

AW: Datenbank Primary Key
 
Hm und welche Funktion hat dann der PK ? Also klar "die Daten sind dann leichter abrufbar" aber kann da jemand genauer drauf eingehen ? Hat das was mit der "Binären Suche" zu tun ?

Und zum Problem: Also es gibt keine Möglichkeit einem Feld die Eigenschaft CASE INSENSITIVE zu verschaffen ?

fkerber 26. Jun 2010 18:02

AW: Datenbank Primary Key
 
Der PK ist wie der Name sagt, ein Schlüssel - ein Schlüssel dient dazu, ein Tupel in einer Tabelle eindeutig zu identifizieren.

Dabei gibt es verschiedene Konzepte - ein Superschlüssel erfüllt einfach das o.g. - ein sog. Kandidatenschlüssel erfüllt das auch, ist aber zusätzlich minimal - d.h. man kann ihn nicht mehr kleiner machen, ohne, dass er nicht mehr Schlüssel wäre.

So, der primary key schlussenndlich ist ein an sich beliebig ausgewählter Kandidatenschlüssel. Besondere Bedeutung bekommt er, wenn es um Fremdschlüssel-zuweisungenn gibt...

Grüße, Frederic

idefix2 28. Jun 2010 10:39

AW: Datenbank Primary Key
 
Als Primary key kannst Du eine beliebige Kombination von Feldern definieren, einzige Voraussetzung ist, dass diese Feldkombination jeden Datensatz eindeutig identifiziert. Zum Primary key legt das DBS automatisch einen Index an, der natürlich Unique ist. In der Praxis empfiehlt es sich UNBEDINGT, in JEDER Tabelle ein künstliches, Trigger-befülltes Feld zu definieren, das Du als Primary Key hernimmst. Jede andere Vorgangsweise führt mit ziemlicher Sicherheit früher oder später zu Problemen.

Zusätzlich zum Primary key, für den das DBS automatisch einen Unique Index anlegt, kannst Du nach beliebige andere Indexe (oder sagt man Indizes?) anlegen, die den Zugriff auf die Datenbank über die entsprechenden Feldelemente beschleunigen. Ist so ein Index als Unique definiert, dann erlaubt das Datenbanksystem keine 2 Datensätze mit identischen Feldwerten in diesen Feldern. Der Unique Index kann auch berechnet sein, so kannst Du einen Unique Index auf UPPER(Feld) legen und damit eine Case-insensitive Feldeindeutigkeit erzwingen.

Die Eindeutigkeit des Zugriffs an einen Index zu koppeln, ist insofern sinnvoll, als ohne vorhandenen Index die Überprüfung auf Eindeutigkeit extrem langsam wäre. Aber im Prinzip dient der Index in erster Linie zum schnellen Auffinden von Datensätzen und quasi nur als Nebeneffekt kann über einen UNIQUE Index Eindeutigkeit erzwungen werden.

Das Problem eines berechneten Unique Index ist, dass er nur vor dem Speichern von Duplicates schützt, beim Zugriff auf die Daten aber nicht verwendet wird. Wenn Du also irgendwo in einer Abfrage des Feldes auf =, <, >, like oder dergleichen abfragst, ist diese Abfrage erst wieder case-sensitiv und liefert Dir das gewünschte Ergebnis nur, wenn Du Upper(Feld) mit Upper(Vergleichswert) vergleichst.

Seit Firebird 2 ist es aber problemlos möglich, einem Feld eine caseinsensitive (und sogar eine accent insensitive) "Collation" zuzuordnen. Damit wird sozusagen das Feld selbst caseinsensitiv gemacht. Wenn Du das machst, wird automatisch überall, wo der Inhalt des Feldes mit etwas anderem verglichen wird, ein Case-insensitiver Vergleich durchgeführt. Es gibt standardmässig in Firebird zwar nur ganz wenige case-insensitive Collations, aber es ist sehr einfach, eine solche zu definieren - siehe http://www.delphipraxis.net/1031544-post57.html.

Die Verwendung von Uppercase-Schattenfeldern in der Datenbank war früher der einzig mögliche Workaround, weil es damals mit den Möglichkeiten der Datenbanksysteme nicht anders ging, hat aber heute bei einer Datenbankneuentwicklung überhaupt nichts verloren.

shmia 28. Jun 2010 15:14

AW: Datenbank Primary Key
 
Zitat:

Zitat von JoltinJoe (Beitrag 1031742)
Hm und welche Funktion hat dann der PK

Ohne PK sind die Daten in einer Tabelle quasi "verloren".
Stell' Dir vor, du hast eine Tabelle in der einige Datensätze völlig gleich sind:
Code:
FeldA | Feld B | Feld C
=======================
430   | 14.70  | blau
590   | 20.00  | rot
430   | 14.70  | blau
Dich stört der doppelte Datensatz; du willst ihn löschen.
Mit SQL gibt es aber keine Chance nur einen der beiden Datensätze zu löschen.
Das gleiche Problem entsteht beim Editieren.
Über eine UPDATE-Anweisung würden immer beide Datensätze geändert.
Nur wenn eine Tabelle einen PK hat, kann garantiert werden, dass jeder Datensatz einzeln ansprechbar ist.

DeddyH 28. Jun 2010 17:06

AW: Datenbank Primary Key
 
Außerdem kommt der PK noch bei Detailtabellen zum Tragen. Hier muss der Master-Datensatz ja eindeutig identifizierbar sein.

idefix2 28. Jun 2010 17:15

AW: Datenbank Primary Key
 
Der Primary key ist aber nichts anderes als ein willkürlich ausgewählter eindeutiger Schlüssel. Wenn Du die Datensätze über unterschiedliche Schlüssel eindeutig identifizieren kannst, dann kannst Du theoretisch jede beliebige Kombination von Feldern, die die Datensätze eindeutig identifizieren, zum primary key ernennen. Früher hab ich das gelegentlioch so gehandhabt, es ist mir aber noch jedesmal später auf den Kopf gefallen. Deshalb die Empfehlung, als Primary Key prinzipiell ein künstliches Feld zu verwenden, das mit Hilfe eines insert-Triggers und eines Generators (neuerdings heisst das auch in Firebird - SQL Standard gemäss - Sequence) gesetzt wird.

DeddyH 28. Jun 2010 18:01

AW: Datenbank Primary Key
 
Das hat ja auch niemand bestritten. Ich persönlich verzichte allerdings gelegentlich auf einen Generator, wenn es sich um eine Auflösungstabelle einer m:n-Beziehung handelt. In dem Fall kann man IMO auch getrost die Kombination der beiden FKs als PK definieren. Wobei es natürlich auch nicht schadet, auch hier einen künstlichen Schlüsel zu erzeugen und die angesprochene Kombination einfach UNIQUE zu deklarieren. Wie man sieht gibt es hier mehrere Möglichkeiten.

idefix2 28. Jun 2010 21:16

AW: Datenbank Primary Key
 
Ja, Du hast schon Recht. Wenn es sich nur um eine Auflösungstabelle einer m:n-Beziehung handelt, könnte man sich das künstliche Feld samt Trigger wahrscheinlich sparen.

mkinzler 28. Jun 2010 21:35

AW: Datenbank Primary Key
 
Er schadet aber nicht und ermöglicht eine spätere Erweiterung

JoltinJoe 29. Jun 2010 05:44

AW: Datenbank Primary Key
 
Hm okay eine Sache ist noch unklar.

Wenn ich ein Feld_A habe und dieses als PK definieren will dann soll ich ein künstliches K_Feld_A erzeugen und einen Trigger auf das eigentliche Feld_A setzen. Danach kann ich K_Feld_A als PK definieren.

Und was soll das ganze ? Warum definiert man nicht gleich das Feld_A als PK ?

fkerber 29. Jun 2010 07:03

AW: Datenbank Primary Key
 
Hi!

Du sollst keinen Trigger auf Feld_A setzen. Ein Trigger ist einfach eine Funktion, die z.B. bei jedem Insert aufgerufen wird (in dem Fall hier vor dem Insert - ein sog. before-Trigger)

Machen wir mal ein prakt. Beispiel:
Du hast eine Tabelle "Adressdaten" mit den Feldern "Strasse, Hausnummer, PLZ, Ort, Land" - nach den Anforderungen deines Systems sind alle diese Felder nötig, um eine Adresse eindeutig zu identifizieren. Du müsstest also einen PK definieren, der über alle 5 Felder geht.
(Würdest du z.B. nur Strasse+Hausnummer nehmen würden diese 2 Einträge nicht gehen:
"Hauptstr., 22, 12345, Testort, Testland" und "Haupstr., 22, 98765, Musterstadt, Musterland".

Somit hast du jetzt einen ziemlich unhandlichen PK in der Hand.
Sagen wir mal, du hast eine Tabelle Person [Vorname, Nachname] (auch beide zusammen als PK) und willst der Person eine Adresse zuordnen - das Ganze als n:m-Beziehung (also mehrere Personen an einer Adresse, mehrere Adressen pro Person), dann musst du in der Tabelle, die diese Beziehung ausdrückt, die Schlüssel der beiden beteiligten Tabellen haben. D.h. du hast hier eine Mega-Tabelle mit 7 Attributen.

So, würdest du sowohl bei Person wie auch bei Adresse einen künstlichen PK erzeugt hast (fortlaufende Nummerierung), dann identifiziert das eindeutig. D.h. du brauchst in der Beziehunstabelle nur 2 Felder, die ID von Person und die ID von Adresse.

Ich hoffe, ich konnte etwas Licht ins Dunkle bringen. ;)


Liebe Grüße,
Frederic

JoltinJoe 29. Jun 2010 07:17

AW: Datenbank Primary Key
 
Jo alles klar das hab ich kapiert :)

Nochmal zu der Frage "Warum lassen sich Daten mit einem PK schneller abrufen?" : Das macht doch nur Sinn wenn in der Abfrage der abzurufende Schlüssel bekannt ist ?

mkinzler 29. Jun 2010 08:40

AW: Datenbank Primary Key
 
Das zusätzlich Feld wird zum PK. Das hat den Vorteil, dass die Werte im FELD_A später geändert werden können ohne dass Fremdschlüsselbeziehung zerstört werden bzw. angepasst ´werden müssten.

idefix2 29. Jun 2010 10:11

AW: Datenbank Primary Key
 
Es geht da nicht um "schneller".
Der PK muß Unique sein. Auch wenn im Moment iregend eine Feldkombination unique ist, muß das nicht immer so bleiben. Beispiel:

Du hast einen Unique Key: Name, Vorname, Wohnort.
Dein Programm funktioniert wunderbar, und greifst überall in Deinem Programm mit diesem primary Key auf die Tabelle zu. Jetzt kommst Du irgendwann drauf, dass es in Berlin zwei verschiedene Hans Meier gibt, die Du in Deiner Datenbank verwalten musst, und brauchst deshalb für die Eindeutigkeit noch zusätzlich das Feld Strasse. Dann musst Du überall in Deinem Programm in allen Abfragen den Zugriff auf die Datenbank anpassen, alle Fremdschlüssel, die in anderen Tabellen auf diese Tabelle verweisen, müssen geändert werden usw.
Wenn Du aber von vorneherein ein künstliches Feld als PK verwendest, bedeutet so eine Änderung nur minimalen Aufwand.

Hansa 29. Jun 2010 13:30

AW: Datenbank Primary Key
 
Zitat:

Zitat von JoltinJoe (Beitrag 1032193)
Jo alles klar das hab ich kapiert :)

Sicher ? Noch ein Beispiel :

Szenario 1 (ohne IDs) : folgende Tables werden für irgendein Programm gebraucht : Artikel, Lager, Statistik, Rechnung. Den 3 letzten müssen dann natürlich Artikel zugeordnet werden. OK, man nimmt die Art.Nr. Da stehen also jetzt in der Lager-,Statistik- und Rechnungstabelle z.B. Datensätze mit artnr = 100. Der User verspürt aber plötzlich Lust, für den entsprechenden Artikel artnr = 1000 zu verwenden. Was ist zu tun ? Die 3 vom Artikel abhängigen Tabellen müssen komplett nach artnr = 100 durchsucht werden und an allen Fundstellen durch artnr = 1000 ersetzt werden. Im Prinzip kann erst wenn alle auf 1000 gesetzt sind der entsprechende Artikel selbst von artnr = 100 auf 1000 geändert werden.

Szenario 2 (mit IDs) : Artikel kriegt zusätzlich eine ID. Und diese wird automatisch per Generator/Trigger hochgezählt. Dann ist sie sofort eindeutig. Auch die drei anderen Tabellen erhalten vorsichtshalber eine ID und auch (und jetzt kommt das Wichtige) eine IDart. Also steht da nicht mehr ein Feld artnr = 100, sondern das Feld IDart = 95 (bspw.). Die 95 stammt von dem Artikel mit Nr. 100, der die ID = 95 hat. Was muss hier jetzt bei Änderung der Art.Nr. von 100 auf 1000 gemacht werden ? Einfach das Feld Art.Nr. von 100 auf 1000 ändern. Das wars. Die 95 bleibt ja, wie sie ist. Für die Rechnung- usw. Tabellen, ist der Artikel dadurch immer noch eindeutig zu lokalisieren. Da braucht überhaupt nichts gemacht zu werden !

Man sieht hier sehr oft weggelassene IDs oder so was wie bereits gesagt : PK für Name und dann noch die Str. mitschleppen usw. Was aber, wenn in einem Haus 2 Meier wohnen ? Ich sage nur : Murphy lässt grüssen. :mrgreen: Mal ganz davon abgesehen, dass ein PK aus Name, Strasse, Ort oder womöglich noch mehr viel zu gross wird. ID hätte lediglich 4 Byte. :gruebel:

JoltinJoe 29. Jun 2010 14:45

AW: Datenbank Primary Key
 
Ja, wie schon erwähnt...das hab ich kapiert.

Ich war nur etwas verwirrt weil, anscheinend ein labersack, mal meinte "wenn du kein pk hast, dann wird es Ewigkeiten dauern einen String in deinem Feld zu finden" ...

mkinzler 29. Jun 2010 16:12

AW: Datenbank Primary Key
 
Wenn die Tabelle sehr groß ist, kann es schon dauern, wird dieses Feld dann zufällig zum PK, kann es schon schnneller werden ( wenn nicht auf like gesucht wird). Ich glaube aber er hat PK mit Index verwechselt/gleichgesetzt

JoltinJoe 29. Jun 2010 19:07

AW: Datenbank Primary Key
 
Hm ja möglicherweise. Aber auf einen Primärschlüssel wird doch automatisch ein Index gelegt? Möglicherweise hat er das verwechselt.

DeddyH 29. Jun 2010 19:10

AW: Datenbank Primary Key
 
Jedes PK-Feld wird automatisch indiziert, aber nicht jedes indizierte Feld wird automatisch PK (wie soll das auch funktionieren?).

JoltinJoe 30. Jun 2010 05:29

AW: Datenbank Primary Key
 
Ja, das hat auch keiner behauptet ;) Ich denke ich habe vorerst genug Informationen.. Danke !

bYe

Stevie 30. Jun 2010 06:22

AW: Datenbank Primary Key
 
Zitat:

Zitat von Hansa (Beitrag 1032310)
Szenario 1 (ohne IDs) : folgende Tables werden für irgendein Programm gebraucht : Artikel, Lager, Statistik, Rechnung. Den 3 letzten müssen dann natürlich Artikel zugeordnet werden. OK, man nimmt die Art.Nr. Da stehen also jetzt in der Lager-,Statistik- und Rechnungstabelle z.B. Datensätze mit artnr = 100. Der User verspürt aber plötzlich Lust, für den entsprechenden Artikel artnr = 1000 zu verwenden. Was ist zu tun ? Die 3 vom Artikel abhängigen Tabellen müssen komplett nach artnr = 100 durchsucht werden und an allen Fundstellen durch artnr = 1000 ersetzt werden. Im Prinzip kann erst wenn alle auf 1000 gesetzt sind der entsprechende Artikel selbst von artnr = 100 auf 1000 geändert werden.

Dafür gibts aber on update cascade foreign keys. (erwähn ich nur der Vollständigkeit halber, ich find die auch eher sinnlos)
Mich wundert übrigens, dass hier noch nicht das Wort Normalisierung gefallen ist (oder hab ichs überlesen?) 8-)

mkinzler 30. Jun 2010 08:42

AW: Datenbank Primary Key
 
Zitat:

Mich wundert übrigens, dass hier noch nicht das Wort Normalisierung gefallen ist (oder hab ichs überlesen?)
So in die Tiefe gehen wollten wird bisher noch nicht


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:32 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz