Definición de relaciones entre tablas de base de datos

Objectives

After completing this lesson, you will be able to:
  • Comprender las relaciones en los modelos de datos.
  • Definir dependencias de clave externa en tablas de diccionario.

Relaciones en modelos de datos

Normalmente, las entidades de un modelo de datos están relacionadas entre sí. La definición de un modelo de datos incluye la definición de estas relaciones.

Veamos el modelo de datos de una empresa, que incluye las entidades Empleado y Departamento. Las dos entidades están relacionadas porque los empleados están asignados a departamentos.

Pero las dos entidades también pueden compartir otras relaciones. Por ejemplo, cada departamento está liderado por uno de los empleados.

Características importantes de una relación son sus cardinalidades o multiplicidades. Le indican cuántas instancias de una entidad pertenecen a una instancia de la otra entidad.

Existen diferentes sistemas de notación para cardinalidades. El Unified Modeling Language (UML), por ejemplo, utiliza un valor máximo y mínimo, con * para un máximo no restringido.

Veamos nuestros ejemplos:

Cada empleado debe estar asignado exactamente a un departamento. Por lo tanto, la cardinalidad en esta dirección es 1..1. En la otra dirección, un departamento puede tener asignado cualquier número de empleados, incluso se permite cero. Por lo tanto, la cardinalidad es 0..*.

Para la otra relación, consideremos que cada departamento está dirigido exactamente por un empleado, no más, no menos. Esto significa que ignoramos casos especiales como posiciones de lead vacantes (cero es un valor permitido) o liderazgo doble o múltiple (se permiten valores superiores a 1). En la otra dirección, podemos decir fácilmente que no todos los empleados son líderes, lo que significa que el mínimo es cero. Decidimos fijar el máximo en 1, por el cual expresamos, que un empleado no puede dirigir dos departamentos al mismo tiempo.

Nota

En Dictionary ABAP y CDS ABAP, la cardinalidad y la multiplicidad se utilizan como sinónimos. Estrictamente hablando, una cardinalidad es el número real de instancias, mientras que la multiplicidad especifica el rango de valores permitidos.

ABAP CDS y Dictionary ABAP utilizan diferentes conceptos para expresar relaciones:

Asociaciones

ABAP CDS utiliza asociaciones para definir relaciones entre entidades de vista CDS. Por lo general, una relación se refleja en dos asociaciones, apuntando en direcciones opuestas.

Claves externas

El Dictionary ABAP define una dependencia para los campos de tabla para establecer una relación con otra tabla de base de datos. Una relación de clave externa de este tipo corresponde a una relación.

Exploremos las posibilidades para definir relaciones analizando más de cerca las dependencias de clave externa en el diccionario ABAP.

Definiciones de clave externa en tablas de Dictionary

En el Dictionary ABAP, puede utilizar dependencias de clave externa para definir relaciones entre tablas.

En la programación ABAP moderna, el objetivo principal de estas dependencias de clave externa es la documentación. En el desarrollo ABAP clásico, sin embargo, tuvieron una influencia directa en la interfaz de usuario. Han dado lugar a verificaciones de entrada implícitas y a ayudas para entradas generadas.

Nota

En el desarrollo ABAP moderno, las asociaciones entre entidades de vista CDS se han hecho cargo parcialmente de esta tarea. Consulte la siguiente lección para obtener más detalles.

Es importante tener en cuenta que las definiciones de clave externa en el Dictionary ABAP permanecen en la capa ABAP. No se transfieren a la base de datos. Como consecuencia, no provocan verificaciones de consistencia implícitas en la base de datos.

Una dependencia de clave externa define una relación entre dos tablas de base de datos de Dictionary, una de ellas se denomina tabla de clave externa y la otra, tabla de verificación.

Una relación de clave externa completa enlaza cada campo de clave primaria de la tabla de verificación con un campo correspondiente en la tabla de claves externas. En el ejemplo, la clave primaria de la tabla de verificación consta de tres campos: C1, C2 y C3. La relación de clave externa los enlaza con los campos F1, F2 y F6 de la tabla de claves externas. Los campos F1, F2 y F6 forman conjuntamente la clave externa.

Nota

Una clave externa puede incluir cualquier combinación de campos, campos clave y campos no clave. Los campos relacionados en la tabla de verificación son siempre campos clave.

La relación de clave externa restringe los valores en los campos de clave externa: solo se permiten las combinaciones que están presentes en la tabla de verificación. Esta restricción es especialmente importante para el último campo de clave externa, es decir, el campo que está vinculado al último campo de clave primaria de la tabla de verificación. Este campo se denomina campo de verificación. En nuestro ejemplo, el campo de verificación es el campo F6.

Ejemplo: relación de clave externa

Reproduzca el vídeo para ver un ejemplo de una relación de clave externa.

Atributos semánticos de claves externas

Cuando define una relación de clave externa, puede añadir información semántica para describir aún más la relación e influir en la forma en que la utiliza el framework.

La mayoría de la información semántica se especifica mediante anotaciones de clave externa. Solo la cardinalidad se especifica directamente en la sentencia DEFINE TABLE.

Si un campo tiene una relación de clave externa, puede añadir las siguientes anotaciones de clave externa:

Descripción breve

El texto breve se utiliza como texto explicativo para una relación de clave externa.

Tipo de campo de clave externa

La anotación @AbapCatalog.foreignKey.keyType describe el significado de los campos de clave externa en la tabla de claves externas. Seleccione el valor #KEY si todos los campos de clave externa son campos clave de la tabla de claves externas. Seleccione #NON_KEY si al menos un campo de clave externa no es un campo clave de la tabla de claves externas. En el ejemplo, #NON_KEY es correcto porque el campo DEPARTMENT_ID no es un campo clave de la tabla EMPLOYEE. El tercer valor, #TEXT_KEY, es relevante si la tabla de claves externas es una tabla de texto, es decir, contiene texto traducible para la tabla de verificación.

Verificación de valores para IU clásica

La anotación @ABAPCatalog.foreignKey.screenCheck controla si los diálogos de usuario clásicos realizan verificaciones de valor basadas en esta relación de clave externa. Si se fija en verdadero, hay más anotaciones disponibles para especificar un mensaje de error dedicado. De lo contrario, se visualizará un mensaje de error genérico.

Nota

Las anotaciones de pantalla y mensaje no son relevantes en los diálogos de usuario modernos. A menos que planee desarrollar IU clásicas, fije el valor de @ABAPCatalog.foreignKey.screenCheck en falso.

La cardinalidad describe una relación de clave externa con respecto a la cantidad de registros dependientes posibles (registros de la tabla de claves externas) o registros referenciados (registros de la tabla de verificación).

En el Dictionary ABAP, la cardinalidad se especifica con [ n , m ] inmediatamente después de la palabra clave KEY.

  • El lado izquierdo (n) especifica el número de registros de tabla de clave externa por registro de tabla de verificación y puede tener los valores 1, 0..1, 1..* y 0..* .
  • El lado derecho (m) especifica el número de registros de tabla de verificación por registro de tabla de clave externa y puede tener los valores 1 o 0..1.

Para seleccionar la cardinalidad correcta, empiece por el lado derecho.

Seleccione m = 1 si el campo de verificación es un campo obligatorio. En este caso, cada registro de la tabla de claves externas requiere un valor en el campo de verificación y un registro coincidente en la tabla de verificación.

Seleccione m = 0..1 si el campo de verificación es opcional. A continuación, los registros sin un valor en el campo de verificación no requieren un registro coincidente en la tabla de verificación.

Veamos de nuevo nuestro ejemplo con empleados y departamentos:

Si es obligatorio que un empleado esté asignado a un departamento, la cardinalidad de la clave externa debe tener m = 1. Si también es posible que un empleado no esté asignado a un departamento, la cardinalidad debe tener m = 0..1.

Ahora echemos un vistazo al lado izquierdo de la cardinalidad. El significado de los diferentes valores es el siguiente:

  n = 1

Para cada registro de la tabla de verificación existe exactamente un registro dependiente (registro de la tabla de claves externas).

n = 0..1

Existe como máximo un registro dependiente para cada registro de la tabla de verificación. Pero hay registros de la tabla de verificación para los que no hay ningún registro dependiente en la tabla de claves externas.

n = 1..*

Existe al menos un registro dependiente para cada registro de la tabla de verificación.

n = 0..*

Puede haber cualquier cantidad de registros dependientes para cada registro de la tabla de verificación: ninguno, uno o más.

En nuestro ejemplo, debe preguntarse: ¿Cuántos empleados se pueden asignar al mismo departamento? ¿Exactamente uno? ¿A lo sumo uno? ¿Al menos uno? ¿Algún número? ¿Qué crees?

Cómo definir una relación de clave externa

Reproduzca el vídeo para ver cómo definir una relación de clave externa.

Definir una relación de clave externa

Defina una segunda tabla de base de datos para departamentos y defina la relación de clave externa entre departamentos y empleados.

Modelo:

  • /LRN/EMPLOY_DEP (Definición de tabla de base de datos)

Solución:

  • /LRN/DEPMENT_REL (Definición de tabla de base de datos)
  • /LRN/EMPLOY_REL (Definición de tabla de base de datos)
  • /LRN/DEPMENT_HEAD (elemento de datos)
  • /LRN/DEPMENT_ASSISTANT (elemento de datos)

Prerrequisitos

Para este ejercicio, necesita la tabla de base de datos para los datos de empleado que ha creado y rellenado en un ejercicio anterior (el nombre sugerido era: Z##EMPLOY, donde ## es su número de grupo). Si no ha finalizado este ejercicio, cree una copia de la tabla de base de datos /LRN/EMPLOY_DEP.

Tarea 1: Definir una tabla de base de datos para datos de departamento

Cree una definición de tabla de base de datos para almacenar datos de departamento (nombre sugerido: Z##DEPMENT, donde ## es su número de grupo).

Además del campo de cliente, añada los siguientes campos:

Nombre de campoElemento de datos
IDZ##_DEPARTMENT_ID (creado en el ejercicio anterior)
descripción/LRN/DEPMENT_DESCRIPTION

Añada el campo id a la clave de tabla e incluya la estructura /LRN/S_ADMIN para datos administrativos en la lista de campos.

Pasos

  1. Cree un nuevo objeto de desarrollo del tipo Tabla de base de datos (nombre sugerido: Z##DEPMENT).

    1. En el Explorador de proyectos, despliegue el paquete y abra el menú contextual en el subnodo Diccionario.

    2. Seleccione Nueva→tabla de base de datos.

    3. Confirme el paquete, introduzca el nombre Z##DEPMENT y la descripción Departamento y, a continuación, seleccione Siguiente.

    4. Asigne el nuevo objeto a una orden de transporte y seleccione Finalizar.

    5. El código de la definición de la tabla de base de datos debería tener el siguiente aspecto:

      Code Snippet
      123456789101112
      @EndUserText.label : 'Department' @AbapCatalog.enhancement.category : #NOT_EXTENSIBLE @AbapCatalog.tableCategory : #TRANSPARENT @AbapCatalog.deliveryClass : #A @AbapCatalog.dataMaintenance : #RESTRICTED define table z##depment { key client : abap.clnt not null; }
  2. Después del campo de cliente, añada un segundo ID de campo clave y escríbalo con el elemento de datos Z##_DEPARTMENT_ID.

    Nota

    Si no ha completado el ejercicio correspondiente, utilice el elemento de datos /LRN/DEPARTMENT_ID en su lugar.
    1. Ajuste el código de la siguiente manera:

      Code Snippet
      12345678
      define table z##depment { key client : abap.clnt not null; key id : z##_department_id; }
  3. Añada una descripción de campo basada en el elemento de datos /LRN/DEPMENT_DESCRIPTION.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      123456789
      define table z##depment { key client : abap.clnt not null; key id : z##_department_id; description : /lrn/depment_description; }
  4. Estructura Include /LRN/S_ADMIN con campos administrativos.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      12345678910
      define table z##depment { key client : abap.clnt not null; key id : z##_department_id; description : /lrn/depment_description; include : /lrn/s_admin; }
  5. Actualice las opciones técnicas de la tabla. Utilice la ayuda para entradas para seleccionar los valores adecuados para la clase de datos y la categoría de tamaño.

    Nota

    Esperamos que la tabla contenga menos de 100 entradas.
    1. Haga clic con el botón derecho en cualquier lugar del editor y seleccione Abrir Otros→Opciones técnicas.

    2. Seleccione APPL0 Datos maestros, tabla transparente.

    3. Seleccione 0 Registros previstos 0 - 2.600.

  6. Active las opciones técnicas de tabla y la definición de tabla de base de datos.

    1. Mientras aún está en el diálogo Opciones de tabla técnica, pulse Ctrl + F3 para activar las opciones técnicas de la tabla.

    2. Vuelva al editor con el código fuente de la definición de tabla de base de datos y pulse Ctrl + F3 para activar la definición de tabla de base de datos.

Tarea 2: Definir una relación de clave externa

Defina una relación de clave externa entre sus tablas de base de datos para datos de empleado y datos de departamento. La relación debe documentar que los empleados solo se pueden asignar a departamentos existentes. O, en otras palabras, en el campo department_id de la tabla Z##EMPLOY, solo se permiten aquellos valores para los que existe una entrada en la tabla Z##DEMENT. Seleccione una cardinalidad adecuada para documentar que cualquier número de empleados se puede asignar a un único departamento.

Pasos

  1. Identifique la tabla de claves externas y navegue hasta el campo de verificación.

    1. Abra la definición de su tabla de base de datos para los datos de empleado (el nombre sugerido era Z##EMPLOY).

    2. Desplácese hacia abajo hasta el campo department_id.

  2. Añada una clave externa al campo de verificación.

    Consejo

    Utilice la finalización de código siempre que sea posible.
    1. En la definición del campo department_id, coloque el cursor antes del punto y coma (;) de cierre y pulse Intro para insertar una nueva fila de código.

    2. Coloque el cursor al principio de la nueva fila y pulse Ctrl + Espacio para invocar la finalización del código.

    3. En la lista de sugerencias, seleccione con clave externa - palabra clave.

    4. Introduzca un espacio en blanco y pulse Ctrl + Espacio para volver a llamar la compleción de código.

    5. En la lista de sugerencias, seleccione su tabla de base de datos para los datos de departamento, es decir, la entrada z##envío - tabla.

    6. Introduzca un espacio en blanco y utilice la finalización de código para introducir la palabra clave WHERE.

    7. Siga utilizando la compleción de código para añadir la asignación de campos clave (en el lado izquierdo) y campos de clave externa (en el lado derecho).

  3. Guarde la definición de la tabla de base de datos para invocar el formato automático.

    Nota

    Al guardar la definición, el editor también añade la anotación @AbapCatalog.foreignKey.screenCheck.
    1. Pulse Ctrl + Espacio para guardar el objeto de desarrollo.

    2. El código ahora debería tener el siguiente aspecto:

      Code Snippet
      12345678
      entry_date : z##_entry_date; @AbapCatalog.foreignKey.screenCheck : false department_id : z##_department_id with foreign key z##depment where client = z##employ.client and id = z##employ.department_id;
  4. Añada una cardinalidad para documentar que se puede utilizar un único ID de departamento en cualquier cantidad de conjuntos de datos de empleados y que, por otro lado, cada empleado debe asignarse a un departamento existente.

    1. Ajuste el código de la siguiente manera:

      Code Snippet
      12345678
      entry_date : z##_entry_date; @AbapCatalog.foreignKey.screenCheck : false department_id : z##_department_id with foreign key [0..*,1] z##depment where client = z##employ.client and id = z##employ.department_id;
  5. Active la definición de la tabla de base de datos.

    1. Pulse Ctrl + F3 para activar el objeto de desarrollo.

Tarea 3: Definir jefe de departamento y asistente

Amplíe la tabla de base de datos para los datos de departamento con campos para el jefe de departamento y el asistente de departamento (nombres sugeridos: head_id y assistance ant_id). Defina un nuevo elemento de datos para cada uno de los campos, pero asegúrese de utilizar el mismo dominio que en el campo employee_id de su tabla de empleados. A continuación, defina una relación de clave externa para cada uno de los campos para documentar que solo se permiten números de empleado existentes.

Pasos

  1. Edite la lista de campos de su tabla de base de datos para datos de departamento. Antes de la sentencia INCLUDE, añada los siguientes campos y utilice una corrección rápida para crear los nuevos elementos de datos:

    Nombre de campoElemento de datos
    department_headZ##_DEPMENT_HEAD
    ayudante de departamentoZ##_DEPMENT_ASSISTANT

    Para ambos elementos de datos, utilice su dominio Z##_EMPLOYEE_IDcomo tipo de datos.

    Nota

    Solo si no ha creado un dominio Z##_EMPLOYEE_ID, puede utilizar el dominio /LRN/EMPLOYEE_ID en su lugar. Asegúrese de que el ID de campo clave de su tabla de base de datos para datos de empleado (el nombre sugerido era Z##EMPLOY) se base en el mismo dominio.
    1. Al final de la lista de elementos, introduzca department_head : z##_depment_head; (siendo ## su número de grupo).

    2. Abra la vista Problemas. Debería ver un error Campo DEPARTMENT_HEAD: el tipo de componente o el dominio utilizado no está activo o no existe.

    3. Sitúe el cursor enz##_depment_head y pulse Ctrl + 1 para abrir el menú de corrección rápida.

    4. Desde el menú de corrección rápida, haga doble clic en Crear elemento de datos ....

    5. Confirme el paquete y el nombre, introduzca una descripción, por ejemplo, Jefe de departamento, y seleccione Siguiente.

    6. Asigne el nuevo objeto a una orden de transporte y seleccione Finalizar.

    7. En Nombre de tipo, introduzca Z##_EMPLOYEE_ID e introduzca las siguientes etiquetas de campo:

      CampoValor
      Breve

      Sal. Cabecera

      Medio

      Jefe de departamento

      Largo

      Jefe de departamento

      Cabecera

      Jefe de departamento

    8. Active el nuevo elemento de datos y vuelva a la tabla de base de datos Z##DEPMENT.

    9. En una nueva línea de código, introduzca assistant_id : Z##_depment_assistant; y utilice la corrección rápida de nuevo para crear el elemento de datos Z##_DEPMENT_ASSISTANT utilizando el mismo dominio, pero con las siguientes etiquetas de campo:

      CampoValor
      Breve

      Asistente

      Medio

      Sal. Asistente

      Largo

      Asistente de departamento

      Cabecera

      Asistente de departamento

  2. Para ambos campos nuevos, añada una relación de clave externa con la tabla Z##EMPLOY como tabla de verificación. A continuación, guarde la definición de la tabla de base de datos para invocar el formato automático.

    Consejo

    Utilice la finalización de código siempre que sea posible.
    1. Después de aplicar el formato automático, el código debería tener el siguiente aspecto:

      Code Snippet
      123456789101112131415161718192021
      define table z##depment { key client : abap.clnt not null; key id : z##_department_id not null; description : /lrn/depment_description; @AbapCatalog.foreignKey.screenCheck : false head_id : z##_depment_head with foreign key z##employ where client = z##depment.client and employee_id = z##depment.head_id; @AbapCatalog.foreignKey.screenCheck : false assistant_id : z##_depment_assistant with foreign key z##employ where client = z##depment.client and employee_id = z##depment.assistant_id; include /lrn/s_admin; }
  3. Añada una cardinalidad a ambas relaciones de clave externa. Seleccione la cardinalidad en función de la siguiente información:

    • No todos los empleados pueden ser un jefe de departamento o un asistente de departamento.
    • El mismo empleado no puede ser jefe de más de un departamento.
    • El mismo empleado no puede ser un ayudante de más de un departamento.
    • Cada departamento necesita exactamente un asistente de departamento.
    • Un departamento bien podría prescindir de un jefe de departamento.
    1. Ajuste el código de la siguiente manera:

      Code Snippet
      12345678910111213
      @AbapCatalog.foreignKey.screenCheck : false head_id : z##_depment_head with foreign key [0..1,0..1] z##employ where client = z##depment.client and employee_id = z##depment.head_id; @AbapCatalog.foreignKey.screenCheck : false assistant_id : z##_depment_assistant with foreign key [0..1,1] z##employ where client = z##depment.client and employee_id = z##depment.assistant_id;
  4. Active la definición de la tabla de base de datos.

    1. Pulse Ctrl + F3 para activar el objeto de desarrollo.

Tarea 4: Rellenar tablas

Rellene la nueva tabla de base de datos con algunos datos de departamento y actualice la tabla de empleados. Para ello, cree una copia de la clase ABAP /LRN/CL_S4D430_CHECK_AND_FILL y ajuste los valores de las constantes c_version, c_employ_table y c_depment_table. A continuación, active y ejecute la clase como una aplicación de consola.

Pasos

  1. Cree una copia de la clase ABAP /LRN/CL_S4D430_CHECK_AND_FILL, denomínela Z##_S4D430_CHECK_AND_FILL y colóquela en el paquete ZS4D430_##.

    Nota

    Omita este paso si ha creado una copia de /LRN/CL_S4D430_CHECK_AND_FILL en un ejercicio anterior.
    1. En la vista Explorador de proyectos, localice la clase ABAP en el paquete /LRN/S4D430_EXERCISE y haga clic con el botón derecho para abrir el menú contextual.

    2. En el menú contextual, seleccione Duplicar.

    3. Introduzca el nombre del paquete, el nombre de la copia y una descripción. A continuación, seleccione Siguiente.

    4. Asigne el nuevo objeto a una orden de transporte y seleccione Finalizar.

  2. Modifique el valor de la constante c_version de lcl_generador=>employee_table_only a lcl_generador=>with_Relations.

    Consejo

    Puede añadir un signo de comentario delante de la definición actual y eliminar el signo de comentario de la segunda alternativa de definición.
    1. Ajuste el código de la siguiente manera:

      Code Snippet
      12345
      * CONSTANTS c_version TYPE t_version VALUE lcl_generator=>employee_table_only. CONSTANTS c_version TYPE t_version VALUE lcl_generator=>with_relationships. * CONSTANTS c_version TYPE t_version VALUE lcl_generator=>with_extensions.
  3. Modifique los valores de las constantes c_employ_table y c_depment_table por los nombres de sus tablas de base de datos.

    1. Desplácese hacia abajo hasta la fila de código que empieza por CONSTANTS c_employ_table.

    2. Si el literal después de VALUE aún contiene ##, sustitúyalo por su número de grupo.

    3. Desplácese hacia abajo hasta la fila de código que empieza por CONSTANTS c_depment_table.

    4. En el literal después de VALUE, sustituya ## por su número de grupo.

  4. Active la clase ABAP y ejecútela como una aplicación de consola. Si la salida de la consola contiene errores, ajuste la definición de las tablas de base de datos hasta que sean compatibles con las definiciones de tabla de base de datos /LRN/EMPLOY_REL y LRN/DEPMENT_REL.

    1. Pulse Ctrl + F3 para activar el objeto de desarrollo.

    2. Pulse F9 para ejecutar la clase ABAP como aplicación de consola.

    3. Asegúrese de que la salida de la consola contiene el texto Tabla rellenada ... para ambas tablas de base de datos.