Listando las funciones externas

Deja un comentario

Como recordarás, Firebird nos permite usar funciones externas en nuestras bases de datos. Una función externa no está incluida en la instalación del Firebird sino que la agregamos después y a cada Base de Datos que la necesite utilizar. Eso significa que cada una de nuestras bases de datos puede tener cero, una, o varias funciones externas.

Si queremos saber cuales son las funciones externas que hemos registrado en una Base de Datos, podemos usar nuestro administrador gráfico para ello:

externa01

Captura 1. Si haces clic en la imagen la verás más grande

o podemos escribir un SELECT que nos de esa información:

Listado 1.

SELECT
   *
FROM
   RDB$FUNCTIONS
WHERE
   RDB$SYSTEM_FLAG = 0

Donde obtendremos un resultado similar al siguiente:

externa02

Captura 2. Si haces clic en la imagen la verás más grande

  • RDB$FUNCTION_NAME. Es el nombre con el cual se conoce a esta función dentro de nuestra Base de Datos
  • RDB$FUNCTION_TYPE. Tipo de la función, no está siendo usado y por eso siempre es Null
  • RDB$QUERY_NAME. Nombre de la consulta, no está siendo usada y por eso siempre es Null
  • RDB$DESCRIPTION. Comentarios que podemos escribir para describir lo que hace la función
  • RDB$MODULE_NAME. El nombre que tiene el archivo .DLL o el objeto compartido, en el disco duro u otro dispositivo de almacenamiento
  • RDB$ENTRYPOINT. El nombre que tiene la función externa en el archivo .DLL o en el objeto compartido. No siempre es igual a RDB$FUNCTION_NAME
  • RDB$RETURN_ARGUMENT. El número de posición del argumento que se devuelve, en la lista de argumentos de entrada
  • RDB$SYSTEM_FLAG. Una bandera que indica si la función fue definida internamente o externamente. 0=definida externamente, 1=definida internamente

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

 

 

 

 

Anuncios

Como saber si una tabla existe en una Base de Datos

6 comentarios

A veces puedes encontrarte con la necesidad de saber desde tu aplicación si una Base de Datos corresponde a lo que necesitas.

Por ejemplo, debes importar datos que se encuentran en la Base de Datos de nombre BaseAjena.FDB a tu propia Base de Datos.

Si tú harás esa tarea te resultará fácil comprobarlo, simplemente te conectas a BaseAjena.FDB y miras los nombres de sus tablas usando el programa ISQL.EXE o algún programa de administración gráfica. Ningún problema con eso.

Rápidamente sabrás si esa Base de Datos es correcta o no lo es.

Pero ¿y si no serás tú quien debe realizar el proceso de importación sino un usuario de tu aplicación?

Allí el asunto se complica, porque deberás asegurarte que la Base de Datos externa sea correcta.

Por ejemplo, en la computadora del usuario hay varias bases de datos de Firebird, con distintas finalidades y quizás creadas por distintas personas: Contabilidad, Facturación, Sueldos, etc.

Tú necesitas conectarte a una Base de Datos de Contabilidad, pero no conoces el nombre de esa Base de Datos. Así que le das al usuario la opción de seleccionar la Base de Datos. Pero ¿es una Base de Datos de Contabilidad o no lo es?

Una forma de comprobarlo es verificando los nombres de las tablas de la Base de Datos externa.

Por ejemplo, si la única Base de Datos que tiene una tabla cuyo nombre es ASIENTOSCAB es la Base de Datos contable entonces puedes tener la certeza de que se trata de la Base de Datos adecuada.

Listado 1.

SELECT
   RDB$RELATION_NAME AS NombreTabla
FROM
   RDB$RELATIONS
WHERE
   RDB$RELATION_NAME = 'ASIENTOSCAB'

Si al ejecutar el Listado 1. obtienes que NombreTabla es igual a ASIENTOSCAB entonces ya sabes que la Base de Datos es la correcta. Desde luego que en algunos casos podrías necesitar verificar el nombre de varias tablas para asegurarte bien.

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

 

 

Todas las columnas que se usan como Primary Key

4 comentarios

Cuando tenemos muchas tablas, verificar si cada tabla tiene la Primary Key correcta puede ser muy tedioso si debemos estar mirando una por una. La siguiente consulta nos facilitará esa tarea:

Listado 1.

SELECT
   I.RDB$FIELD_NAME      AS NOMBRE_COLUMNA,
   R.RDB$RELATION_NAME   AS NOMBRE_TABLA,
   R.RDB$CONSTRAINT_TYPE AS TIPO_RESTRICCION,
   I.RDB$INDEX_NAME      AS NOMBRE_RESTRICCION
FROM
   RDB$RELATION_CONSTRAINTS R
JOIN
   RDB$INDEX_SEGMENTS       I
      ON R.RDB$CONSTRAINT_NAME = I.RDB$INDEX_NAME
WHERE
   R.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'

PRIMARYS01

Captura 1. Si haces clic en la imagen la verás más grande

En la Captura 1. podemos ver los nombres de cada tabla, los nombres de las columnas que están incluidas en la Primary Key, y los nombres de las Primary Key.

De esta manera nos resultará fácil saber si todas las tablas tienen las Primary Key que deberían tener, o si a alguna de ellas le está sobrando o faltando alguna columna.

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

 

Para conocer la versión del Firebird que estás usando

2 comentarios

¿Cuál es la versión del Firebird que estás usando?

A veces puede ser interesante poder responder a esa pregunta, inclusive dentro de un programa. Pues bien, la respuesta te la dará el siguiente SELECT:

Listado 1.

SELECT 
   RDB$GET_CONTEXT('SYSTEM', 'ENGINE_VERSION') 
FROM 
   RDB$DATABASE;

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

Potenciando a DESCRIPTION

4 comentarios

En cada columna de cada tabla de Firebird disponemos de la posibilidad de describir a dichas columnas.

DESCRIPTION1

Captura 1. Si haces clic en la imagen la verás más grande

Lo cual está muy bien y es muy útil, porque nos permite a los desarrolladores tener un “ayuda memoria” y nos facilita entender para que sirve cada columna.

Y si necesitamos un SELECT que nos devuelva esas descripciones podríamos escribir algo como:

SELECT
   RDB$FIELD_NAME,
   RDB$DESCRIPTION
FROM
   RDB$RELATION_FIELDS
WHERE
   RDB$RELATION_NAME = 'BANCOS'

Que nos dará un conjunto resultado similar a esto:

DESCRIPTION2

Captura 2. Si haces clic en la imagen la verás más grande

Hasta aquí, todo está muy bien pero … estamos usando a RDB$DESCRIPTION solamente para guardar descripciones simples de columnas. Sin embargo, si nos interesa, podríamos usarla para guardar muchos datos relevantes.

¿Y por qué haríamos algo así?

Porque nos ahorraríamos de guardar esos datos relevantes en otra u otras tablas. Por ejemplo, queremos que el título de cada columna de cada grilla sea siempre el mismo. Si no lo estandarizamos podríamos encontrarnos con algo como esto:

DESCRIPTION3

Captura 3. Si haces clic en la imagen la verás más grande

DESCRIPTION4

Captura 4. Si haces clic en la imagen la verás más grande

Las dos grillas sirven para mostrar los datos de los Bancos, pero los títulos de las columnas son distintos. Y eso implica que nuestras pantallas están mal diseñadas porque un buen diseño siempre muestra pantallas consistentes.

No es tan difícil cuando una sola persona es la encargada de los diseños pero ¿y si es un trabajo en equipo y hay varios desarrolladores trabajando en el proyecto? Lo más probable es que cada uno haga como mejor le parezca.

Claro, podemos escribir un documento especificando todos y cada uno de los puntos que nos interesa estandarizar pero:

  • Seguro que no todos lo leerán
  • Y aún quienes lo lean podrían olvidarse de lo leído
  • O simplemente no estar de acuerdo y hacer lo que se les antoja

Una posibilidad para tener diseños consistentes es asegurarnos de que todas las características del “display” se guarden en tablas. Y para eso nos resultará muy útil la columna DESCRIPTION.

Entonces, podríamos tener algo así:

 DESCRIPTION5

 Captura 5. Si haces clic en la imagen la verás más grande

  • El texto que está entre corchetes es el que se usará en el título de cada columna de cada grilla
  • El texto que está entre llaves es el mensaje de ayuda al usuario, para que sepa para que sirve esa columna
  • El texto que no está rodeado ni por corchetes ni por llaves es para los desarrolladores

Como puedes ver, ahora la descripción es mucho más útil porque sirve para varios objetivos.

¿Y si necesitamos más datos?

Una posibilidad es la siguiente:

DESCRIPTION6

Captura 6. Si haces clic en la imagen la verás más grande

Si te fijas en la primera fila podrás ver que allí hay varios datos, separados por punto y coma:

Suc. —> es el título de la columna

FN —> font name, es el tipo de letra que se desea usar por defecto

FS —> font size, es el tamaño del tipo de letra que se desea usar por defecto

Otra posibilidad es escribir la descripción similar a esto:

DESCRIPTION7

Captura 7. Si haces clic en la imagen la verás más grande

El texto que está en la primera línea es para los desarrolladores.

Header —> es el título que deseamos mostrar en la grilla

FN —> font name, es el tipo de letra por defecto que usaremos en la grilla

FS —> font size, es el tamaño del tipo de letra por defecto que usaremos en la grilla

Help —> es el mensaje de ayuda que se le mostrará al usuario, en los lugares donde queremos mostrar mensajes de ayuda

Conclusión:

La descripción de las columnas podemos usarla para describirle la columna al desarrollador. Y por lo tanto solamente le resultará útil a él. Pero si lo deseamos también podríamos potenciar la descripción para que contenga muchos datos útiles. ¿Cuál es la ventaja de hacerlo así? que nos ahorramos crear una tabla para guardar esos datos. Y además que es más fácil saber si nos están faltando descripciones.

Desde luego que los datos mostrados en este artículo son solamente ejemplos, tú podrías guardar muchísimos más. Lo importante a recordar es que podemos usar a DESCRIPTION para guardar no solamente comentarios para el desarrollador.

Artículo relacionado:

El índice del blog Firebird21

Conociendo las sentencias en ejecución

4 comentarios

¿Qué están haciendo los usuarios en este momento?

A veces puede interesarnos conocer las sentencias que están ejecutando los usuarios en este momento o las sentencias que ejecutaron con anterioridad.

Esa información la podemos recuperar de la tabla MON$STATEMENTS, como se muestra a continuación:

SELECT
   *
FROM
   MON$STATEMENTS

Ese SELECT nos mostrará algo similar a esto:

STATEMENT1

Captura 1. Si haces clic en la imagen la verás más grande

La columna MON$STATE puede tener 3 valores posibles:

0 significa que no se está usando en este momento

1 significa que está activo en este momento

2 significa que está detenido, va a continuar enviando datos al Cliente pero ahora no lo está haciendo

La columna MON$TIMESTAMP muestra el momento en que empezó la ejecución del comando

La columna MON$SQL_TEXT muestra el comando que ejecutó el usuario

Comandos actualmente en ejecución

Para conocer los comandos que actualmente están siendo ejecutados debes poner la condición de que MON$STATE sea 1.

SELECT
   *
FROM
   MON$STATEMENTS
WHERE
   MON$STATE = 1

Y para conocer los comandos que actualmente están siendo ejecutados pero sin incluir la conexión actual (es decir, que tus propios comandos no se muestren)  podrías escribir algo como:

SELECT
   A.MON$USER,
   A.MON$REMOTE_ADDRESS,
   S.MON$SQL_TEXT,
   S.MON$TIMESTAMP
FROM
   MON$ATTACHMENTS A
JOIN
   MON$STATEMENTS S
      ON A.MON$ATTACHMENT_ID = S.MON$ATTACHMENT_ID
WHERE
   A.MON$ATTACHMENT_ID <> CURRENT_CONNECTION AND
   S.MON$STATE = 1

Conclusión:

 Firebird nos permite conocer los comandos que están siendo ejecutados en este preciso momento. Eso puede resultarnos muy útil si descubrimos que algo está mal pero no sabemos exactamente qué es lo que está mal. Observando lo que hacen los usuarios puede darnos unas pistas muy valiosas para encontrar el problema.

Artículo relacionado:

El índice del blog Firebird21

Una vista para verificar la transacción actual

Deja un comentario

A veces queremos saber cuales son las características de la transacción actual ¿es “read only”? ¿tiene acceso exclusivo a las tablas? si hay un conflicto al actualizar o borrar datos ¿espera o inmediatamente sale con error?, etc.

La siguiente vista nos dará esa información:

SELECT
   MON$TRANSACTION_ID             AS tnIdentificadorTransaccion,
   MON$ATTACHMENT_ID              AS tnIdentificadorConexion,
   IIF(MON$STATE = 1, 'ACTIVA', 'INACTIVA') AS tcEstadoTransaccion,
   MON$TIMESTAMP                  AS tdFechaHora,
   MON$TOP_TRANSACTION            AS tnUltimaTransaccion,
   MON$OLDEST_TRANSACTION         AS tnOldestInterestingTransaction,
   MON$OLDEST_ACTIVE              AS tnOldestActiveTransaction,
   DECODE(MON$ISOLATION_MODE, 0, 'Acceso exclusivo', 1, 'Lecturas repetidas', 2, 'Lee filas confirmadas inmediatamente', 3, 'No lee una fila si otra transacción la usa') AS tcModoAislamiento,
   DECODE(MON$LOCK_TIMEOUT, -1, 'Espera por siempre', 0, 'No espera', 'Espera ' || MON$LOCK_TIMEOUT || ' segundos') AS tcTiempoEspera,
   IIF(MON$READ_ONLY = 1, 'Read Only', 'Read Write')               AS tcReadOnly,
   IIF(MON$AUTO_COMMIT = 1, 'Auto COMMIT', 'No auto COMMIT')       AS tcAutoCommit,
   IIF(MON$AUTO_UNDO = 1, 'Tiene savepoint', 'No tiene savepoint') AS tcAutoUndo,
   MON$STAT_ID                                                     AS tnIdentificadorEstadisticas
FROM
   MON$TRANSACTIONS
WHERE
   MON$ATTACHMENT_ID  = CURRENT_CONNECTION AND
   MON$TRANSACTION_ID = CURRENT_TRANSACTION;

Si la transacción es SNAPSHOT TABLE STABILITY entonces tiene acceso exclusivo a todas las tablas (algo no recomendable en Firebird)

Si la transacción es SNAPSHOT entonces las lecturas pueden repetirse muchas veces y siempre se obtendrán los mismos resultados. Suele ser la más aconsejable para las consultas (SELECT, FETCH)

Si la transacción es READ COMMITED RECORD_VERSION entonces la última versión confirmada del registro es leída inmediatamente. Es la opción por defecto. Suele ser la más aconsejable para mantenimiento de los datos (INSERT, UPDATE, DELETE)

Si la transacción es READ COMMITED NO RECORD_VERSION y otra transacción tiene una versión no confirmada del registro, la transacción actual espera hasta que la otra transacción termine con un COMMIT o con un ROLLBACK (si el modo de bloqueo es WAIT) o termina inmediatamente con error (si el modo de bloqueo es NO WAIT). Estas transacciones pueden causar muchos “deadlock”, por lo tanto hay que pensar muy bien si es el aislamiento correcto.

Es aconsejable que la consulta anterior se guarde como una vista entonces cuando quieras saber las características de la transacción actual simplemente escribes:

SELECT * FROM V_TRANSACCION_ACTUAL

y listo, ya podrás saberlas.

Artículos relacionados:

Entendiendo las transacciones

Modos de bloqueo de las transacciones

El índice del blog Firebird21

Older Entries