Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Modèle de conception pour les champs personnalisés dans la base de données relationnelle

Évitez les données de type chaîne en remplaçant VALUE avec NUMBER_VALUE , DATE_VALUE , STRING_VALUE . Ces trois types sont suffisants la plupart du temps. Vous pouvez ajouter XMLTYPE et d'autres colonnes sophistiquées ultérieurement si nécessaire. Et pour Oracle, utilisez VARCHAR2 au lieu de CHAR pour économiser de l'espace.

Essayez toujours de stocker les valeurs sous le type correct. Les types de données natifs sont plus rapides, plus petits, plus faciles à utiliser et plus sûrs.

Oracle dispose d'un système de types de données génériques (ANYTYPE, ANYDATA et ANYDATASET), mais ces types sont difficiles à utiliser et doivent être évités dans la plupart des cas.

Les architectes pensent souvent que l'utilisation d'un seul champ pour toutes les données facilite les choses. Cela facilite la génération de jolies images du modèle de données, mais cela rend tout le reste plus difficile. Tenez compte des problèmes suivants :

  1. Vous ne pouvez rien faire d'intéressant avec des données sans en connaître le type. Même pour afficher des données, il est utile de connaître le type pour justifier le texte. Dans 99,9 % des cas d'utilisation, il sera évident pour l'utilisateur laquelle des 3 colonnes est pertinente.
  2. Développer des requêtes de type sécurisé sur des données de type chaîne est pénible. Par exemple, supposons que vous souhaitiez rechercher la "date de naissance" pour les personnes nées au cours de ce millénaire :

    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'
    

    Pouvez-vous repérer le bug? La requête ci-dessus est dangereuse, même si vous avez stocké la date dans le bon format, et très peu de développeurs savent comment la corriger correctement. Oracle a des optimisations qui rendent difficile de forcer un ordre spécifique des opérations. Vous aurez besoin d'une requête comme celle-ci pour être sûr :

    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';
    

    Vous ne voulez pas avoir à dire à tous les développeurs d'écrire leurs requêtes de cette façon.