Core Data Services (CDS)
Modelos de datos que se definen una vez y se ejecutan en la base de datos, con relaciones, anotaciones y control de acceso.
- Apartados
- 12
- Revisado
- Octubre de 2026
- Fuentes
- 2 enlaces
Qué son las vistas CDS
Una vista CDS describe datos de una o varias tablas con un lenguaje parecido a SQL. Además de leer, añade significado: relaciones con otras vistas (asociaciones), textos y unidades (anotaciones) y permisos (roles DCL). Es la base de RAP, de Fiori elements y de la analítica en S/4HANA.
Desde ABAP 7.55 se usan las CDS view entities (define view entity). Las vistas antiguas con @AbapCatalog.sqlViewName están obsoletas.
El modelo de datos virtual (VDM)
SAP S/4HANA trae miles de vistas CDS organizadas en capas: el modelo de datos virtual. En lugar de leer VBAK o KNA1 con sus nombres de cinco letras, usas vistas con nombres legibles en inglés, como I_SalesOrder o I_Customer.
| Prefijo | Significado | Ejemplo |
|---|---|---|
| I_ | Vista de interfaz (básica o compuesta), reutilizable | I_SalesOrder, I_Customer |
| C_ | Vista de consumo para una app o un informe | C_SalesOrderManage |
| R_ | Vista raíz de un objeto de negocio RAP | R_SalesOrderTP |
| A_ | Vista publicada como API remota | A_SalesOrder |
| Z / Y | Tus propias vistas: se recomienda seguir los mismos prefijos | ZI_Pedido, ZC_Pedido |
- Para buscar la vista que necesitas, abre en ADT la tabla (por ejemplo
VBAK) y usa Where-Used List filtrando por vistas CDS. - Comprueba en la pestaña Properties › API State que esté liberada (Released).
- En S/4HANA también puedes usar la app Fiori View Browser para buscar vistas por nombre o por tabla.
De la vista clásica a la view entity
@AbapCatalog.sqlViewName: 'ZVPEDIDO'
@AccessControl.authorizationCheck: #CHECK
define view ZI_Pedido
as select from vbak
{
key vbeln as Pedido,
erdat as FechaCreacion,
kunnr as Cliente,
netwr as Importe,
waerk as Moneda
}@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Pedido de venta'
define view entity ZI_Pedido
as select from vbak
{
key vbeln as Pedido,
erdat as FechaCreacion,
kunnr as Cliente,
vkorg as OrgVentas,
@Semantics.amount.currencyCode: 'Moneda'
netwr as Importe,
waerk as Moneda
}- No crea una vista SQL adicional en el diccionario.
- Comprueba mejor los tipos y las anotaciones.
- Se activa más rápido y es la única opción en ABAP Cloud.
Asociaciones
Una asociación declara una relación con otra vista. La base de datos solo hace el JOIN cuando alguien usa la asociación.
define view entity ZI_PedidoCliente
as select from vbak
association [1..1] to I_Customer as _Cliente
on $projection.Cliente = _Cliente.Customer
{
key vbeln as Pedido,
kunnr as Cliente,
_Cliente
}Desde ABAP se sigue la asociación con una expresión de ruta:
SELECT Pedido,
\_Cliente-CustomerName AS NombreCliente
FROM ZI_PedidoCliente
INTO TABLE @DATA(lt_pedidos).Vistas con parámetros
define view entity ZI_PedidosDesde
with parameters p_desde : abap.dats
as select from vbak
{
key vbeln as Pedido,
erdat as Fecha
}
where erdat >= $parameters.p_desdeSELECT * FROM ZI_PedidosDesde( p_desde = @( sy-datum - 30 ) )
INTO TABLE @DATA(lt_pedidos).Control de acceso con DCL
Un rol CDS filtra automáticamente las filas según las autorizaciones del usuario. No hace falta escribir AUTHORITY-CHECK en cada programa.
@EndUserText.label: 'Acceso a pedidos'
@MappingRole: true
define role ZI_Pedido {
grant select on ZI_Pedido
where ( OrgVentas ) = aspect pfcg_auth( V_VBAK_VKO, VKORG, ACTVT = '03' );
}Tipos de objeto CDS
| Objeto | Para qué sirve |
|---|---|
| View entity | Leer y combinar datos: la vista de uso general |
| Projection view | Exponer solo lo que necesita un servicio o una app (RAP) |
| Custom entity | Datos que calcula una clase ABAP, no la base de datos |
| Table function | Datos calculados con SQLScript en un método AMDP |
| Metadata extension | Anotaciones de interfaz (Fiori) separadas de la vista |
| Rol DCL | Permisos sobre las filas de una vista |
Cálculos, CASE y agregaciones
Una vista CDS puede calcular campos, convertir tipos, clasificar con CASE y agrupar. Todo se ejecuta en la base de datos.
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Ventas por cliente'
define view entity ZI_VentasCliente
as select from vbak
{
key kunnr as Cliente,
waerk as Moneda,
count( * ) as NumPedidos,
@Semantics.amount.currencyCode: 'Moneda'
sum( netwr ) as Total,
max( erdat ) as UltimoPedido
}
group by kunnr, waerkdefine view entity ZI_PedidoTipo
as select from vbak
{
key vbeln as Pedido,
case auart
when 'TA' then 'Normal'
when 'SO' then 'Urgente'
else 'Otro'
end as TipoPedido,
concat_with_space( vkorg, vtweg, 1 ) as Area,
dats_days_between( erdat, $session.system_date ) as DiasDesdeAlta
}| Necesitas… | En CDS |
|---|---|
| Unir textos | concat( a, b ) o concat_with_space( a, b, 1 ) |
| Convertir tipos | cast( campo as abap.char(10) ) |
| Valor si es nulo | coalesce( campo, 0 ) |
| Redondear o dividir | round( a, 2 ), division( a, b, 2 ) |
| Convertir moneda o unidad | currency_conversion( … ), unit_conversion( … ) |
| Fechas | dats_days_between( a, b ), dats_add_days( a, n, 'FAIL' ) |
Las anotaciones más usadas
Las anotaciones (@…) añaden significado a la vista y a sus campos. Las lee el compilador, el framework de autorizaciones, Fiori o la analítica.
| Anotación | Para qué sirve |
|---|---|
@EndUserText.label | Texto descriptivo de la vista o del campo |
@AccessControl.authorizationCheck | Si se comprueban autorizaciones con un rol DCL |
@Semantics.amount.currencyCode | Une un importe con su moneda |
@Semantics.quantity.unitOfMeasure | Une una cantidad con su unidad |
@ObjectModel.text.element | Indica qué campo tiene el texto de un código |
@Consumption.valueHelpDefinition | Ayuda de búsqueda (F4) en Fiori |
@Search.searchable | Permite la búsqueda libre en la vista |
@UI.lineItem, @UI.selectionField | Columnas y filtros de una app Fiori elements |
@Analytics.dataCategory | Cubo, dimensión o hecho para informes analíticos |
Tipos simples de CDS
En las versiones recientes (ABAP Cloud y S/4HANA 2023 o posterior) los tipos se pueden definir también en CDS, como sucesores de los elementos de datos del diccionario. Se reutilizan en vistas, tablas y código ABAP.
@EndUserText.label: 'Estado del viaje'
define type ZEstadoViaje : abap.char( 1 );DATA lv_estado TYPE zestadoviaje.
SELECT FROM ZI_Viaje
FIELDS ViajeId
WHERE Estado = @( CONV zestadoviaje( 'A' ) )
INTO TABLE @DATA(lt_aceptados).Ampliar vistas estándar sin modificarlas
Si una vista de SAP está liberada para ampliaciones (contrato C0), puedes añadirle campos con una extensión. La vista original no se toca y sobrevive a las actualizaciones.
extend view entity ZI_Pedido with
{
vbak.auart as ClasePedido,
vbak.vtweg as CanalDistribucion
}Los campos nuevos tienen que venir de las fuentes de datos de la vista o de sus asociaciones. Para las vistas de SAP, comprueba primero en ADT que admitan ampliaciones.
Probar y depurar vistas CDS
- F8 en ADT abre la vista previa de datos: puedes filtrar, ordenar y seguir asociaciones con un clic.
- Dependency Analyzer (botón derecho › Open With) dibuja todas las vistas y tablas de las que depende una vista.
- SQL Console ejecuta consultas ABAP SQL al momento, sin crear un programa.
- Active Annotations muestra todas las anotaciones que recibe un campo, incluidas las heredadas.
Para pruebas unitarias, el CDS Test Double Framework sustituye las tablas por datos de prueba, sin depender de lo que haya en el sistema:
CLASS ltc_pedido DEFINITION FINAL FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA go_entorno TYPE REF TO if_cds_test_environment.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS setup.
METHODS lee_pedidos FOR TESTING.
ENDCLASS.
CLASS ltc_pedido IMPLEMENTATION.
METHOD class_setup.
go_entorno = cl_cds_test_environment=>create( i_for_entity = 'ZI_PEDIDO' ).
ENDMETHOD.
METHOD class_teardown.
go_entorno->destroy( ).
ENDMETHOD.
METHOD setup.
go_entorno->clear_doubles( ).
ENDMETHOD.
METHOD lee_pedidos.
DATA lt_vbak TYPE STANDARD TABLE OF vbak WITH EMPTY KEY.
lt_vbak = VALUE #( ( vbeln = '0000000001' netwr = 100 waerk = 'EUR' )
( vbeln = '0000000002' netwr = 250 waerk = 'EUR' ) ).
go_entorno->insert_test_data( lt_vbak ).
SELECT FROM zi_pedido FIELDS Pedido INTO TABLE @DATA(lt_res).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lines( lt_res ) ).
ENDMETHOD.
ENDCLASS.