Sind Prefixe bei der Benennung von Tabellen nützlich?

  • VB.NET

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von raist10.

    Sind Prefixe bei der Benennung von Tabellen nützlich?

    Hi!

    Ich habe (mal wieder ;)) einen sachlichen Dissenz mit raist, und würd ihn eiglich lieber hier ausdiskutieren, als den Thread, wo er aufgetreten ist, damit zu überfrachten.

    raist empfiehlt, alle Datenbank-Objekte mit prefix zu benennen, weil komplexes Sql dann leichter zu lesen sei.

    ich empfehle, wenigstens bei Tabellen keine Prefixe zu verwenden, weil Sql dann leichter zu lesen ist (es entspricht mehr der natürlichen Sprache).

    Ausserdem empfiehlt er, Tabellen als Plural zu benennen, während ich Tabellen singular benenne.

    Beispiel: Gegeben die Tabellen Group und User, mit der 1:n - Relation: Group -> User.
    Nun will man alle User und deren Gruppen-Namen (klassischer Inner-Join):

    SQL-Abfrage

    1. SELECT User.Name, Group.Name FROM User INNER JOIN Group ON User.GroupID = Group.GroupID;
    (ich hoffe, ich machs richtig - Sql ist nämlich nicht mein Steckenpferd ;))
    Jedenfalls finde ich obige Query klar wie Klosbrühe, und kann in

    SQL-Abfrage

    1. SELECT tblUsers.Name, tblGroups.Name FROM tblUsers INNER JOIN tblGroups ON tblUsers.GroupID = tblGroups.GroupID;
    nur eine Verschlechterung der Lesbarkeit finden.
    Hier zeigt sich auch das (in Sql unlösbare) Problem: ist plural oder singular flexiert sinniger?
    In meiner Abfrage ist der Select-Abschnitt mit singular richtig flexiert, denn der Select-Abschnitt betrachtet einen einzelnen Datensatz. Dafür muß man hinnehmen, dass der FROM - Abschnitt falsch flexiert ist, denn es wird aus einer Auflistung selektiert. Aber schon die ON-Bedingung ist wieder korrekt flexiert, weil sie betrachtet wieder den einzelnen User / die einzelne Group.

    In raists System ist einzig der FROM-Abschnitt richtig flexiert, alle anderen Abschnitte sind mit plural falsch flexiert.

    Perfekt wäre ein Sql, welches folgendes ermöglichte:

    SQL-Abfrage

    1. SELECT User.Name, Group.Name FROM Users INNER JOIN Groups ON User.GroupID = Group.GroupID;
    (Linq2Sql und Entity-Framework haben sowas drauf, allerdings nur für englisch-sprachige Bezeichner)

    Wie gesagt: Ich empfehle den Verzicht auf Prefixe nur bei Tabellen - andere Datenobjekte sollen mw. "geprefixt" sein. Auf diese Weise ist die Unterscheidbarkeit der Objekte immer noch 100% sichergestellt: sehe ich einen Bezeichner ohne Prefix, so weißich, es ist eine Tabelle.

    Ich muß aber gleich dazusagen: Ich hab wirklich nicht viel Ahnung von Sql - ich bevorzuge, DB-Daten in einer Data-Acces-Schicht zu laden, und alsbald in .Net-Datentypen zu konvertieren, und jegliche Datenverarbeitung dann innerhalb des TypSystems des Frameworks durchzuführen.
    Schon obigen Inner Join würde ich nur in extremen Ausnahmefällen konstruieren, sondern stattdessen die Daten in verschiedene DataTables laden und erst im Formular zu einem gejointen View zusammenführen.
    Geschmackssache ;)

    Sing vs Plural:
    Inzwischen bevorzuge ich Plural. Eine Liste in .Net würde "Users" heißen, wenn darin Objekte vom Typ "User" gespeichert/verwaltet werden. Warum sollte das bei Tabellen anders sein?

    Prefixe: Kenn ich grundsätzlich eher aus dem Web-Bereich. Man hat EINE Datenbank aber verschiedene irgendwas die genau diese eine DB benutzen (zb ne Typo3 Installation, ein xtc Shop und ein Blog). Um Überschneidungen zu vermeiden MUSS man Prefixe verwenden. Ob man jetzt wirklich "tblUsers" schreiben muss, oder "UserTable" statt einfach "Users" glaub ich nicht.
    @ ErfinderDesRades

    Na dann will ich mich auch mal äußern. ^^

    Aber zuerst möchte ich betonen das es beim Thema Benamsung und Präfixe eh kein richtig und falsch gibt, sondern vieles wirklich nur Ansichtssache ist.

    Das was Du als "meine Empfehlungen" bezeichnest sind nicht MEINE Empfehlungen sondern die übliche Handhabung im Datenbank-Bereich und daher absolut nicht auf meinem Mist gewachsen. Nur damit klar gestellt ist das ich mich hier nicht mit fremden Federn schmücken möchte. ;)

    Ich habe mal Deinen Post in den Zitaten etwas umsortiert um leichter/verständlicher auf sie eingehen zu können.

    ---------------------------------------------------------


    Ausserdem empfiehlt er, Tabellen als Plural zu benennen, während ich Tabellen singular benenne.


    Diese Empfehlung folgt der einfachen Logik das eine Tabelle immer dafür ausgelegt ist MEHRERE Datensätze des gleichen Typs aufzunehmen. Daher ist es einfach natürlicher z.B. die Tabelle Users zu nennen und einen einzelnen Datensatz in der Tabelle User.

    Oder andersrum: Eine Entität in einer Datenbank repräsentiert immer die Gesamtheit aller Datensätze und daher ist die Anwendung des Plurals als Bezeichnung einfach nur folgerichtig.

    ---------------------------------------------------------

    Und ich hoffe Du bist mir nun nicht böse das ich Dich erstmal an einigen Stellen verbessere um auf das Thema Benamsung von Tabellen sinnvoll eingehen zu können.


    SQL-Abfrage

    1. SELECT User.Name, Group.Name FROM User INNER JOIN Group ON User.GroupID = Group.GroupID;
    (ich hoffe, ich machs richtig - Sql ist nämlich nicht mein Steckenpferd ;))


    Das würde kein Datenbänker so schreiben, dass ist MS-Automatismus-Syntax.

    Wenn ein Datenbänker sowas schreiben müsste würde das vermutlich eher so aussehen:

    SQL-Abfrage

    1. SELECT t1.Name, t2.Name FROM User As t1 INNER JOIN Group As t2 ON t1.GroupID = t2.GroupID;


    Aber selten das ein Datenbänker die Benamsung so wählen würde.

    Hier mal so die allgemeinen Grundregeln für die Benamsung an die ICH mich halte und die sich bisher für MICH gut bewährt haben:

    1. Tables, Querys/Views, Stored Procedures erhalten jeweils einen separaten Präfix ... z.B. "tbl_" für Tables, "qry_" oder "vw_" für View etc.

    2. Tables werden immer im Plural benamst, Fieldnames werden immer im Singular benamst

    3. Attribute einer Entität (Fields eines Tables) erhalten selber auch ein Präfix was sich aus dem Table-Namen ergibt, z.B. im tbl_Users erhält jedes Field den Präfix "usr" und jedes Attribut der Entität tbl_Groups erhält den Präfix "grp", in Views berechnete/ermittelte Felder erhalten keinerlei Präfix

    4. Foreign Key in einem Table erhalten den Präfix "fk_" und Primary Keys beinhalten immer als Suffix "ID", also der PK im tbl_Users heisst dann usrID und der Foreign Key grpID im tbl_Users heisst dann fk_grpID

    5. Zwischentables die zur Auflösung von m:n-Beziehungen erstellt worden sind, erhalten das Präfix "tbl_mn_"

    6. Bei Inner Joins steht links immer das Attribut aus dem linken Table des Inner Joins stammt

    Wenn ich diesen Reglungen folge ergibt sich für Dein Beispiel folgendes SQL-Statement:

    SQL-Abfrage

    1. SELECT usrName, grpName FROM tbl_Users INNER JOIN tbl_Groups ON fk_grpID = grpID;


    Vorteile:

    - viel einfacher/natürlicher lesbar als das Ausgangs-Statement
    - auf einem Blick erkennbar woher welches Field stammt
    - keine Notwendigkeit für Table-Identifiers zu den Fields = kürzere Schreibweise = weniger Raum für Rechtschreibfehler
    - durch Standarisierung der Benamsung viel weniger Fehler auf Grund "verschrieben"

    Bei so kleinen Statements mag das jetzt vermutlich arg pingelig erscheinen, aber in komplexeren DB-Anwendungen sind SQL-Statements (z.B. für ein View oder eine Stored Procedure) mit einigen 100 Zeilen die sich über x Tables in Kombination mit x Views erstrecken nicht wirklich was unnormales.

    Z.B. sowas mal als Ansatz (syntaktisch sollte es stimmen aber nicht wirklich sinnvoll, also rein zur Veranschaulichung):

    [MySQL]
    SELECT
    usrID As [ID],
    usrName As [Name],
    usrFirstName As [Vorname],
    usrAnrede As [Anrede],
    grpBezeichnung As [Schicht],
    (SELECT ldrName FROM vw_Leaders WHERE fk_grpID = t1.grpID) As [Schicht-Leiter],
    grpSchichtStunden * (SELECT Count(fk_grpID) FROM tbl_mn_Wrk2Grp WHERE fr_grpID = t1.grpID) As [Anzahl Stunden]
    FROM
    tbl_Users INNER JOIN tbl_Groups As t1
    ON fk_grpID = grpID
    WHERE
    grpSchicht = 'Nachtschicht'
    AND
    usrID IN (SELECT usrID FROM vw_Schichtplaene WHERE Status = 'Eingeteilt')[/MySQL]

    Die Überprüfung solcher Statements längere Zeit nachdem man sie erstellt hat wird dann wirklich zur Qual wenn man dann nicht auf einen Blick erkennt auf welches Basis bezieht sich die Abfrage und welches Attribut gehört zu welcher Entität.

    Versuch einfach mal dieses Statement syntaktisch genauso korrekt ohne die Berücksichtung "meiner" Benamsungs-Regelung zu erstellen ... ich denke dann wird sofort klar was ich mit lesbar meine.


    Ich muß aber gleich dazusagen: Ich hab wirklich nicht viel Ahnung von Sql - ich bevorzuge, DB-Daten in einer Data-Acces-Schicht zu laden, und alsbald in .Net-Datentypen zu konvertieren, und jegliche Datenverarbeitung dann innerhalb des TypSystems des Frameworks durchzuführen.
    Schon obigen Inner Join würde ich nur in extremen Ausnahmefällen konstruieren, sondern stattdessen die Daten in verschiedene DataTables laden und erst im Formular zu einem gejointen View zusammenführen.


    Gut, darüber haben wir uns ja schonmal ausführlicher unterhalten, daher hier nur soviel:

    Viel Spaß dabei wenn die Tables mal so 1-2 Mio DS beinhalten. Dann stürtzt Dir vermutlich der Rechner ab bevor Du das Ergebnis hast ... diese Mengen in den Memory zu laden bevor man sie verarbeitet ist einfach tödlich, mal von der Zeit abgesehen die es braucht die Daten vom SQL-Server über die Netzwerkverbindung auf den Client zu schaufeln.

    Und selbst wenn es nur x00.000 DS sind, wäre die Ausführung des SQL-Statements serverseitig in einem aktiven DBMS x-mal schneller als Deine Variante erstmal die Tables komplett in den Memory zu laden und dann erst von dort aus erst die benötigten DS zu selektieren.

    Aber richtig ... es kommt aber natürlich darauf an über welche DB-Größen wir hier reden. Für eine passive Single-File-DB die auf dem lokalen Laufwerk liegt und nur ein paar 100 DS pro Table beinhaltet ist vermutlich Deine Variante wirklich schneller/effizienter oder zumindest gleich schnell/effizient.

    Gruß

    Rainer
    Also mir kommt sogar sowas komplexes in meiner Benamung leserlicher und verständlicher vor:

    SQL-Abfrage

    1. SELECT
    2. User.ID,
    3. User.Name,
    4. User.FirstName,
    5. User.Anrede,
    6. User.Schicht,
    7. (SELECT Leader.Name FROM Leader WHERE Leader.GroupID = User.GroupID) As [Schicht-Leiter],
    8. User.SchichtStunden * (SELECT Count(Wrk2Grp.GroupID) FROM Wrk2Grp WHERE Wrk2Grp.GroupID = User.GroupID) As [Anzahl Stunden]
    9. FROM
    10. User INNER JOIN Group ON User.GroupID = Group.ID
    11. WHERE
    12. User.Schicht = 'Nachtschicht'
    13. AND
    14. User.ID IN (SELECT Schichtplan.UserID FROM Schichtplan WHERE Schichtplan.Status = 'Eingeteilt')
    Ich hoffenur, ich habs richtig übersetzt, weil bei 'fr_grpID' blick ich nicht mehr durch, wo das eiglich herkommt.
    Und 'tbl_mn_Wrk2Grp' ist für mich die hässlichste Benamung der Woche ;)

    Ach guck - ich hab dem View nichtmal einen Prefix verpasst, und macht hier grad garnix, weils hier schnuppe ist, denn sowohl eine Tabelle als auch ein View sind Datensatz-Lieferanten.
    Auch ich habe die Erfahrung gemacht, dass Datenbänker und OO-Programmierer unterschiedliche Nomenklaturen verwenden und auch völlig unterschiedliche Denkweisen haben.

    Ich schlage mich mit meinem Stil auch eher auf die Seite von ErfinderDesRades.
    Aber wie raist10 schon betonte, es gibt weder völlig richtig noch völlig falsch.
    Die Welt ist nun mal (glücklicherweise) nicht schwarz-weiß.

    Während mancher DBler schon staunte, wie einfach man mit einem objektorientierten Ansatz komplexe Probleme erschlagen kann, bekomme ich manchmal den Mund nicht zu, wie perfomant man Daten mit einem 50-Zeilen-SQL-Statement aus einer gigantischen Datenbank zu Tage fördern kann.
    Allerdings kenne ich auch Gegenbeispiele, wo manche meinen, die komplette Programmlogik in einem View abbilden zu müssen und dabei sowohl Übersicht als auch Performance in die Binsen geht.

    Wenn ich meine Datenbank selbst designe, benenne ich die Tabellen und Felder so, dass sie zu meinem Programm passen :)
    Ich habe inzwischen aber auch keine Mühe mehr, mich den üblichen Benennungen der Oracle-Entwickler anzupassen und sie zu verwenden.
    Das ist wohl alles Gewohnheitssache.

    Ich glaube, dass die gesprächige Namensgebung der DBler daher rührt, dass die Entwicklungs- und Debug-Umgebungen dieser Systeme wesentlich rudimentärer sind, als wir sie in der doch recht komfortablen Visual-Studio-Welt gewohnt sind.
    Man muss einfach wesentlich sprechenderen Code produzieren, weil das die einzige Möglichkeit ist, auf die Herkunft der Daten zu schliessen.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    ErfinderDesRades schrieb:

    Also mir kommt sogar sowas komplexes in meiner Benamung leserlicher und verständlicher vor:


    Nur kurz als Anmerkung: Mein Beispiel-Statement war weder komplex noch umfangreich, sondern ein absolut simples Beispiel ... halt bloss ein wenig näher an der Realität als Dein einfachst Beispiel.

    Wie schon gesagt, dass ist zum einen Ansichtssache zum anderen hat sich eine Benamsung in dieser Richtung durchgesetzt weil die Unterstützung bei der Tipparbeit im Datenbankbereich relativ mau ist.

    Bei so kurzen Tabellennamen wie User oder Group mag es noch so einigermaßen gehen den Table-Name als Identifier zu nutzen. Aber wenn Du eine DB mit mehreren hundert Tables hast und für jedes Table einen einigermaßen sprechenden Namen verwendest, dann sind Table-Namen mit 20 bis 40 Zeichen auch nichts ungewöhnliches. Und schreib mal so lange Namen ohne jegliche IntelliSense Unterstützung wenn in SQL-Statements wo Du Felder aus dem Table 30-40 mal ansprichst.

    Erstens wird das Statement je länger es wird umso unübersichtlicher und zweitens steigt die Fehlerquote für Rechtschreibfehler ins Unermeßliche.


    Ich hoffenur, ich habs richtig übersetzt, weil bei 'fr_grpID' blick ich nicht mehr durch, wo das eiglich herkommt.


    Keine Ahnung, habe es nicht überprüft da es ja nix zur Sache tut, dass was Du meinst ist ja auch ohne syntaktische Korrektheit zu erkennen.


    Und 'tbl_mn_Wrk2Grp' ist für mich die hässlichste Benamung der Woche ;)


    Es geht nicht um Schönheit, sondern darum mit möglichst wenig Aufwand möglichst viele Informationen zu verpacken die dem Fremdleser es ermöglichen das Statement schnell zu begreifen ohne jedesmal nachzugucken was ist das, woher kommt das und wofür taugt das. Hier wird auf einen Blick (selbst für jemanden der meine Benamsungs-Regeln nicht kennt) deutlich das es ein Zwischentable zur Auflösung einer m:n Beziehung ist und wenn er meinen Präfixe begriffen hat wird er auch gleich wissen das die linke Seite der m:n Beziehung aus dem Table das Wrk als Field-Präfix beinhaltet stammt und auf der rechten Seite das Table das Grp als Field-Präfix in der Benamsung beinhaltet.


    Ach guck - ich hab dem View nichtmal einen Prefix verpasst, und macht hier grad garnix, weils hier schnuppe ist, denn sowohl eine Tabelle als auch ein View sind Datensatz-Lieferanten.


    Juup ... und ein Fremdleser sucht sich dann dumm und dämlich nach dem Table Leader im ERM-Diagramm.

    Mach das mal ... Dich in einem Diagramm einer mittleren DB mit 300 bis 400 Tables dumm und dämlich zu suchen um das Table zu finden nur um dann nach einigen grundlos vergeudeten Arbeitsstunden darauf zu kommen das das vermaledeite Ding eine View ist ... da kommen Gewaltphantasien vom aller Feinsten auf. ;)

    Gruß

    Rainer

    picoflop schrieb:

    Eine Liste in .Net würde "Users" heißen, wenn darin Objekte vom Typ "User" gespeichert/verwaltet werden. Warum sollte das bei Tabellen anders sein?

    Weil Sql dieselbe Tabelle sowohl als Singular anspricht als auch als Plural

    SQL-Abfrage

    1. Select User.Name, User.ID, Game.Name FROM User, Game WHERE User.GameID = Game.GameID
    Hier wird 5 mal ein TabellenBezeichner als Singular verwendet, und nur 2 mal als Plural.

    Derselbe Bezeichner bezeichnet einmal einen Datensatz, und ein andermal die Tabelle, der er entstammt.

    Dieses Prinzip setzt sich auch im OOP fort, wenn man sich aus der DB typisierte Datenklassen generiert. Und auch im typisierten Code addressiert man den einzelnen Datensatz häufiger als die Tabelle in ihrer Gesamtheit.

    Der Dataset-Designer generiert sogar weitestgehend korrekt: Aus einer DB-Table "User" generiert er die Klassen UserTable und UserRow. Hieße die DB-Tabelle "Users", so käme UsersTable dabei heraus, und UsersRow.
    Bei der Tabelle isses schnurz: UsersTable ist ebenso korrekt plural wie UserTable. Aber UsersRow ist Unfug, denn die Row repräsentiert nur einen User.

    Noch besser generiert Linq2Sql: hier entstehen Entitäten im Singular, und die Property, die ein EntitySet, also viele dieser Entitäten bereitstellt ist Plural flexiert (geht nur mit englischen Bezeichnern korrekt).

    ErfinderDesRades schrieb:

    Dieses Prinzip setzt sich auch im OOP fort

    Ich spiel gerade mit ADO.Net Entity rum. Wenn man da ne Klasse hat "Person" und ne andere "Family" und im Database Create Wizard "pluralize" anklickt (warum ist die Möglichkeiten vorhanden, wenn das keinen Sinn macht?), dann heißen die erzeugten Tabellen ... "People" und "Families"
    @ ErfinderDesRades

    Wir reden hier über Benamsungs-Regelungen für Datenbanken und nicht für OOP-Programmierung in NET. ;)

    Und bei den Datenbänkern ist es eben üblich Tabellen im Plural zu benamsen, einfach weil die Logik dahinter bestechend simple ist: Eine Tabelle nimmt mehrere Datensätze auf und stellt daher immer die Mehrzahl der in ihr gespeicherten Datensätze dar. Simple, logisch und eben eine Grundregel für die Benamsung beim Datenbank-Design.

    Gruß

    Rainer

    picoflop schrieb:

    ErfinderDesRades schrieb:

    Dieses Prinzip setzt sich auch im OOP fort

    Ich spiel gerade mit ADO.Net Entity rum. Wenn man da ne Klasse hat "Person" und ne andere "Family" und im Database Create Wizard "pluralize" anklickt (warum ist die Möglichkeiten vorhanden, wenn das keinen Sinn macht?), dann heißen die erzeugten Tabellen ... "People" und "Families"

    Dochdoch - das macht genau sinn. Er erzeugt die Tabelle Families, und jede einzelne Entity dieser Tabelle ist vom Typ Family. Das meinte ich ja, als ich die gute Generierung von Linq2Sql erwähnte.

    Damit ist die Unstimmigkeit, die bei Sql drin ist ( User.Name bezeichnet korrekt singular, Users.Name wäre sprachlich falsch ) behoben, und wo Sql formuliert

    SQL-Abfrage

    1. SELECT Users.Name FROM Users
    formuliert L2S

    VB.NET-Quellcode

    1. From usr As User in Users Select usr.Name


    Gegenfrage: Wieso gibts das L2S-Pluralize-Feature, wenn es wirklich allgemeine Sql-Konvention wäre, die Tabellen plural zu deklarieren?
    Oder kann L2S auch singularisieren, wenn die DB-Table plural flexiert ist?

    IMO ist das Feature auf eine BenamungsKonvention ausgerichtet, die die DB-Tabellen singular benennt.

    ErfinderDesRades schrieb:

    Oder kann L2S auch singularisieren, wenn die DB-Table plural flexiert ist?

    habich jetzt ausprobiert. Tatsache kanner beides, und das Feature heißt auch genau: "Bezeichner in den Singular oder in den Plural setzen"

    Macht also keine Aussage zur Sql-Namenskonvention - höchstens eben, dasser sowohl als auch unterstützt.