SENTENCIAS SQL
|
6.1. SENTENCIAS OPEN SQL:
Se llaman sentencias Open SQL a aquellas propias de Abap/4 que simulan un subconjunto de sentencias SQL (“Structured Query Language”). En general, las sentencias SQL (del tipo que sean) se usan para el acceso a datos en tablas. Las Open SQL tratan tablas de bases de datos (es decir, las tablas del Diccionario de Datos) mientras que las Native SQL tratan tablas internas).
Las sentencias Open SQL son: SELECT (lectura de registros de una tabla), INSERT (inserción de un registro en una tabla), UPDATE (modificación de un registro), OPEN CURSOR (abre un cursor), FETCH (avanza una posición el cursor), CLOSE CURSOR (cierra un cursor), COMMIT WORK (actualiza los últimos cambios de la BD, confirmando que se hacen las modificaciones), ROLLBACK WORK (deshace las modificaciones hechas a la BD volviendo al último checkpoint).
- 6.1.1. Sentencia SELECT:
- SELECT [ SINGLE ]campos FROM tabla[ INTO … | APPENDING … ] [ WHERE …][ GROUP BY campos][ ORDER BY criterio].…[ ENDSELECT ].
- Con SELECT se leen registros de una tabla del Diccionario de Datos (no vale para leer de una tabla interna). La tabla se indica tras FROM. Se pueden especificar los campos a leer (si se desean leer todos los campos de la tabla, poner un ‘*’ como ‘campos’) y si se trata de una lectura individual o múltiple (con SINGLE sólo se lee el primer registro que cumpla los criterios WHERE de búsqueda, acabando el SELECT. En este caso no se debe cerrar éste con ENDSELECT. Y sin SINGLE se leen todas las entradas que concuerden con dichos criterios). Devuelve SY-SUBRC 0 si encuentra algo (y en SY-DBCNT el nº de entradas leídas); y si no, 4. Parámetros:
Ejemplo:
- [ SINGLE [ FOR UPDATE ]][DISTINCT] { * | campos | MAX(c) AS m | MIN(c) AS m | AVG(c) AS m | SUM(c) AS m | COUNT(c) AS m | COUNT DISTINCT(c) AS m | COUNT(*) AS m }: Con DISTINCT se excluyen automáticamente las líneas duplicadas. Se puede especificar, en lugar de campos a leer, un parámetro ‘AS’ para que el SELECT simplemente calcule un valor numérico, como el máximo, mínimo, media, suma, … de todas las entradas (numéricas) encontradas.
- FROM tabla | vista | (tabla) [ CLIENT SPECIFIED ] [ BY PASSING BUFFER ] [ UP TO n ROWS ]: Este ‘parámetro’ es obligatorio. Especifica la tabla de la base de datos a leer. La tabla o vista debe existir en el D.D. y debe estar declarada con TABLES en el programa. Con (tabla) puede especificarse la tabla o vista dinámicamente (aquí ‘tabla’ es una variable). El mandante se especifica con CLIENT SPECIFIED. Con BY PASSING BUFFER se lee directamente de la base de datos sin pasar por el buffer de SAP. Se usa UP TO n ROWS para leer hasta una línea determinada (si n = 0, se leen todas; si n < 0, es un error).
- APPENDING[ CORRESPONDING FIELDS OF ] TABLE tabla[ PACKAGE SIZE n] Añade (INTO machaca) directamente los registros leídos en la tabla interna especificada.
- INTO[ CORRESPONDING FIELDS OF ] { field-string | TABLE tabla } [ PACKAGE SIZE n ]: Se usa para indicar al sistema el lugar donde debe dejar el dato leído (en una tabla interna o en un registro), y si guarda todos los campos o bien sólo los iguales en nombre. De esta forma no hace falta moverlos con un MOVE de la tabla de la BD a la tabla interna, basta hacer directamente el APPEND o COLLECT.
- WHERE campo_BD operador campo: En las cláusulas WHERE se definen los criterios de selección. Serán seleccionadas todas las entradas (si existen) de la tabla que cumplan estos criterios (o sólo la primera si es un SELECT SINGLE). SinWHERE se lee toda la tabla. Primero se escribe siempre el campo de la tabla de la BD (sólo el nombre del campo, sin el nombre de la tabla) y luego el campo o variable con el que se compara. Los operadores pueden ser: EQ, NE, LT, LE, GT, GE, =, <> o bien ><, <, <=, >, >=. Hay otros operadores especiales: [ NOT ] BETWEEN c1 AND c2, [ NOT ] LIKE c [ ESCAPE e ], [ NOT ] IN (c1, …, cn), [ NOT ] IN criterio_selección,IS [ NOT ] NULL (tabla_condiciones).
- GROUP BY campo1 … campon (tabla): Esta opción permite combinar el contenido de un grupo de entradas de una tabla de la BD, en una única línea. Los campos a agrupar pueden especificarse de forma estática (en tiempo de compilación) o dinámica (en ejecución).
- ORDER BY[ PRIMARY KEY ] campo1 [ ASCENDING | DESCENDING ] … campon [ ASCENDING | DESCENDING ](tabla): Este parámetro sirve para definir el orden de tratamiento (criterio de ordenación) de las líneas seleccionadas por el SELECT. Con PRIMARY KEY la tabla se ordena por la clave primaria. Se puede ordenar por varios campos, de forma ascendente (por defecto) o descendente. También puede especificarse el criterio de ordenación a través de una tabla (definida con entradas de 72 caracteres máximo. En cada línea de la tabla se especifica un criterio de ordenación).
SELECT * FROM name WHERE campo1 = 'valor1' AND campo2 = 'valor2'. WRITE: / name-campo1, name-campo2. ENDSELECT.
- INSERT [ INTO ] { tabla | (c) } [ CLIENT SPECIFIED ] [ VALUES field-string | FROMfield-string ] | FROM TABLE tabla_interna[ ACCEPTINGDUPLICATE KEYS ] ].
- Con INSERT se añaden nuevas entradas a una tabla del Diccionario de Datos (para una tabla interna se haría con APPEND o COLLECT). Dicha tabla puede especificarse de forma directa, con ‘tabla’ (debe estar declarada con TABLES), o indirecta, con ‘(c)’. En ambos casos ésta debe existir en el D.D. Con FROM TABLE inserta en una sola operación todas las entradas de la tabla_interna. Con CLIENT-SPECIFIED se pueden insertar registros en la base de datos sobre otro mandante. El área de trabajo especificada en el field-string de VALUES debe ser tan ancha como el área de trabajo de la tabla de la base de datos. Con la opción ACCEPTING DUPLICATE KEYS, si una línea no puede ser insertada no se aborta la sentencia, aunque sigue devolviendo SY-SUBRC = 4.
Las sentencias Native SQL a aquellas tomadas directamente tal cual del lenguaje SQL. Todas estas sentencias tratan tablas internas. Son: LOOP, READ TABLE, DESCRIBE TABLE, MODIFY, WRITE TO, DELETE, SORT, CLEAR, REFRESH, FREE.
6.3. SENTENCIAS AT:
- LOOP AT tabla_interna [ INTO área_trabajo ] [ FROM índice1 ] [ TO índice2 ][ WHERE condición ] [ TRANSPORTING NO FIELDS ]. … ENDLOOP.
Lee entradas de una tabla interna, recorriéndola en un bucle. Cada entrada se lee y se envía a un área de trabajo. Con INTO se indica un área de trabajo distinta a la cabecera de la tabla (el área por defecto). Si no hay entradas en la tabla no se entra en el bucle, y se tendrá SY-SUBRC = 4 (también si ninguna entrada cumple las condiciones del WHERE). En cada vuelta, el campo SY-TABIX contiene el índice de la entrada actual. Con FROM y TO se delimita el rango de entradas a procesar, de una inicial a otra final. Con TRANSPORTING NO FIELDSno se copia la entrada procesada en el área de trabajo (se gana velocidad si por ejemplo sólo se desea contar el número de entradas, no procesarlas). Esta opción se puede usar junto con WHERE pero nunca con INTO. Con la sentencia CONTINUE puede pasarse a la vuelta siguiente, y con EXIT se abandona el bucle.
- READ TABLE tabla_interna [ INTO at ] { INDEXi | WITH KEY c1 = v1 ... cn = vn |WITHKEY = valor | WITH KEY clave } [ BINARY SEARCH ][ COMPARING c1 ... cn | COMPARING ALL FIELDS ][ TRANSPORTING c1 ... cn | TRANSPORTING NO FIELDS ].
Lee una línea de una tabla interna, a través de un índice o una clave (es más rápido que la búsqueda mediante LOOP … WHERE). Si se encuentra una entrada, devuelve SY-SUBRC = 0 y en SY-TABIX el índice de esa entrada; y SY-SUBRC = 4 en otro caso. Ocurre un error en ejecución si el índice a buscar es negativo; si es mayor que el número de entradas, se retorna SY-SUBRC = 4. Con INTO puede especificarse un área de trabajo distinta a la cabecera de la tabla.
- DESCRIBE TABLE tabla_interna [ LINES nr_líneas ] [ OCCURS occ ].
Pregunta información al sistema respecto a la tabla interna especificada. Con LINES se actualiza en la variable ‘nr_líneas’ el número de líneas de dicha tabla (esto es útil por ejemplo para saber si la tabla está vacía o no, antes de intentar mostrarla por pantalla). Con OCCURS, guarda en ‘occ’ el número de entradas con que está definida la tabla.
- MODIFY tabla_interna [ FROM área_trabajo ] [INDEX índice ] [ TRANSPORTING c1 ... cn | (campos) [ WHEREcondición ] ].
Modifica el contenido de una entrada de una tabla interna, a partir de la información del área de trabajo especificada con FROM, o por defecto de la cabecera. Con INDEX se especifica la entrada a modificar (entonces no es necesario escribir el MODIFY dentro de un LOOP), o bien se busca dicha entrada con la condición del WHERE. Con TRANSPORTINGsólo se actualizan los campos especificados (que se pueden dar de forma dinámica).
- WRITE campo[offset1] TO tabla_interna[offset2] INDEX índice.
Actualiza la entrada de índice especificado de la tabla interna dada. Los offset permiten escribir en sólo una parte de la entrada de la tabla, y se escriben así: +número, todo pegado al nombre del campo. La sentencia similar WRITE … TO pero sinINDEX sólo sirve para variables simples.
- DELETE tabla_interna [ INDEX índice ] [ FROM índice1 TO índice2 ] [ WHERE cond ][ ADJACENT DUPLICATES FROM itab [ COMPARING { f1...fn | ALL FIELDS } ] ].
Borra entradas de una tabla interna. Sin INDEX se usa dentro de un LOOP, y con INDEX fuera. Con ADJACENT DUPLICATESborra las entradas duplicadas conservando la primera. Dos líneas son consideradas duplicadas si sus campos clave son iguales, o bien si los campos f1 ... fn son iguales (si se especifican estos), o bien si todos sus campos son iguales (con ALL FIELDS).
- SORT tabla_interna [ ASCENDING | DESCENDING ] [ AS TEXT ][ BY campo1 [ASCENDING | DESCENDING ] AS TEXT ] … [ BY campon [ASCENDING | DESCENDING ] AS TEXT ].
Ordena una tabla interna por los criterios especificados. Por defecto, de forma ascendente respecto a los campos clave. Para ordenar por otro(s) campo(s), indicarlo con BY.
- CLEAR tabla_interna | campo.
Limpia o borra el área de trabajo de la tabla (la cabecera), pero no modifica ninguna entrada de la misma. También es aplicable a una variable simple (CLEAR está sobrecargado), y su efecto es borrarla (la pone a su valor inicial: SPACE o cero).
- REFRESH tabla_interna.
Limpia el contenido de la tabla interna, borrando todas sus entradas, pero preservando el valor de su cabecera.
- FREE tabla_interna | campo.
Libera el espacio ocupado en memoria por la tabla interna. También es aplicable a variables simples, destruyéndolas.
- Las sentencias AT permiten controlar el procesamiento de una tabla interna, dentro de un LOOP. Sólo se usan por tanto dentro de bucles LOOP. Permiten ejecutar condicionalmente un bloque de sentencias, dentro del bucle, según se cumpla o no una u otra condición. Son: ATNEW, AT END OF, AT FIRST, AT LAST.
- AT NEW campo. … ENDAT.
Con ATNEW se ejecuta el bloque cuando el campo especificado tiene un nuevo valor, es decir, que se activa al cambiar el campo su valor (se activa también en la primera vuelta, pues el campo pasará de INITIAL a su primer valor, pero no en la última vuelta, pues el campo no variará su valor). Puede convenir o no ordenar la tabla respecto ese campo.
- AT END OF campo. … ENDAT.
Con AT END OF se ejecuta el bloque cuando el campo especificado alcanza su último valor. Puede convenir o no ordenar la tabla por ese campo.
- AT FIRST.…ENDAT.
Con AT FIRST se ejecuta el bloque en la primera vuelta del LOOP.
- AT LAST.…ENDAT.
Con AT LAST se ejecuta el bloque en la última vuelta del LOOP.
- Dentro de ATNEW y ATEND OF, la sentencia SUM suma todos los campos numéricos de las entradas procesadas en estos bloques de proceso. Dentro de AT FIRST y AT LAST, suma los campos numéricos de todas las entradas de la tabla.
Ejemplo:
* Suma el subtotal para cada 'cliente' AT END OF cliente SUM importe. * Suma todas las entradas de la tabla, tras recorrerla AT LAST SUM.