Ejemplo Nº 003 – Mostrar un mensaje y una operación aritmética

1 comentario

Puedes también usar un solo SELECT para mostrar un mensaje y el resultado de una operación aritmética, como en este ejemplo:


SELECT 'La suma de 2 + 7 es:', 2 + 7 FROM RDB$DATABASE

Después de ejecutar esa consulta verás dos columnas:

  • Una que muestra el texto ‘La suma de 2 + 7 es:’
  • Otra que muestra el número 9

Un concepto importante a recordar es que los SELECT no solamente pueden retornar filas de una tabla, también pueden retornar constantes numéricas, constantes alfanuméricas, fórmulas y el resultado de funciones.

 

Anuncios

Ejemplo Nº 002 – Mostrar una operación aritmética

1 comentario

Si quieres obtener el resultado de una operación aritmética, también puedes usar un SELECT, como en este ejemplo:


SELECT 6 * 5 - 9 FROM RDB$DATABASE

Por legibilidad, es aconsejable que a los operandos y a los operadores los separes con espacios, pero eso no es obligatorio.

Después de ejecutar el SELECT obtendrás un cursor que tendrá una sola fila y una sola columna, el nombre de la columna será SUBSTRACT (porque la última operación aritmética que se hizo fue una resta) y su valor será 21 (porque es el resultado de la operación aritmética).

 

Ejemplo Nº 001 – Mostrando un mensaje

3 comentarios

Un SELECT te puede servir para mostrar tus propios mensajes, no solamente para mostrar las columnas de una tabla:


SELECT 'Firebird es una maravilla' FROM RDB$DATABASE

En Firebird toda instrucción SELECT debe tener la cláusula FROM y el nombre de una tabla. Como en este caso se desea mostrar un mensaje entonces la tabla correspondiente debe tener una fila y solamente una fila. Cualquier tabla que tenga una sola fila servirá perfectamente. Los programadores de Firebird suelen usar RDB$DATABASE porque es una tabla que se encuentra en todas las Bases de Datos (es una tabla interna o sea creada automáticamente por el Firebird) y además se garantiza que siempre tendrá una fila y nada más que una, pero cualquier otra tabla que tenga una sola fila serviría, por ejemplo:


SELECT ‘Puedes si piensas que puedes’ FROM EMPRESA

También funcionaría perfectamente … siempre y cuando la tabla EMPRESA tenga una sola fila.

Para evitarte complicaciones y tener una vida sencilla, lo mejor es que siempre utilices la tabla RDB$DATABASE la cual tendrás siempre disponible en cualquier instalación del Firebird.

 

Entendiendo las excepciones

9 comentarios

Una excepción es un mensaje que el Servidor le envía al Cliente para informarle que ocurrió un error.

(Si no tienes claro el concepto de Cliente/Servidor puedes leer este artículo: Entendiendo Cliente/Servidor)

Una excepción consta de dos partes:

  • El nombre de la excepción
  • El mensaje de la excepción

Aquí está el ejemplo de una excepción:

CREATE EXCEPTION E_SIN_CODIGO 'Falta el código del producto'

En este ejemplo, E_SIN_CODIGO es el nombre de la excepción y ‘Falta el código del producto’ es el mensaje que está asociado a esta excepción.

¿Qué sucede cuándo se envía una excepción?

Que el Firebird detiene lo que estaba haciendo y regresa al nivel anterior.

¿Dónde se usan las excepciones?

En los stored procedures y en los triggers.

Veamos un ejemplo:

CREATE EXCEPTION E_SIN_SUCURSAL 'Falta el Código de la Sucursal';
CREATE EXCEPTION E_SIN_IDENTIFICADOR 'No existe el Identificador';
CREATE EXCEPTION E_SIN_NOMBRE 'Falta el Nombre, no se puede dejar el nombre vacío';

CREATE TRIGGER PRODUCTOS_BIU FOR PRODUCTOS
   ACTIVE BEFORE INSERT OR UPDATE
   POSITION 1
AS
BEGIN

   IF (NEW.PRD_CODSUC IS NULL OR NEW.PRD_CODSUC < 0) THEN
      EXCEPTION E_SIN_SUCURSAL;

   IF (NEW.PRD_IDENTI IS NULL OR NEW.PRD_IDENTI <= 0) THEN
      EXCEPTION E_SIN_IDENTIFICADOR;

   IF (NEW.PRD_NOMBRE IS NULL OR CHAR_LENGTH(TRIM(NEW.PRD_NOMBRE)) = 0) THEN
      EXCEPTION E_SIN_NOMBRE;

END

Este es un trigger que se disparará antes de insertar o actualizar un producto y que sirve para validar que no se introduzcan datos incorrectos en la  tabla PRODUCTOS. Si se dispara una de esas excepciones entonces la fila no será ni insertada ni actualizada y el Cliente recibirá la excepción correspondiente para que sepa que ocurrió un error y también cual fue ese error

  • Si el código de la Sucursal es nulo o el Código de la Sucursal es menor que cero, se enviará la excepción E_SIN_SUCURSAL
  • Si el Identificador es nulo o el Identificador es menor o igual que cero, se enviará la excepción E_SIN_IDENTIFICADOR
  • Si el Nombre es nulo o el nombre está vacío, se enviará la excepción E_SIN_NOMBRE

Resumiendo:

  • Una excepción es un mensaje que el Servidor le envía al Cliente para informarle que ocurrió un error
  • Una excepción consta de dos partes:
    • El nombre de la excepción
    • El mensaje de la excepción
  • Cuando se envía una excepción el Firebird detiene lo que estaba haciendo y regresa al nivel anterior
  • Las excepciones se usan en los stored procedures y en los triggers

Artículos relacionados:

Entendiendo a los stored procedures

Entendiendo a los triggers

El índice del blog Firebird21

El foro del blog Firebird21

 

 

Unsupported on-disk structure for file xxx.FDB; found 32779, support 15

1 comentario

Si encuentras este error el problema es que estás ejecutando Interbase XE/XE2 y estás intentando abrir una Base de Datos de Firebird 2.x

Interbase no puede trabajar con bases de datos de Firebird y viceversa desde Interbase 7.x y Firebird 2.x

La solución es:

  • Desinstalar Interbase
  • Instalar Firebird 2.x (preferiblemente 2.5.2)

 

Entendiendo a los triggers

7 comentarios

Los triggers (desencadenantes, en castellano) son rutinas, procedimientos, código fuente, que se ejecutan en forma automática cuando se cumple alguna de estas condiciones:

  • Se está insertando una nueva fila
  • Se está borrando una fila
  • Se está actualizando una fila

¿Para qué sirven?

  1. Para asegurarnos que en la tabla se guarden datos válidos y solamente datos válidos.
  2. Para actualizar otra tabla cuyos datos dependen de esta tabla

Los triggers pueden “dispararse”:

  • Antes de la inserción, borrado, actualización
  • Después de la inserción, borrado, actualización

Los triggers que se disparan antes sirven para evitar que la tabla tenga datos inválidos

Los triggers que se disparan después sirven para actualizar a otras tablas cuyos datos dependen de esta tabla

Lo peor que le podría ocurrir a una tabla es tener datos inválidos o incorrectos dentro suyo. El nombre conque se conoce a dichos datos es “basura“. Si eres un buen programador, jamás permitirás que entre basura en una tabla tuya.

En los triggers se pueden usar unas “pseudo” variables llamadas NEW y OLD.

NEW nos indica el valor que tiene una columna antes de ser insertada en la tabla.

OLD nos indica el valor que tiene actualmente la columna en la tabla. O sea el valor que está grabado en ella.

NEW y OLD son muy útiles para comparar el valor que queremos introducir en una columna con el valor que ya está guardado en esa columna.

Por ejemplo, para detectar si el nuevo precio de venta es menor que el actual precio de venta podríamos escribir:

IF (NEW.PRD_PREVTA < OLD.PRD_PREVTA) THEN

Para detectar si el nuevo precio de venta es cero o menor que cero podríamos escribir:

IF (NEW.PRD_PREVTA <= 0) THEN

Para detectar si el nombre del producto está vacío podríamos escribir:

IF (CHAR_LENGTH(TRIM(NEW.PRD_NOMBRE)) = 0) THEN

Para detectar si el código del producto es NULL podríamos escribir:

IF (NEW.PRD_CODIGO IS NULL) THEN

En el caso de encontrar algún error debes elevar una EXCEPCIÓN y así conseguirás que la fila no sea insertada ni borrada ni actualizada.

Una tabla puede tener muchos triggers, el orden en que se ejecutan viene dado por el valor de POSITION. El primer trigger que se ejecuta es el que tiene POSITION 0, luego se ejecuta el que tiene POSITION 1, luego el que tiene POSITION 2, etc.

Resumiendo:

  • Los triggers son código fuente que se ejecuta automáticamente cuando se quiere:
    • Insertar una nueva fila
    • Borrar una fila
    • Actualizar una fila
  • Sirven para asegurar que en una tabla solamente se introduzcan datos válidos y para actualizar otras tablas cuyos datos dependen de esta tabla
  • Los triggers pueden dispararse:
    • Antes de la inserción, borrado, actualización
    • Después de la inserción, borrado, actualización
  • Dentro de los triggers se pueden usar dos pseudo-variables: NEW y OLD
    • NEW es el valor que tendrá la columna si se realiza la inserción o actualización exitosamente
    • OLD es el valor que actualmente tiene la columna
  • Si se encontró un error en un trigger se debe elevar una excepción para que esa fila no sea insertada ni borrada ni actualizada
  • Una tabla puede tener muchos triggers, el orden en el cual se ejecutan lo determina la variable POSITION

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

Entendiendo a los Stored Procedures

54 comentarios

Las bases de datos del Firebird sirven para guardar datos en ellas, para procesar dichos datos y para consultarlos cuando se los necesita.

  • En las tablas se guardan los datos
  • En los stored procedures y en los triggers se procesan los datos
  • Con las vistas se consultan los datos

Los stored procedures (procedimientos almacenados) son los equivalentes a las rutinas, procedimientos, o funciones disponibles en casi todos los lenguajes de programación (Visual FoxPro, Visual Basic, C, Delphi, Java, etc.), allí se utilizan los datos que se encuentran en las tablas, se realizan operaciones aritméticas o lógicas sobre esos datos y se devuelve el resultado de ese procesamiento.

Los stored procedures pueden recibir cero, uno, o varios parámetros de entrada y devolver cero, uno, o varios parámetros de salida.

En Firebird hay dos clases de stored procedures:

  • Ejecutables
  • Seleccionables

Los stored procedures ejecutables son llamados de manera similar a como se llaman las rutinas, procedimientos o funciones en los lenguajes de programación, por ejemplo:

EXECUTE PROCEDURE MiStoredProcedureEjecutable(123, ‘Firebird me gusta’)

Los stored procedures seleccionables en cambio son utilizados como si fueran tablas en un SELECT, por ejemplo:

SELECT * FROM MiStoredProcedureSeleccionable(123, ‘Firebird me gusta’)

La forma de escribirlos es casi la misma. Las únicas diferencias son:

  • Los stored procedures ejecutables pueden devolver cero filas o una fila, jamás pueden devolver más de una fila
  • Los stored procedures seleccionables pueden devolver cero filas, una fila, o muchas filas
  • Cuando finaliza un stored procedure ejecutable devuelve todos los parámetros de salida. Todos esos parámetros de salida son devueltos en una fila y solamente en una fila, jamás en más de una fila
  • Cada vez que un stored procedure seleccionable encuentra el comando SUSPEND le devuelve al SELECT que lo llamó todos los parámetros de salida, con los valores que tienen asignados en ese momento. O sea que devuelve una fila cada vez que encuentra el comando SUSPEND.

Veamos un ejemplo de un stored procedure ejecutable:

CREATE PROCEDURE EXISTE_NUMERO_DOCUMENTO(
   tcNroDoc TYPE OF COLUMN VENTASCAB.VTC_NRODOC)
RETURNS(
   ftcDocumentoExiste TYPE OF D_BOOLEAN)
AS
   DECLARE VARIABLE lcNroDoc TYPE OF COLUMN VENTASCAB.VTC_NRODOC;
BEGIN

   SELECT
      COALESCE(V.VTC_NRODOC, '')     -- Si VTC_NRODOC es nulo, devuelve una cadena vacía
   FROM
      VENTASCAB V
   WHERE
      V.VTC_NRODOC = :tcNroDoc
   INTO
      :lcNroDoc;

   ftcDocumentoExiste = 'F';

   IF (tcNroDoc = lcNroDoc) THEN
      ftcDocumentoExiste = 'V';

END;
  • Este stored procedure se llama EXISTE_NUMERO_DOCUMENTO
  • Recibe un parámetro de entrada llamado tcNroDoc cuyo tipo de datos es el mismo que tiene la columna VTC_NRODOC de la tabla VENTASCAB
  • Devuelve un parámetro de salida llamado ftcDocumentoExiste, el cual es de tipo D_BOOLEAN y por lo tanto puede valer “V” o “F”
  • Usa una variable que es local al stored procedure y cuyo nombre es lcNroDoc y su tipo también es igual al de la columna VTC_NRODOC
  • Busca en la tabla VENTASCAB un documento cuyo número sea igual al del parámetro de entrada (tcNroDoc) y guarda el resultado en la variable lcNroDoc
  • Supone que el documento que se está buscando no existe
  • Compara el parámetro de entrada tcNroDoc con el resultado de la búsqueda que se guardó en la variable lcNroDoc. Si son iguales eso significa que se encontró el número de documento buscado
  • Al terminar el stored procedure se devuelve el valor de la variable ftcDocumentoExiste (que puede ser o “V” o “F”) ya que ftcDocumentoExiste es el parámetro de salida

Veamos ahora un ejemplo de un stored procedure seleccionable:

CREATE PROCEDURE PRODUCTOS_CLASIFICADOS
  RETURNS(tnResultado SMALLINT)
AS
  DECLARE VARIABLE lnPreVta TYPE OF COLUMN PRODUCTOS.PRD_PREVTA;
BEGIN
   FOR SELECT 
      PRD_PREVTA 
   FROM 
      PRODUCTOS 
   INTO 
      :lnPreVta 
   DO BEGIN
      IF (lnPreVta < 1000) THEN
         tnResultado = 1;
      IF (lnPreVta >= 1000 AND lnPreVta <= 50000) THEN
         tnResultado = 2;
      IF (lnPreVta > 50000) THEN
         tnResultado = 3;
      SUSPEND;
   END
END

Este stored procedure lo que hace es clasificar a los productos según sus precios de venta: si el precio de venta es menor que 1.000, devuelve 1. Si el precio de venta está entre 1.000 y 50.000 devuelve 2. Si el precio de venta es mayor que 50.000 devuelve 3.

Cada vez que se llega al SUSPEND el parámetro de salida tnResultado se devuelve al SELECT para que éste lo muestre. Después que se le entregó al  SELECT el parámetro de salida tnResultado se procesa la siguiente fila, y así hasta procesarlas a todas las filas. Al SELECT se le devolverá una fila cada vez que se encuentre un SUSPEND. Entonces, si la tabla PRODUCTOS tiene 1.800 filas, este stored procedure seleccionable devolverá 1.800 filas.

SELECT
   *
FROM
   PRODUCTOS_CLASIFICADOS

Aunque PRODUCTOS_CLASIFICADOS es un stored procedure se lo utiliza como si fuera una tabla. ¿Por qué? porque es un stored procedure seleccionable ¿Y cómo sabemos que es un stored procedure seleccionable? Porque tiene el comando SUSPEND dentro suyo.

Resumiendo:

  • Los stored procedures se utilizan para procesar datos
  • Hay dos clases de stored procedures:
    • Ejecutables
    • Seleccionables
  • Los stored procedures ejecutables son llamados con EXECUTE PROCEDURE y pueden devolver cero filas o una fila
  • Los stored procedures seleccionables son llamados con SELECT y pueden devolver cero filas, una fila o muchas filas
  • La forma de escribirlos es casi la misma, la diferencia es que en los stored procedures ejecutables cuando finalizan devuelven los parámetros de salida, en cambio los stored procedures seleccionables devuelven los parámetros de salida cada vez que encuentran el comando SUSPEND
  • Cuando finaliza un stored procedure ejecutable devuelve sus parámetros de salida, con los valores que tienen en ese momento
  • Cada vez que un stored procedure seleccionable encuentra al comando SUSPEND devuelve sus parámetros de salida con los valores que tienen en ese momento

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21