# Frage zu Datenbankmodellierung



## kossy (7. Jan 2012)

Hallo zusammen !

Hi Folks !

Ich habe mal eine Frage an euch zu dem Thema Datenbanken. Eigentlich sind es eher gesagt sogar vier ;-)

1. Ist es eigentlich möglich, dass man einen Primärschlüssel in einer Datenbanktabelle nur mit Buchstaben oder auch einem Mix aus Buchstaben versehen kann und dürfen diese dann auch nciht doppelt vorkommen?

2. Werde doppelte Primärschlssel nur berücksichtigt und geblockt, wenn ich die Datenbanktabellen mit Beziehungen versehe und Refentielle Integrität aktiviert habe?

3. Wie genau werden eigentlich in modernen Anwendungen Passwörter von Benutzern hinterlegt und gespeichert (welchen Datentyp hätte dann die entsprechende Zeile in einer Datenbanktabelle)?

4. Wie genau kann ich Zugriffsrechte für Benutzer auf bestimmte Tabelle festlege und so den Benutzer in seinen Ausführungen restriktiver gestalten?

Danke für eure Hilfestellungen !


----------



## California (7. Jan 2012)

Hallo Kossy,

1. der Primärschlüssel kann beliebige Typ(en) haben- CHAR, VARCHAR, INT,usw, es geht alles ausser BLOBS und CLOBS (Einträge mit unbegrenzter Länge) Der Primärschlüssel muss nicht aus einem Feld bestehen, sollte aber. Am Besten- für spätere Referenzen- nimmst Du ein "autogeneriertes" Integerfeld- d.h. jeder Satz bekommt dann automatisch einen Integer- Wert immer um 1 erhöht als PK. In der Anwendung solltest Du den PK verbergen, er wird immer (so machen wir's) nur programmintern für Referenzen, zum Ändern und Löschen verwendet. Neben dem PK kannst Du ja beliebig viele EINDEUTIGKEITS-Bedingungen vereinbaren, wenn Du das brauchst. Da sind dann Deine "gemischten" Keys bestens aufgehoben, ich nehme an, Du meinst sowas wie einen Menschenlesbaren Code.

2. Primärschlüssel sind IMMER eindeutig (sonst wären sie keine), unabhängig, ob Du darauf nochmal referenzierst oder nicht.

3. Passwörter kann man verschlüsseln (siehe Crypt..) und dann auch als String hinterlegen.

4. Das macht man mit Datenbankrollen - das sind sowas wie Benutzergruppen in Windows. Ein Benutzer bekommt eine Rolle zugeordnet, in der Rolle sind die Zugriffsrechte definiert (welche Tabellen er lesen, schreiben, löschen, ändern bzw. auch strukturell bearbeiten darf)

Gruß Stephan


----------



## Marcinek (7. Jan 2012)

kossy hat gesagt.:


> 1. Ist es eigentlich möglich, dass man einen Primärschlüssel in einer Datenbanktabelle nur mit Buchstaben oder auch einem Mix aus Buchstaben versehen kann und dürfen diese dann auch nciht doppelt vorkommen?



Genau.



kossy hat gesagt.:


> 2. Werde doppelte Primärschlssel nur berücksichtigt und geblockt, wenn ich die Datenbanktabellen mit Beziehungen versehe und Refentielle Integrität aktiviert habe?



Nein. Es muss lediglich ein Primärschlüssel sein. PKs haben i.d.r. keine referenzielle Integritätseigenschaft. Es sei den sie sind auch FK (Foraign keys) aber das hat nix mit ihrer Eigenschaft der eindeutigkeit zu tun.



kossy hat gesagt.:


> 3. Wie genau werden eigentlich in modernen Anwendungen Passwörter von Benutzern hinterlegt und gespeichert (welchen Datentyp hätte dann die entsprechende Zeile in einer Datenbanktabelle)?



MD5 hashwert eines Strings => varchar(255) 



kossy hat gesagt.:


> 4. Wie genau kann ich Zugriffsrechte für Benutzer auf bestimmte Tabelle festlege und so den Benutzer in seinen Ausführungen restriktiver gestalten?



Dies hängt von der Datenbank ab. Google nach table rights <db name>.


----------



## stareagle (7. Jan 2012)

Hallo,

zu den anderen Fragen wurde ja schon genug gesagt, aber zu den Passwörtern gebe ich noch mal meinen Senf dazu.



kossy hat gesagt.:


> Hallo zusammen !
> 
> 3. Wie genau werden eigentlich in modernen Anwendungen Passwörter von Benutzern hinterlegt und gespeichert (welchen Datentyp hätte dann die entsprechende Zeile in einer Datenbanktabelle)?



Passwörter sollten nicht im Klartext gespeichert. Üblicherweise speichert man nur den Hashwert des Passwortes. Dazu sollte man aber auch einen sicheren Hash-Algorithmus verwenden. MD5 gilt mittlerweile als unsicher, ebenso wie SHA-1. SHA-256 und SHA-512 dürften die sichersten sein. Wenn man wirklich richtig machen will, fügt man an die Passwörter noch ein zufallsgeneriertes Salt an, und speichert den Hash-Wert von Passwort mit angehängtem Salt und das Salt. Damit machst du es einem potentiellen Angreifer so schwer wie möglich. In der DB legt man das wieder als String ab. Mehr zum Salt kannst du hier nachlesen: Salt in der Wikipedia

Wenn sich ein Benutzer anmeldet, berechnet man den Hash-Wert des Passwortes, das er eingegeben hat, und vergleicht ermittelten Hash-Wert mit dem gespeicherten Hash-Wert.

Beste Grüße

Stareagle


----------



## Tobse (8. Jan 2012)

> MD5 hashwert eines Strings => varchar(255)


Hier muss ich noch was anhängen. Ein MD5 (oder sha-x...) hashwert liefert eine 32-Stellen langen String, der eine Hexadezimalzahl darstellt. Für Hashwerte (egal ob mit salt oder ohne) sind also die Datentypen VARCHAR(32) oder INT(16) empfehlenswert. Sonst hast du pro user 223 bytes ( = 255-32) ungenuzten speicherplatz. Das mag wenig aussehen, aber kleinvieh macht auch mist.


----------



## Marcinek (8. Jan 2012)

Ja prinzipiell hast du recht.

Aber bei varchar wäre das egal, da nur so viel speicher reserviert wird, wieviel benötigt wird. variabel eben.

Und ja statt md5 würde man sha2 nehmen.


----------



## kossy (8. Jan 2012)

Hallo Leute !

Vielen Dank nochmal für die Hilfe !

Eine Frage hätte ich aber doch noch mal an euch: Wann genau macht es wirklich in einer relationalen Datenbank Sinn, einen oder mehrere Spalten gleichzeitig als Primärschlüssel und Fremdschlüssel zu kennzeichnen bzw. wann ist das sogar unumgänglich?

Grüße
Kossy


----------



## Marcinek (8. Jan 2012)

z.B. in einer Intersection table.

Dann hast du key_table_1 und key_table_2 als zusammengesetzteb PK.

Für OR-Mapping ist das unumgänglich.


----------



## kossy (9. Jan 2012)

Ich versteht nicht ganz, was Du mir einer Intersection Table meinst...


----------



## Evil-Devil (9. Jan 2012)

Er meint eine Tabelle die nichts anderes macht als Schlüssel miteinder zu verbinden. Zb. wenn du N zu M Beziehungen hast und die irgendwo hinterlegen willst machen jene Tabellen, auch Kreuztabellen genannt, am meisten Sinn.


----------



## kossy (10. Jan 2012)

Hallo Leute !

Danke nochmal für eure Beiträge !

Ich habe mal einen SQ Code wie diesen hier gesehen und wollte mal von euch als Profis hören, ob das ein guter oder schlechter Code ist.


```
SELECT *
FROM Tab1 INNER JOIN Tab2
INNER JOIN Tab3
INNER JOIN Tab4
ON Tab1.FeldA = Tab2.FeldA
ON Tab1.FeldA = Tab3.FeldA
ON Tab3.FeldB = Tab4.FeldB
```


Müsste man nicht eigentlich zwischen jeden INNER JOIN auch gleich die enstprechende ON Klausel hinzufügen?

Grüße
Kossy


----------



## Evil-Devil (10. Jan 2012)

Abgesehen davon das ich es nicht sonderlich lesbar finde, kann es ok sein. Hätte das wie folgt geschrieben.

[sql]
SELECT *
FROM Tab1
INNER JOIN (Tab2, Tab3, Tab4)
ON (Tab1.FeldA = Tab2.FeldA
	AND Tab1.FeldA = Tab3.FeldA
	ANDTab3.FeldB = Tab4.FeldB)[/sql]

Allerdings sollte das * weg. Es ist sehr schlecht * zu schreiben, am besten immer genau die Felder angeben die man ausgegeben haben will. Alles andere ist nur unnötiger Ballast für das DBMS.


----------



## kossy (12. Jan 2012)

Hallo nochmal an euch !

Kann mir vielelicht jemand von euch sagen, wo ier ein Syntaxfehler in meinem SQL Code vorliegt? Das ist zwar mit Basci geschrieben, sollte aber in diesme fall gleichgültig sein. Vielen Dank nochmal für eure Hilfe !


```
strSql = "SELECT tbl301_37_ZsStruktur.ZsStruktur_GueltigAb, tbl301_37_ZsStruktur.ZsStruktur_GueltigBis, " & _
                    "tbl301_38_ZsStrukturDetails_TMP.Ebene, tbl301_38_ZsStrukturDetails_TMP.KumSpalte, " & _
                    "tbl301_38_ZsStrukturDetails_TMP.Gruppe, tbl301_38_ZsStrukturDetails_TMP.ZsStruktur_ID, " & _
                    "tbl301_38_ZsStrukturDetails_TMP.ZS_ID, tbl301_38_ZsStrukturDetails_TMP.Parent_ZS_ID, " & _
                    "tbl301_21_Zahlungsstroeme.ZS_Bez, tbl301_21_Zahlungsstroeme.ZS_Bez_Kurz, " & _
                    "tbl301_38_ZsStrukturDetails_TMP.Sort, tbl301_38_ZsStrukturDetails_TMP.BAS_SpalteNr " & _
             "FROM tbl301_38_ZsStrukturDetails_TMP INNER JOIN tbl301_37_ZsStruktur " & _
                    "ON tbl301_38_ZsStrukturDetails_TMP.ZsStruktur_ID = tbl301_37_ZsStruktur.ZsStruktur_ID " & _
                  "INNER JOIN tbl301_21_Zahlungsstroeme " & _
                    "ON tbl301_38_ZsStrukturDetails_TMP.ZS_ID = tbl301_21_Zahlungsstroeme.ZS_ID " & _
             "WHERE tbl301_38_ZsStrukturDetails_TMP.ZS_ID = " & lngZs_Id & " AND " & _
                   "tbl301_38_ZsStrukturDetails_TMP.ZsStruktur_ID = " & lngIDZsStruktur
```


----------



## Tobse (13. Jan 2012)

Also das ganze mal im klartext:

```
SELECT
	tbl301_37_ZsStruktur.ZsStruktur_GueltigAb,
	tbl301_37_ZsStruktur.ZsStruktur_GueltigBis,
	tbl301_38_ZsStrukturDetails_TMP.Ebene, tbl301_38_ZsStrukturDetails_TMP.KumSpalte,
	tbl301_38_ZsStrukturDetails_TMP.Gruppe, tbl301_38_ZsStrukturDetails_TMP.ZsStruktur_ID,
	tbl301_38_ZsStrukturDetails_TMP.ZS_ID, tbl301_38_ZsStrukturDetails_TMP.Parent_ZS_ID,
	tbl301_21_Zahlungsstroeme.ZS_Bez, tbl301_21_Zahlungsstroeme.ZS_Bez_Kurz,
 	tbl301_38_ZsStrukturDetails_TMP.Sort, tbl301_38_ZsStrukturDetails_TMP.BAS_SpalteNr
FROM
	tbl301_38_ZsStrukturDetails_TMP INNER JOIN tbl301_37_ZsStruktur
    ON
		tbl301_38_ZsStrukturDetails_TMP.ZsStruktur_ID = tbl301_37_ZsStruktur.ZsStruktur_ID
INNER JOIN
	tbl301_21_Zahlungsstroeme
	ON
		tbl301_38_ZsStrukturDetails_TMP.ZS_ID = tbl301_21_Zahlungsstroeme.ZS_ID
WHERE
		tbl301_38_ZsStrukturDetails_TMP.ZS_ID = 0
	AND
		tbl301_38_ZsStrukturDetails_TMP.ZsStruktur_ID = 0
```
Ganz spontan fällt mir nur auf, dass die zahlen keine ' haben, aber ob die wirklich nötig sind, weiss ich nicht. Die Fehlermeldung von der Datenbank wäre da schon ganz hilfreich.


----------



## kossy (15. Jan 2012)

Hallo !

Ich habe einen Syntaxfehler in der From Klausel ausgegeben bekommen, angeblich soll dort irgendein Operator fehlen . Ich erhielt die Meldung "Fehlender Operator in der der From Klausel".

Diesen sehe ich aber nicht.

Gruß
Kossy


----------



## turtle (15. Jan 2012)

Ich schlage vor, den SQL-Befehl mal in einem JDBC-Client (wie zum Beispiel Squirrel) zu probieren.

dann kannst Du dich auch dem Befehl schrittweise nähern, bis es Fehler hagelt oder Du zufrieden bist

Dieses Zusammenbasteln eines SQL-Befehls über Strings halte ich ehe für Nonsens. Das kann man besser/lesbarer mit PreparedStatements machen (mit dem Befehl, den Du in Squirrel getestet hast)


----------

