Ejemplo de recursión (6). Repitiendo las filas

3 comentarios

Un usuario del foro hizo esta pregunta: “Tengo una tabla llamada ETIQUETAS con dos columnas: NOMBRES Y NUMERO_REPETICIONES y deseo que cada nombre se repita esa cantidad de veces”.

La idea es imprimir etiquetas con esos nombres.

Solución:

Primero, creamos la tabla ETIQUETAS

ETIQUETAS1

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

Segundo, le insertamos algunas filas a la tabla de ETIQUETAS

ETIQUETAS2

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

Tercero, usando recursión obtenemos cada nombre, repetido la cantidad de veces indicada.

Listado 1.

WITH RECURSIVE MISETIQUETAS AS (
 
   SELECT
      ETI_NOMBRE,
      ETI_REPITE
   FROM
      ETIQUETAS
   WHERE
      ETI_REPITE > 0
 
   UNION ALL
 
   SELECT
      ETI_NOMBRE,
      ETI_REPITE - 1
   FROM
      MISETIQUETAS
   WHERE
      ETI_REPITE - 1 > 0
 
)

SELECT
   ETI_NOMBRE
FROM
   MISETIQUETAS

ETIQUETAS3

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

Y como podemos ver, cada nombre se ha repetido la cantidad de veces que habíamos escrito en la columna ETI_REPITE.

Explicación:

Primero, obtenemos todas las filas de la tabla ETIQUETAS cuya cantidad de etiquetas a imprimir es mayor que cero. Eso hace el primer SELECT, o sea nuestro “ancla” como habíamos visto en artículos anteriores.

Segundo, repetimos cada una de esas filas ETI_REPITE – 1 veces. ¿Por qué – 1? Porque la primera fila ya fue insertada por el “ancla” así que debemos insertar solamente las demás filas.

Tercero, mostramos cada nombre repetido la cantidad de veces que habíamos especificado en su columna ETI_REPITE. De eso se encarga el último SELECT.

Artículos relacionados:

Stored procedures recursivos

Entendiendo a las tablas autoreferenciadas

Usando CTE (Common Table Expression)

Otro ejemplo de CTE: ventas semanales

Usando varias CTE en una vista o en un stored procedure

FOR SELECT y tablas CTE

Usando recursividad con CTE

Ejemplo de recursión (1). Filas salteadas

Ejemplo de recursión (2). Numerar filas

Ejemplo de recursión (3). Fechas consecutivas

Ejemplo de recursión (4). Actualizando filas recursivamente

Ejemplo de recursión (5). Saldos acumulados

El índice del blog Firebird21

El foro del blog Firebird21

Anuncios

Nombres de tablas con guión bajo

Deja un comentario

Si quieres que el nombre de una tabla empiece con un guión bajo tendrás problemas porque el Firebird no admite al guión bajo como primer carácter del nombre de una tabla.

Sin embargo … hay una solución.

Y la solución es rodear al nombre de la tabla con comillas, así:

CREATE TABLE
   "_CON_GUION"
   (GUI_IDENTI INTEGER,
    GUI_NOMBRE VARCHAR(40));

Desde luego que para acceder a esa tabla siempre tendrás que usar las comillas, por ejemplo:

INSERT INTO "_CON_GUION"
           (GUI_IDENTI, GUI_NOMBRE)
    VALUES (1         , 'SILVIA BEATRIZ');

SELECT
   *
FROM
   "_CON_GUION"

Conclusión:

A veces podría ser útil que los nombres de algunas tablas empiecen con un guión bajo, el Firebird no nos permite eso, salvo que el nombre de la tabla esté rodeado por comillas.

Artículo relacionado:

El índice del blog Firebird21

 

Obteniendo los nombres de todos los usuarios

2 comentarios

Alguna vez podrías necesitar conocer los nombres de todos los usuarios que tiene admitidos el Firebird, estos son los usuarios que pueden conectarse a cualquier Base de Datos, siempre y cuando se les otorguen los derechos correspondientes, por supuesto.

No conozco algún SELECT que nos provea esa información. Los nombres de los usuarios se encuentran en el archivo SECURITY2.FDB y el acceso a ese archivo está restringido por razones obvias. Entonces, ¿cómo hacemos para obtener los nombres de todos los usuarios?

Aquí se muestra una solución.

Si creamos un archivo batch similar al siguiente tendremos en el archivo USUARIOS.TXT los nombres de todos los usuarios de bases de datos de Firebird.

USUARIOS

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

Como puedes ver, el archivo batch se llama USUARIOS.BAT y lo que hace es ejecutar al programa GSEC pidiéndole que muestre los nombres de los usuarios (la opción -display hace eso). No cualquier usuario puede listar los nombres de los demás usuarios, solamente SYSDBA puede hacerlo. La salida se redirige a un archivo llamado USUARIOS.TXT, o sea que en lugar de mostrar los nombres de los usuarios en la pantalla guarda esos nombres en el archivo USUARIOS.TXT

¿Por qué redirigimos la salida del programa GSEC al archivo USUARIOS.TXT?

Para más tarde poder procesar el archivo USUARIOS.TXT y extraer de él los nombres de los usuarios, pues eso es lo que estamos intentando conseguir. Queremos tener los nombres de los usuarios para mostrarlos en un ComboBox o en un Grid, etc.

El siguiente código en Visual FoxPro nos muestra como podemos obtener los nombres de todos los usuarios:

Local lcComando, llComandoOK, loShell, lnRetorno, lcUsuarios, lnMemoWidth, lnTotalLineas, lnI, lcLinea

   *--- Nombre del archivo donde se guardarán los nombres de los usuarios
   lcArchivo = "USUARIOS.TXT"

   *--- Contenido que tendrá el archivo batch USUARIOS.BAT
   lcComando = ["C:\ARCHIVOS DE PROGRAMA\FIREBIRD\FIREBIRD_2_5\BIN\GSEC" -user SYSDBA -password masterkey -display > ] + lcArchivo

   *--- Se crea el archivo batch USUARIOS.BAT
   =StrToFile(lcComando, "USUARIOS.BAT")

   *--- Se supone que el archivo batch se ejecutará exitosamente
   llComandoOK = .T.

   *--- Se crea un objeto shell para ejecutar el archivo batch
   loShell = CreateObject("WScript.Shell")

   *--- Se intenta ejecutar el archivo batch, la bandera llComandoOK nos dirá si se ejecutó exitosamente o no
   TRY
      lnRetorno = loShell.Run("USUARIOS.BAT", 0, .T.)
   CATCH
      llComandoOK = .F.
   ENDTRY

   if llComandoOK     && Si la ejecución del archivo batch tuvo éxito
      *--- En la variable lcUsuarios se guarda el contenido del archivo que tiene los nombres de los usuarios
      lcUsuarios = FileToStr(lcArchivo)
      *--- Se obtiene la cantidad de caracteres que se usan en los campos memo
      lnMemoWidth = Set("MEMOWIDTH")
      *--- Se cambia la cantidad de caracteres a 96
      SET MEMOWIDTH TO 96
      *--- Se obtiene la cantidad de líneas que tiene el archivo donde están los nombres de los usuarios
      lnTotalLineas = MemLines(lcUsuarios)
      *--- Se guarda en la variable lcLinea el nombre de cada usuario
      For lnI = 3 to lnTotalLineas
         lcLinea = AllTrim(Left(MLine(lcUsuarios, lnI), 28))
         if !Empty(lcLinea)
            =MessageBox(lcLinea)     && Se muestra en la pantalla el nombre del usuario
         endif
      EndFor
      *--- Se pone la cantidad de caracteres original en los campos memo
      SET MEMOWIDTH to lnMemoWidth
   else     && Si ocurrió algún problema al ejecutar el archivo batch
      =MessageBox("No pude obtener los nombres de los usuarios")
   endif

   *--- Se borra el archivo USUARIOS.BAT porque ya no es necesario
   DELETE FILE USUARIOS.BAT

   *--- Se libera el objeto loShell

   loShell = NULL

   Release loShell

Return
*
*

Dentro del código fuente hay muchos comentarios, los cuales te ayudarán a entender que es lo que hace. Si tienes bastante experiencia con Visual FoxPro te resultará muy fácil entenderlo, aún sin los comentarios.

Conclusión:

Aunque no existe (que yo sepa, claro) un SELECT que nos devuelva los nombres de los usuarios escribir un programita que nos de esa información es muy fácil como se puede ver en este artículo.

Artículos relacionados:

Agregando, modificando y borrando usuarios

El índice del blog Firebird21