sql >> Base de Datos >  >> RDS >> Sqlserver

Patrón de diseño para campos personalizados en base de datos relacional

Evite los datos escritos en forma de cadena reemplazando VALUE con NUMBER_VALUE , DATE_VALUE , STRING_VALUE . Esos tres tipos son lo suficientemente buenos la mayor parte del tiempo. Puede agregar XMLTYPE y otras columnas sofisticadas más adelante si es necesario. Y para Oracle, use VARCHAR2 en lugar de CHAR para ahorrar espacio.

Intente siempre almacenar los valores como del tipo correcto. Los tipos de datos nativos son más rápidos, más pequeños, más fáciles de usar y más seguros.

Oracle tiene un sistema de tipos de datos genéricos (ANYTYPE, ANYDATA y ANYDATASET), pero esos tipos son difíciles de usar y deben evitarse en la mayoría de los casos.

Los arquitectos a menudo piensan que usar un solo campo para todos los datos facilita las cosas. Hace que sea más fácil generar bonitas imágenes del modelo de datos, pero hace que todo lo demás sea más difícil. Considere estos problemas:

  1. No se puede hacer nada interesante con los datos sin conocer el tipo. Incluso para mostrar datos es útil saber el tipo para justificar el texto. En el 99,9% de todos los casos de uso, será obvio para el usuario cuál de las 3 columnas es relevante.
  2. Desarrollar consultas con seguridad de tipos contra datos tipeados en forma de cadena es complicado. Por ejemplo, supongamos que desea encontrar la "Fecha de nacimiento" de las personas nacidas en este milenio:

    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'
    

    ¿Puedes detectar el error? La consulta anterior es peligrosa, incluso si almacenó la fecha en el formato correcto, y muy pocos desarrolladores saben cómo solucionarlo correctamente. Oracle tiene optimizaciones que dificultan forzar un orden específico de operaciones. Necesitará una consulta como esta para estar seguro:

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

    No querrás tener que decirle a cada desarrollador que escriba sus consultas de esa manera.