COALESCE()

3 comentarios

Descripción: Recibe dos o más argumentos y devuelve el primer argumento que no sea NULL. Si todos sus argumentos son NULL, el resultado también será NULL

Tipo de resultado: Depende de sus argumentos

Sintaxis:

      COALESCE(<expresión 1>, <expresión2> [, <expresión N> …])

Ejemplo:

SELECT
   COALESCE(PER_NOMBRE, 'Sr./Sra.') || ' ' || PER_APELLD AS NombrePersona
FROM
   PERSONAS

Si PER_NOMBRE no es NULL entonces mostrará PER_NOMBRE, si es NULL entonces mostrará ‘Sr./Sra.’. Después mostrará un espacio en blanco y después el apellido.

.

CHAR_LENGTH(), CHARACTER_LENGTH()

1 comentario

Descripción: Devuelve la cantidad de caracteres que tiene su argumento

Tipo de resulado: Integer

Sintaxis:

      CHAR_LENGTH(cadena_alfanumérica)

      CHARACTER_LENGTH(cadena_alfanumérica)

Ejemplo:

SELECT
   CHAR_LENGTH('Hola')
FROM
   RDB$DATABASE

Este SELECT devolverá el número 4, que es la cantidad de caracteres de la palabra “Hola”.

.

CEIL(), CEILING()

1 comentario

Descripción: Devuelve el menor número entero que es igual o mayor que su argumento

Tipo de resultado: BigInt o Doble Precisión

Sintaxis:

      CEIL[ING](número)

Ejemplos:

SELECT
   CEIL(27.00000001)
FROM
   RDB$DATABASE

El SELECT anterior devolverá 28 porque ése es el primer número entero que es igual o mayor que 27.00000001

SELECT
   CEIL(27.0000000)
FROM
   RDB$DATABASE

El SELECT anterior devolverá 27 porque ése es el primer número entero que es igual o mayor que 27.00000000

.

Modificaciones a los metadatos

3 comentarios

Cuando modificas un metadato (la estructura de una tabla, un índice, una Primary Key, etc.) siempre existe la posibilidad de que la Base de Datos se corrompa si es que hay usuarios que están usándola.

En realidad la probabilidad es pequeña pero existe (y si conoces la Ley de Murphy…)

Por lo tanto, lo recomendable es que siempre antes de cambiar un metadato obtengas acceso exclusivo a la Base de Datos.

 

 

.

 

 

Un stored procedure para conocer la cantidad de filas de todas las tablas

1 comentario

Como seguramente ya sabrás, usar la función COUNT(*) en tablas que tienen muchas filas no es una buena idea, porque como el Firebird no guarda la cantidad de filas que tiene cada tabla en algún lado, lo que hace la función COUNT() es recorrer la tabla desde el principio hasta el fin y contar cuantas filas hay en total.

Y claro que en tablas pequeñas, que tienen solamente algunas miles de filas no hay problema porque la función COUNT() trabaja muy rápido, pero en tablas grandes de millones y millones de filas es otra cosa, allí la espera puede ser desesperante.

Por eso, el siguiente stored procedure solamente es recomendable de ejecutar cuando todas las tablas de tu Base de Datos tienen pocas filas, o en casos excepcionales cuando necesitas conocer la cantidad de filas de cada tabla.

Este stored procedure seleccionable te mostrará, para cada tabla de tu Base de Datos, la cantidad de filas que tiene.

SET TERM ^ ;
CREATE PROCEDURE CANTIDAD_FILAS
RETURNS(
   NOMBRETABLA VARCHAR(32),
   FILAS INTEGER)
AS
DECLARE VARIABLE COMANDO VARCHAR(80);
BEGIN

 FOR SELECT RDB$RELATION_NAME
       FROM RDB$RELATIONS
      WHERE RDB$FLAGS = '1'
       INTO :NombreTabla
       DO BEGIN
          Comando = 'SELECT COUNT(*) FROM ' || :NombreTabla;
          EXECUTE STATEMENT COMANDO
          INTO :Filas ;
          SUSPEND;
       END

END^

SET TERM ; ^

Para ejecutarlo, escribe lo siguiente:

SELECT
   *
FROM
   CANTIDAD_FILAS

Valor duplicado en una Primary Key o en una Unique Key

1 comentario

Si una columna tiene la restricción Primary Key o la restricción Unique Key entonces no podrás tener valores duplicados en esa columna. Si lo intentas verás un mensaje similar al siguiente:

attempt to store duplicate value <visible to active transactions>in unique index RDB$PRIMARY1051

Este error ocurrirá en dos circunstancias:

  1. Cuando la Primary Key o la Unique Key ya están definidas y quieres insertar un valor que ya existe
  2. Cuando en una columna que tiene valores duplicados quieres definir una Primary Key o una Unique Key

 

.

 

Tratamiento de columnas NULL

8 comentarios

En el lenguaje SQL la palabra NULL significa “desconocida/o”.

Cuando establecemos que una columna de una tabla puede ser de tipo NULL lo que le estamos diciendo al Firebird es: “en esta columna podríamos tener algunos valores desconocidos”.

¿Establecer una columna como NULL podría causarnos problemas?

Pues sí, si es que nuestra aplicación no maneja correctamente a los NULL.

Entender como tratar a las columnas que pueden contener NULL es fundamental para que nuestra aplicación sea exitosa. En general, como una regla mientras no domines SQL:

  • No debes establecer NULL para las columnas numéricas, en lugar de eso ponerles como valor por defecto el número 0 (cero)
  • No debes establecer NULL para las columnas alfanuméricas, en lugar de eso ponerles como valor por defecto un espacio en blanco
  • No debes establecer NULL para las columnas de tipo fecha, en lugar de eso ponerles como valor por defecto una fecha muy antigua y que nunca usarás, como: ’01/01/1900′

¿Por qué es preferible ponerles valores por defecto a las columnas?

Porque el tratamiento de los valores de esas columnas se facilita. Por ejemplo, la función agrupada AVG() ignora a las columnas que tienen NULL para hallar el promedio. Y en general vas a querer que no las ignore. Además, en tu aplicación podrías olvidarte que una columna puede contener NULL y perderías tiempo buscando el problema, problema que nunca habrías tenido si la columna tuviera un valor por defecto.

Dependiendo de nuestro lenguaje de programación podemos hacer asignaciones NULL y también hacer comparaciones para saber si una columna es NULL o no lo es.

En el lenguaje Visual FoxPro escribiríamos:

lcNombre = NULL          && le asigna NULL a la variable lcNombre
IF ISNULL(lcNombre)      && si la variable lcNombre es NULL, entonces ...
IF !ISNULL(lcNombre)     && si la variable lcNombre no es NULL, entonces...

Tener columnas de tipo NULL es muy útil siempre y cuando sepas como usarlas. Si ese no es el caso, es mejor evitarlas y ponerles valores por defecto a todas las columnas, vivirás más tranquilo así.

Si tienes columnas NULL, en tu aplicación a cada momento podrías tener que verificar si una columna es NULL o no lo es. Y eso te hará perder tiempo y complicará tu código fuente.

Una forma de evitar ese problema es que en tu Base de Datos uses la función COALESCE(), como se muestra a continuación:

SELECT
   COALESCE(MiColumnaNumérica, 0) AS MiNumero
FROM
   MiTabla

La función COALESCE() devuelve el primer argumento que no sea NULL. O sea que en este ejemplo si MiColumnaNumérica no es NULL, ese es el valor que devolverá. Y si MiColumnaNumérica es NULL devolverá 0.

.

CAST()

4 comentarios

Descripción: Convierte una expresión de un tipo de datos a otro tipo de datos o dominio. Si la conversión no es posible envía un error.

Tipo de resultado: Elegido por el usuario

Sintaxis:

      CAST(Expresión AS <tipo_datos>)

      tipo_datos = Tipo_de_datos_SQL |
                   [TYPE OF] dominio |
                   TYPE OF COLUMN NombreTabla.NombreColumna

Sintaxis abreviada:

Hay una sintaxis alternativa que puede usarse solamente para convertir a DATE, TIME o TIMESTAMP

      Tipo_de_datos ‘date/timestring’

Ejemplos:

Usando la sintaxis completa:

   SELECT CAST('21' || '-April-' || '2013' AS DATE) FROM RDB$DATABASE

Usando la sintaxis abreviada:

UPDATE
   PRODUCTOS
SET
   FECHA_VENCIMIENTO = CURRENT_DATE + 45        -- la fecha de vencimiento será dentro de 45 días
WHERE
   FECHA_ULTIMA_COMPRA = DATE '21-JAN-2013'     -- para todos los productos que se compraron el 21 de enero de 2013

En algunos casos no es necesario siquiera usar la sintaxis abreviada porque el Firebird entenderá que debe convertir la cadena a fecha. El ejemplo anterior podría ser reescrito así:

UPDATE
   PRODUCTOS
SET
   FECHA_VENCIMIENTO = CURRENT_DATE + 45   -- la fecha de vencimiento será dentro de 45 días
WHERE
   FECHA_ULTIMA_COMPRA = '21-JAN-2013'     -- para todos los productos que se compraron el 21 de enero de 2013

en el cual eliminamos la palabra DATE.

Pero la forma abreviada no siempre es posible, el siguiente caso conducirá a un error porque el Firebird creerá que quieres restarle un entero a una cadena alfanumérica.

SELECT
   'TODAY' - 7
FROM
   RDB$DATABASE

La forma correcta de escribirlo es la siguiente, en la cual la palabra DATE le indica al Firebird que debe convertir la palabra ‘TODAY’ a la fecha de hoy:

SELECT
   DATE 'TODAY' - 7     -- DATE 'TODAY' devuelve la fecha de hoy. Este es un cast abreviado.
FROM
   RDB$DATABASE

Conversiones posibles:

La siguiente tabla muestra las conversiones que pueden realizarse con la función CAST()

-------------------------------------
|Desde              Hacia           |
-------------------------------------
|Tipos numéricos    Tipos numéricos |
|                   [VAR]CHAR       |
|                   BLOB            |
-------------------------------------
|[VAR]CHAR          [VAR]CHAR       |
|BLOB               BLOB            |
|                   Tipos numéricos |
|                   DATE            |
|                   TIME            |
|                   TIMESTAMP       |
-------------------------------------
|DATE               [VAR]CHAR       |
|TIME               BLOB            |
|                   TIMESTAMP       |
-------------------------------------

Recuerda que algunas veces la información puede perderse, por ejemplo cuando moldeas (o sea, haces el cast) de un TIMESTAMP a un DATE. En este caso se perderá la parte de la hora y te quedará solamente la parte de la fecha. Además, el hecho de que según la tabla de arriba pueda convertirse no es garantía de que tal conversión se realice con éxito. Por ejemplo: CAST(‘123456789’ AS SMALLINT) causará un error: “Arithmetic exception, numeric overflow, or string truncation.” ¿Por qué eso? porque el número más grande del tipo SMALLINT que puedes tener es 32767 y el número 123456789 es mayor que 32767.

También escribir algo como CAST(‘New Year’ AS DATE) causará un error.

Haciendo el cast a un dominio o su tipo:

Cuando se moldea (se hace el cast) a un dominio o a su tipo se deben satisfacer las restricciones (NOT NULL y/o CHECK) del dominio o el cast fallará. Un CHECK pasará si evalúa a TRUE o a NULL. Cuidado con esto último: un NULL pasará.

CREATE DOMAIN D_PRECIO_VENTA AS INTEGER CHECK (VALUE >= 1000)
SELECT CAST( 500 AS D_PRECIO_VENTA) FROM RDB$DATABASE     -- (1)
SELECT CAST(3000 AS D_PRECIO_VENTA) FROM RDB$DATABASE     -- (2)
SELECT CAST(NULL AS D_PRECIO_VENTA) FROM RDB$DATABASE     -- (3)

Solamente el primer cast (el número 1) resultará en un error, los otros dos casts pasarán. Cuando el modificador TYPE OF es usado la expresión es moldeada (cast) al tipo base del dominio, ignorando por lo tanto cualquier restricción que tenga ese dominio.

SELECT CAST(400 AS TYPE OF D_PRECIO_VENTA) FROM RDB$DATABASE
SELECT CAST(400 AS INTEGER)                FROM RDB$DATABASE

Los dos SELECT de arriba son equivalentes y ambos funcionarán bien. Recuerda que TYPE OF D_PRECIO_VENTA es lo mismo que escribir INTEGER ya que el tipo de D_PRECIO_VENTA es INTEGER.

Haciendo el cast a un tipo de columna:

También es posible hacer el cast al tipo de columna de una tabla o de una vista. En este caso, solamente el tipo de la columna es usado, ni las restricciones ni los valores por defecto se usan.

CREATE TABLE MiTabla (
    MiColumna INTEGER);

COMMIT;

SELECT CAST(12345 AS TYPE OF COLUMN MiTabla.MiColumna) FROM RDB$DATABASE;

.

BIT_LENGTH()

1 comentario

Descripción: Devuelve la longitud en bits de la cadena de entrada.

Tipo de resultado: Integer

Sintaxis:

      BIT_LENGTH(cadena_alfanumérica)

Nota: También soporta tipos BLOB

Ejemplo:

SELECT BIT_LENGTH('HOLA') FROM RDB$DATABASE

Devolverá 32 porque cada carácter está compuesto por 8 bits y la palabra HOLA tiene 4 caracteres. Y 8 x 4 = 32. En realidad esta función no es necesaria con los idiomas occidentales (castellano, inglés, francés, italiano, portugués, etc.) porque siempre cada carácter está compuesto por 8 bits, pero en otros idiomas esa cantidad varía y allí sí puede ser importante usar la función BIT_LENGTH().

.

.

BIN_XOR()

1 comentario

Descripción: Devuelve el resultado de una operación XOR bit a bit sobre sus argumentos

Tipo de resultado: Integer o BigInt

Sintaxis:

BIN_XOR(número [, número …])

IMPORTANTE: Si la función externa BIN_XOR() está declarada en tu Base de Datos, ella tendrá preferencia. Para que la función interna pueda usarse deberás borrar (DROP) o cambiar (ALTER) a la función externa.

.

Older Entries