Sentencia BEGIN ... END

La sentencia BEGIN ...END proporciona a las sentencias definidas en las palabras clave BEGIN y END el estado de una sentencia individual.

Esto permite a las sentencias contenidas:
  • Ser el cuerpo de una función o un procedimiento
  • Hacer que un manejador gestione sus excepciones
  • Interrumpir una ejecución mediante una sentencia LEAVE

SINTAXIS

La etiqueta sólo puede aparecer por segunda vez si existe una primera etiqueta. Si aparecen ambas etiquetas, éstas deben ser idénticas. Dos o más sentencias con etiqueta en el mismo nivel pueden tener la misma etiqueta, pero esto anula en parte la ventaja de la segunda etiqueta. La ventaja es que las etiquetas hacen que cada END, coincida de forma exacta y sin ambigüedades, con su BEGIN. No obstante, una sentencia que contiene una etiqueta anidada dentro de Sentencias no puede tener la misma etiqueta porque esto hace que el comportamiento de las sentencias ITERATE y LEAVE sea ambiguo.

Ámbito de las variables

Se abre un nuevo ámbito de variable local inmediatamente después del BEGIN inicial y, por lo tanto, las variables declaradas en esta sentencia están fuera del ámbito cuando se alcanza el END final. Si una variable local tiene el mismo nombre que una variable existente, cualquier referencia a dicho nombre se produce después de que la declaración acceda a la variable local. Por ejemplo:
DECLARE Variable1 CHAR 'Existing variable';

-- Un referencia a Variable1 devuelve 'Existing variable'

BEGIN
  -- Un referencia a Variable1 devuelve 'Existing variable'

  DECLARE Variable1 CHAR 'Local variable';  -- Está permitido aunque el nombre 
sea el mismo

  -- Un referencia a Variable1 devuelve 'Local variable'
END;

ATOMIC

Si se especifica ATOMIC, sólo se permite una instancia de un flujo de mensajes (es decir, una hebra) para ejecutar las sentencias de una sentencia BEGIN ATOMIC... END específica (identificada por su esquema y su etiqueta), en un momento dado. Si no hay ninguna etiqueta, el comportamiento es como si se hubiera especificado una etiqueta de longitud cero.

La construcción BEGIN ATOMIC es útil cuando deben realizarse varios cambios en una variable compartida y es importante evitar que otras instancias vean los estados intermedios de los datos. Observe el siguiente código de ejemplo:
CREATE PROCEDURE WtiteSharedVariable1(IN NewValue CHARACTER)
SharedVariableMutex1 : BEGIN ATOMIC
  -- Establecer el nuevo valor en la variable compartida
END;

CREATE FUNCTION ReadSharedVariable1() RETURNS CHARACTER
SharedVariableMutex1 : BEGIN ATOMIC
  DECLARE Value CHARACTER;
  -- Obtener valor de la variable compartida
  RETURN Value;
END;
El último ejemplo supone que el procedimiento WriteSharedVariable1 y la función ReadSharedVariable1 están en el mismo esquema y los nodos los utilizan en el mismo flujo. Sin embargo, no importa si el procedimiento y la función están contenidos o no dentro de módulos, o si se utilizan dentro de los mismos nodos o nodos diferentes. El intermediario asegura que, en cualquier momento, sólo una hebra esté ejecutando cualquiera de las sentencias dentro de las secciones ATOMIC. Así se garantiza que, por ejemplo, dos grabaciones simultáneas o una lectura y una grabación simultánea, se ejecuten en serie. Observe que:
  • La serialización está limitada al flujo. Dos flujos que utilicen sentencias BEGIN ATOMIC... END con el mismo esquema y etiqueta pueden ejecutarse simultáneamente. En relación a ello, varias instancias dentro de un flujo y varias copias de un flujo, no son equivalentes.
  • La serialización está limitada por el esquema y la etiqueta. Las sentencias ATOMIC BEGIN ... END especificadas en distintos esquemas o con distintas etiquetas, no interactúan entre sí.
Nota: Esto puede verse desde otro punto de vista. Para cada combinación de flujo de mensajes, esquema y etiqueta, el intermediario tiene un bloqueo de exclusión mutua que evita el acceso simultáneo a las sentencias asociadas a esa exclusión mutua (mutex).

No anide sentencias BEGIN ATOMIC... END, tanto directa como indirectamente, porque podría originar "inclusiones erróneas". Por ello, no utilice una sentencia PROPAGATE desde dentro de un bloque ATOMIC.

No es necesario utilizar la construcción BEGIN ATOMIC en flujos que nunca se desplegarán con más de una instancia (pero no es aconsejable dejar esto al azar). También es innecesario utilizar la construcción BEGIN ATOMIC en lecturas y grabaciones en variables compartidas. El intermediario siempre graba de forma segura un nuevo valor en una variable compartida, y también de forma segura lee el último valor de esa variable. ATOMIC sólo es necesario cuando la aplicación puede ver resultados intermedios.

Considere el siguiente ejemplo:
DECLARE LastOrderDate SHARED DATE;
...
SET LastOrderDate = CURRENT_DATE;
...
SET OutputRoot.XMLNSC.Data.Orders.Order[1].Date = LastOrderDate;
En este ejemplo suponemos que una hebra actualiza periódicamente LastOrderDate y otra lee periódicamente de ella. No es necesario utilizar ATOMIC, porque la segunda sentencia SET siempre lee un valor válido. Si la actualización y la lectura se realizan dentro de un intervalo de tiempo muy corto, no está definido si se lee el valor antiguo o el nuevo, pero siempre será uno o el otro. El resultado nunca será información no válida.
Observemos ahora el ejemplo siguiente:
DECLARE Count SHARED INT;
...
SET Count = Count + 1;
Aquí suponemos que hay varias hebras ejecutando periódicamente la sentencia SET. En este caso sí es necesario utilizar ATOMIC, porque es posible que dos hebras lean Count casi en el mismo instante, y obtengan el mismo valor. Ambas hebras realizan la adición y ambas almacenan el mismo valor de vuelta. Por tanto, el resultado final es N+1 y no N+2.

El intermediario no proporciona automáticamente ningún bloqueo de nivel superior a éste (por ejemplo, un bloqueo que cubra toda la sentencia SET), porque un bloqueo de este tipo podría originar "inclusiones erróneas".

Sugerencia

Puede considerar la sentencia BEGIN ... END como una construcción de bucle que siempre crea un solo bucle. Entonces, el efecto de una sentencia ITERATE o LEAVE anidada dentro de una sentencia BEGIN ... END es el que se espera: el control se transfiere a la sentencia que hay después de END. Utilizar ITERATE o LEAVE en una sentencia BEGIN ... END resulta práctico en los casos en los que hay una larga serie de cálculos que se han de abandonar ya sea porque se ha obtenido un resultado definitivo o porque se ha producido un error.

Conceptos relacionados
Visión general de ESQL
Tareas relacionadas
Desarrollo de ESQL
Referencia relacionada
Diagramas de sintaxis: tipos disponibles
Sentencias ESQL
Avisos | Marcas registradas | Descargas | Biblioteca | Soporte | Su opinión
Copyright IBM Corporation 1999, 2006 Última actualización: 22/08/2006
ak04940_