Ejemplo Nº 037 – Respondiendo preguntas

1 comentario

Muchas veces necesitarás responder preguntas basadas en ¿quién, cuándo, dónde, qué, cómo?, etc.

Con lo aprendido hasta aquí ya podrás responder a muchas de ellas, por ejemplo:

¿Cuál es el producto que tiene el mayor precio de venta?

SELECT
   PRD_CODIGO,
   PRD_NOMBRE,
   PRD_PREVTA
FROM
   PRODUCTOS
ORDER BY
   PRD_PREVTA DESC
ROWS
   1

Fíjate que se usó la cláusula ROWS para obtener solamente una fila, si no se la hubiera escrito se habrían obtenido los datos de todos los productos, no solamente del producto con mayor precio de venta.

Si deseas obtener los datos de los 3 productos con mayor precio de venta entonces podrías escribir:

ROWS
1 TO 3

Y para obtener los datos de los 5 productos con mayor precio de venta:

ROWS
1 TO 5

Supongamos que ahora te interesa obtener los datos del segundo producto con mayor precio de venta, entonces:

SELECT
   PRD_CODIGO,
   PRD_NOMBRE,
   PRD_PREVTA
FROM
   PRODUCTOS
ORDER BY
   PRD_PREVTA DESC
ROWS
   2 TO 2

Esta consulta te dará la respuesta.

¿Y si quieres los 10 productos con mayor precio de venta?

ROWS

1 TO 10

 

.

Ejemplo Nº 036 – Combinando las cláusulas WHERE y ORDER BY

4 comentarios

Una consulta SQL no está limitada a usar solamente la cláusula WHERE o solamente la cláusula ORDER BY, puedes usar ambas cláusulas en la misma consulta si así lo deseas.

SELECT
   PRD_CODIGO,
   PRD_NOMBRE,
   PRD_PREVTA
FROM
   PRODUCTOS
WHERE
   PRD_NOMBRE LIKE 'C%'
ORDER BY
   PRD_NOMBRE

Esta consulta mostrará todos los productos cuyos nombres empiezan con la letra “C”, ordenados alfabéticamente.

Otro ejemplo:

SELECT
   PRD_CODIGO,
   PRD_NOMBRE,
   PRD_PREVTA
FROM
   PRODUCTOS
WHERE
   PRD_NOMBRE LIKE 'C%'
ORDER BY
   PRD_PREVTA DESC

Esta consulta mostrará todos los productos cuyos nombres empiezan con la letra “C”, ordenados descendentemente por precios de venta.

 

.

 

Ejemplo Nº 035 – Ordenando por varias columnas, mezclando ascendentes y descendentes

1 comentario

También es posible que algunas columnas estén ordenadas ascendentemente y otras columnas estén ordenadas descendentemente.

SELECT
   PRD_CODIGO,
   PRD_NOMBRE,
   PRD_PROCED,
   PRD_PREVTA
FROM
   PRODUCTOS
ORDER BY
   PRD_PROCED ASC,
   PRD_NOMBRE DESC

Aquí, el país de procedencia está ordenado en forma ascendente (A, B, C, etc.) mientras que el nombre del producto está ordenado en forma descendente (Z, Y, X, W, etc.)

 

.

 

Ejemplo Nº 034 – Ordenando por varias columnas

1 comentario

A veces queremos ordenar por varias columnas, hacemos eso separando a las columnas con comas:

SELECT
   PRD_CODIGO,
   PRD_NOMBRE,
   PRD_PROCED,
   PRD_PREVTA
FROM
   PRODUCTOS
ORDER BY
   PRD_PROCED,
   PRD_NOMBRE

En este ejemplo se ordenan primero por país de procedencia y luego por nombre del producto.

Si se desea, se pueden usar las posiciones de las columnas en el SELECT en lugar de sus nombres.

ORDER BY
   3, 2

.

Ejemplo Nº 033 – Mostrar los datos ordenados en forma descendente

1 comentario

Si no le decimos al Firebird como queremos que los datos se ordenen, él los ordenará de forma ascendente (o sea: 1, 2, 3, 4, …., A, B, C, D, etc.). Pero a veces necesitamos que estén ordenados en forma descendente.

SELECT
   PRD_CODIGO,
   PRD_NOMBRE,
   PRD_PROCED,
   PRD_PREVTA
FROM
   PRODUCTOS
ORDER BY
   PRD_PREVTA DESC

Este SELECT nos mostrará a los productos ordenados por sus precios de venta, de mayor precio a menor precio (o sea: en forma descendente).

Al igual que cuando se ordena en forma ascendente, cuando se ordena en forma descendente se puede usar el número de la columna, si así se desea.

SELECT
   PRD_CODIGO,
   PRD_NOMBRE,
   PRD_PROCED,
   PRD_PREVTA
FROM
   PRODUCTOS
ORDER BY
   4 DESC

Se escribe menos usando los números de las columnas en lugar de sus nombres, pero es más difícil de entender al principio.

Se puede ordenar por cualquier columna, sea ésta de tipo carácter, de tipo numérico, de tipo fecha, etc. La única excepción son las columnas de tipo BLOB, no se puede ordenar por ellas.

 

.

Como saber si te puedes conectar a una Base de Datos

1 comentario

Lo correcto es que antes de enviarle un comando a una Base de Datos verifiques que estás conectado a ella (podrías haberte desconectado por varias razones). Esta función te dará esa información:

FUNCTION HayConexion
Local lnResultado
   TRY
      lnResultado = SQLExec(gnHandle, "SELECT CURRENT_TIME FROM RDB$DATABASE")
   CATCH
      lnResultado = -1
   ENDTRY
   if Used("SQLRESULT")
      SELECT SQLRESULT
      USE
   endif
   Return(lnResultado == 1)
ENDFUNC
 *
 *

Esta función te devolverá .T. si estás conectado a la Base de Datos o .F. si no lo estás.

.

Como saber cuales tablas tiene una Base de Datos

1 comentario

Si quieres saber los nombres de todas las tablas que tiene una Base de Datos el siguiente SELECT te dará esa información:

FUNCTION ObtenerTablas
LParameters tcCursor
Local lcConsulta, lnResultado

   lcConsulta = "SELECT " ;
              + "   RDB$RELATION_NAME " ;
              + "FROM " ;
              + "   RDB$RELATIONS " ;
              + "WHERE " ;
              + "   RDB$VIEW_SOURCE IS NULL"

   lnResultado = SQLExec(gnHandle, lcConsulta, tcCursor)

   Return(lnResultado)

 ENDFUNC
 *
 *

Registrar los errores en un archivo de texto

1 comentario

Cuando le envías un comando al Firebird a veces la ejecución falla, los motivos pueden ser diversos, entre ellos:

  • Escribiste mal una palabra clave (por ejemplo: escribiste SELECR en lugar de SELECT)
  • Escribiste el nombre de una columna inexistente
  • Escribiste el nombre de una tabla o vista inexistente
  • Enviaste como parámetro un texto y debías enviar como parámetro un número
  • La cantidad de parámetros que enviaste es diferente a la cantidad de parámetros que el stored procedure debe recibir
  • Enviaste más caracteres que los admitidos (enviaste 30 pero solamente puede recibir 20)
  • y un largo etcétera

Si hubo un error, cualquier error, el valor que te devolverá la función SQLEXEC() será -1 pero eso evidentemente no te da suficiente información para saber que fue lo que estuvo mal. Para obtener esa información lo que puedes hacer es lo siguiente:

  1. Capturas el error
  2. Lo grabas en un archivo de texto
  3. Revisas el archivo de texto
FUNCTION RegistrarErrorEnArchivo
Local lnNumElementos, lcNombreArchivLog, lnI, lcElemento, lcVarType, lnPos1, lnPos2, lnPos3, lcExcepcionNombre, lcExcepcionMensaje
   lnNumElementos = AERROR(laErrorArray)
   if lnNumElementos >= 1
      lcNombreArchivoLog = "SQL_ERRORES.TXT"
      =StrToFile(DtoC(Date()) + " " + Left(TIME(), 5) + Chr(13), lcNombreArchivoLog, 1)
      For lnI = 1 to 2
         lcElemento = laErrorArray[lnI]
         lcVarType = VarType(lcElemento)
         lcElemento = icase(lcVarType == "N", Str(lcElemento), lcVarType == "X", "", lcElemento) + " "
         if lnI == 2
            lnPos1 = AT(Chr(10), lcElemento, 1)
            lnPos2 = AT(Chr(10), lcElemento, 2)
            lnPos3 = AT(Chr(10), lcElemento, 3)
            if SubStr(lcElemento, lnPos1 + 1, 2) == "E_"     && Si se trata de una excepción
               lcExcepcionNombre = SubStr(lcElemento, lnPos1 + 1, lnPos2 - lnPos1)
               lcExcepcionMensaje = SubStr(lcElemento, lnPos2 + 1, lnPos3 - lnPos2)
            else
               lcExcepcionNombre = ""
               lcExcepcionMensaje = ""
            endif
         endif
         =StrToFile(lcElemento, lcNombreArchivoLog, 1)
      Next lnI
      =StrToFile(Chr(13) + Replicate("-", 80) + Chr(13), lcNombreArchivoLog, 1)
   endif

 ENDFUNC
 *
 *

Esta función grabará en un archivo de texto llamado SQL_ERRORES.TXT todos los errores que detecte el Firebird. Por cada error se grabarán tres líneas:

  • La primera línea te dirá la fecha y la hora en la cual ocurrió el error
  • La segunda línea te dirá cual fue el error que ocurrió
  • La tercera línea son 80 guiones y sirve para separar un error del siguiente

Fíjate que para que detecte si el error se debió a una excepción del usuario (o sea: una excepción tuya, que tú escribiste) el nombre de tu excepción debe empezar con E_

Desde luego que los nombres de tus excepciones pueden empezar con cualquier letra que quieras, pero lo recomendable es que estandarices esos nombres y empezarlos con E_ es una buena práctica.

Debes invocar a esta función si SQLEXEC() te devuelve -1

lnResultado = SQLEXEC(gnHandle, lcComando)

IF lnResultdo = -1     && Si ocurrió algún error
   =RegistrarErrorEnArchivo()
ENDIF

Cada vez que tengas algún problema revisa el archivo SQL_ERRORES.TXT y así sabrás que fue lo que estuvo mal.

 

.