Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Entwurfsmuster für benutzerdefinierte Felder in relationalen Datenbanken

Vermeiden Sie Zeichenfolgendaten, indem Sie VALUE ersetzen mit NUMBER_VALUE , DATE_VALUE , STRING_VALUE . Diese drei Typen sind meistens gut genug. Sie können XMLTYPE und andere ausgefallene Spalten später hinzufügen, wenn sie benötigt werden. Und für Oracle verwenden Sie VARCHAR2 anstelle von CHAR, um Platz zu sparen.

Versuchen Sie immer, Werte mit dem richtigen Typ zu speichern. Native Datentypen sind schneller, kleiner, benutzerfreundlicher und sicherer.

Oracle hat ein generisches Datentypsystem (ANYTYPE, ANYDATA und ANYDATASET), aber diese Typen sind schwierig zu verwenden und sollten in den meisten Fällen vermieden werden.

Architekten denken oft, dass die Verwendung eines einzigen Felds für alle Daten die Dinge einfacher macht. Es macht es einfacher, schöne Bilder des Datenmodells zu erzeugen, aber es macht alles andere schwieriger. Berücksichtigen Sie diese Probleme:

  1. Sie können mit Daten nichts Interessantes anfangen, ohne den Typ zu kennen. Selbst um Daten anzuzeigen, ist es nützlich, den Typ zu kennen, um den Text zu rechtfertigen. In 99,9 % aller Anwendungsfälle wird es für den Benutzer offensichtlich sein, welche der 3 Spalten relevant ist.
  2. Das Entwickeln typsicherer Abfragen für stringly-typisierte Daten ist mühsam. Angenommen, Sie möchten das „Geburtsdatum“ für Personen finden, die in diesem Jahrtausend geboren wurden:

    select *
    from ReportFieldValue
    join ReportField
        on ReportFieldValue.ReportFieldid = ReportField.id
    where ReportField.name = 'Date of Birth'
        and to_date(value, 'YYYY-MM-DD') > date '2000-01-01'
    

    Können Sie den Fehler erkennen? Die obige Abfrage ist gefährlich, selbst wenn Sie das Datum im richtigen Format gespeichert haben, und nur sehr wenige Entwickler wissen, wie man es richtig behebt. Oracle verfügt über Optimierungen, die es schwierig machen, eine bestimmte Reihenfolge von Vorgängen zu erzwingen. Zur Sicherheit benötigen Sie eine Abfrage wie diese:

    select *
    from
    (
        select ReportFieldValue.*, ReportField.*
            --ROWNUM ensures type safe by preventing view merging and predicate pushing.
            ,rownum
        from ReportFieldValue
        join ReportField
            on ReportFieldValue.ReportFieldid = ReportField.id
        where ReportField.name = 'Date of Birth'
    )
    where to_date(value, 'YYYY-MM-DD') > date '2000-01-01';
    

    Sie möchten nicht jedem Entwickler sagen müssen, dass er seine Abfragen auf diese Weise schreiben soll.