El comando INSERT

Deja un comentario

El comando INSERT (insertar) se utiliza para agregarle nuevas filas a una tabla. Tiene dos sintaxis:

Sintaxis 1:

INSERT INTO tabla | vista (<lista de columnas>)
VALUES (<lista de valores>)
[RETURNING <lista de columnas a retornar>
[INTO <lista con el nombre de las variables>]]

Se utiliza cuando se quiere agregar una fila a la tabla o vista.

Ejemplo:

INSERT INTO ALUMNOS
        (ALU_CODIGO, ALU_NOMBRE, ALU_APELLD)
VALUES  ('1253', 'MIRTHA', 'ROMERO');

Sintaxis 2:

INSERT INTO tabla | vista (<lista de columnas>)
SELECT <lista de valores> FROM ...
[RETURNING <lista de columnas a retornar>
[INTO <lista con el nombre de las variables>]]

 Ejemplo:

INSERT INTO GERENTES
         (GER_CODIGO, GER_NOMBRE)
   SELECT E.EMP_CODIGO, E.EMP_NOMBRE FROM EMPLEADOS E WHERE E.EMP_CARGOX = 'GERENTE'

Esta segunda sintaxis se utiliza cuando se quieren agregar muchas filas de una sola vez.

Si los valores que queremos agregarle a una tabla se encuentran en otra u otras tablas, esta segunda sintaxis es la adecuada porque es muy rápida.

Artículo relacionado:

El índice del blog Firebird21

Anuncios

El generador autoincremental

15 comentarios

En Firebird podemos tener unas variables públicas e internas llamadas generadores o secuencias. Son la misma cosa, lo que en Firebird siempre se llamó generador en el estandar SQL se denomina secuencia.

Que una variable sea pública significa que puede usarse en cualquier lugar dentro de la Base de Datos, o sea en cualquier SELECT, stored procedure o trigger. Que sea interna, significa que fuera de la Base de Datos no es conocida, no existe.

Aunque nosotros podemos cambiar el valor de un generador lo normal y lo correcto es que sea el propio Firebird quien lo cambie.

¿Para qué usar un generador?

Una de sus principales aplicaciones es para tener identificadores para nuestra Primary Key que podemos tener la seguridad 100% de que jamás se repetirán. Recordarás que las Primary Key no pueden tener valores duplicados, entonces como los generadores tampoco pueden tener valores duplicados (si se usan correctamente), son perfectos para ser usados en las Primary Key.

Ejemplo del uso de un generador:

SET TERM ^ ;

CREATE TRIGGER BI_PRODUCTOS_PRD_IDENTI FOR PRODUCTOS
       ACTIVE BEFORE INSERT
       POSITION 0
AS
BEGIN
   IF (NEW.PRD_IDENTI IS NULL OR NEW.PRD_IDENTI = 0) THEN
      NEW.PRD_IDENTI = GEN_ID(PRODUCTOS_PRD_IDENTI_GEN, 1);
END^

SET TERM ; ^

En este trigger tenemos un generador cuyo nombre es PRODUCTOS_PRD_IDENTI_GEN. La función GEN_ID() recibe a ese generador como parámetro e incrementa su valor en 1. ¿Por qué en 1? porque ese es el segundo parámetro que recibió la función GEN_ID(). Si queremos incrementarlo en 2 entonces habríamos escrito:

NEW.PRD_IDENTI = GEN_ID(PRODUCTOS_PRD_IDENTI_GEN, 2);

y así los valores del generador se incrementarían de 2 en 2.

También podríamos poner como segundo parámetro el número 0 ¿para qué nos serviría eso? para conocer el valor actual del generador. Eso significa que si escribimos:

SELECT GEN_ID(PRODUCTOS_PRD_IDENTI_GEN, 0) FROM RDB$DATABASE

podremos conocer cual es el valor actual del generador llamado PRODUCTOS_PRD_IDENTI_GEN

Y si lo deseamos, también podríamos usar un número negativo en el segundo parámetro.

Otra forma para cambiar el valor de un generador:

Además de usar la función GEN_ID() para cambiar el valor de un generador también podríamos hacerlo así:

SET GENERATOR PRODUCTOS_PRD_IDENTI_GEN TO 157;

cuando se ejecute ese comando el valor del generador PRODUCTOS_PRD_IDENTI_GEN será 157

Los generadores cuyos valores les asignó la función GEN_IDE() están afuera de las transacciones

Cuando la función GEN_ID() le asigna un valor a un generador, lo hace en su propia transacción, afuera de cualquier otra transacción que esté activa en ese momento. Eso significa que el valor asignado al generador permanece en él, no cambia, sin importar que la transacción finalice con un COMMIT o con un ROLLBACK.

Ejemplo:

El valor del generador antes de llamar a la función GEN_ID() es 211

Se llama a la función GEN_ID()

El valor del generador es ahora 212

La transacción donde se encuentra la función GEN_ID() terminó con un ROLLBACK

El valor del generador sigue siendo 212

¿Es conveniente cambiar manualmente el valor de un generador?

Depende de para que lo uses, si lo estás usando para asignarle valores a la columna que tienes definida como Primary Key la respuesta es un rotundo NO.

Podrías cambiarlo, si lo deseas, pero eso solamente podría acarrearte problemas y ningún beneficio.

¿Por qué no es conveniente cambiar el valor de un generador que se usa en una Primary Key?

Porque entonces pierdes la principal ventaja de usar un generador en la Primary Key: la seguridad 100% de que sus valores jamás se repetirán. Si disminuyes su valor, dos usuarios podrían intentar usar el mismo valor del generador y ese conflicto ocasionará pérdida de tiempo.

Pero las Primary Key tienen valores salteados, en una tabla pasaron del 226 al 231, faltan 4 números ahí.

Sí. ¿Y qué? ¿cuál es el problema con eso? Las Primary Key sirven para identificar a una fila exactamente, sin confusión posible. Que haya números faltantes no importa, mientras la Primary Key identifique exactamente a cada fila funciona perfectamente, esa es su utilidad, para eso sirve.

Pero a mí no me gusta que falten números, en los informes queda feo y a mis clientes tampoco les gusta

Estás confundiendo las cosas. Una cosa es la Primary Key y otra cosa distinta es el código de un ítem.

Mucha gente usa a los códigos como Primary Key pero eso es un error de concepto. Una Primary Key sirve para identificar a una fila internamente, en cambio un código sirve para identificar a una fila externamente.

Desde luego que en una tabla puedes tener ambos y eso es lo usual. Pero no confundas el uno con la otra.

La confusión ocurre porque el código pueden ser usado internamente y la Primary Key puede ser usada externamente, pero no deberían mezclarse. ¿Quieres relacionar una tabla con otra tabla? Usa la Primary Key. ¿Quiéres mostrarle una consulta al usuario? Usa el código. Y para que los informes queden bien bonitos como te gusta a tí y le gusta a tu cliente, esos códigos sí puedes numerarlos de 1 en 1, sin que falte ninguno.

Pero no cambies el valor de la Primary Key. Es realmente muy estúpido hacer eso. Te tomará más tiempo y solamente podrás tener problemas y ningún beneficio.

Artículo relacionado:

El índice del blog Firebird21

Usando EMS SQL Manager para copiar entre bases de datos

6 comentarios

A veces tenemos dos bases de datos que tienen tablas iguales o similares. Y como en una/s tabla/s de una de esas bases de datos ya se han insertado bastantes filas, nos gustaría simplemente copiar esas filas a la otra Base de Datos.

Hay muchas formas de realizar esa tarea, esta es una de ellas, es muy útil cuando son varias las tablas cuyos contenidos deseamos copiar aunque por supuesto podríamos usarla para copiar los datos de una sola tabla.

Veamos un ejemplo:

En una Base de Datos tenemos una tabla llamada BANCOS, que ya tiene insertadas varias filas:

EMS1

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

y esas mismas filas queremos copiar en la tabla BANCOS de otra Base de Datos. Para ello, hacemos clic con el botón derecho sobre el nombre de la Base de Datos original, o sea la que tiene las filas que deseamos insertar.

EMS2

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

en el menú contextual que nos aparece elegimos Tasks y luego Extract Database…

EMS3

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

a continuación marcamos la opción Extract all metadata and data of the database y hacemos clic en el botón “Next”

EMS4

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

ahora, elegimos la opción Automatically load to Script Editor y luego clic sobre el botón “Next”

EMS5

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

en la siguiente pantalla elegimos como queremos extraer las columnas de tipo BLOB, y en la que aparece a continuación podemos desmarcar todas las opciones porque no nos harán falta para lo que deseamos hacer

EMS6

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

después de un clic sobre el botón “Next” veremos esta pantalla:

EMS7

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

donde tendremos que hacer clic sobre el botón “Finish” para que empiece el proceso (sí, ya sé que es medio raro tener que hacer clic sobre el botón “Finish” para que algo empiece, pero bueno, así está). Cuando el proceso se haya completado hay que hacer clic sobre el botón “Close” y nos mostrará todos los metadatos y todos los datos de nuestra Base de Datos en forma de script.

Así que ahora buscamos el comando INSERT INTO BANCOS y seleccionamos y copiamos (con CTRL+C) todas las filas que  tienen ese comando:

EMS8

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

después abrimos la otra Base de Datos, y elegimos las opciones Tools y a continuación New SQL Script

EMS9

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

en la ventanita que aparece pegamos con CTRL+V lo los comandos INSERT INTO que habíamos copiado y finalmente hacemos clic en la opción Execute script

EMS10

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

y listo, asunto concluido. Todas las filas de la tabla BANCOS que se encontraban en una Base de Datos fueron copiadas a la otra Base de Datos, muy fácilmente y con muy poco esfuerzo.

Hay que aclarar que esta no es la forma más rápida de copiar las filas, pero es una forma práctica y sencilla cuando las filas a copiar no son muchas, quizás hasta unas pocas centenas y además si es algo esporádico. Si las filas son muchas o si este proceso de copia se va a realizar frecuentemente entonces hay que elegir otro método.

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

Tablas de validación

1 comentario

Cuando la cantidad de valores distintos que podemos tener en una columna es fija y es pequeña podemos usar dominios, pero si la cantidad crece entonces es más conveniente usar tablas de validación.

Ejemplo 1:

En una columna queremos guardar el sexo de una persona, sus valores posibles son ‘F’ y ‘M’ (femenino y masculino, respectivamente) entonces tener un dominio resuelve nuestro problema.

Ejemplo 2:

En una columna queremos guardar el estado civil de una persona, sus valores posibles son: ‘S’, ‘C’, ‘P’, ‘D’, ‘V’ (soltero, casado, separado, divorciado, viudo, respectivamente). También en este caso un dominio resuelve nuestro problema.

Ejemplo 3:

En una columna queremos tener la abreviatura del estado de los Estados Unidos, pero hay 50 estados y por lo tanto 50 abreviaturas (AL=Alabama, AK=Alaska, AZ=Arizona, AR=Arkansas, etc.) y eso ya es demasiado para un dominio, claro que podríamos usar un dominio también pero para estos casos es mejor usar una tabla de validación.

TABLAS1

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

TABLAS2

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

Para asegurarnos de no tener valores duplicados, la columna EST_ABREVI debería tener una restricción Unique Key y la columna EST_NOMBRE también debería tener una restricción Unique Key.

Supongamos que deseamos registrar a cual de esos estados pertenece nuestro proveedor. Entonces, en un trigger “Before Insert or Update” de la tabla PROVEEDORES escribiríamos:

CREATE TRIGGER PROVEEDORES_BIU FOR PROVEEDORES
ACTIVE BEFORE INSERT OR UPDATE
POSITION 1
AS
BEGIN
   IF (NEW.PRO_ESTUSA NOT IN (SELECT EST_ABREVI FROM ESTADOS_USA)) THEN
      EXCEPTION E_ESTADO_USA_INEXISTENTE;
END;

O sea que si se quiere insertar o actualizar en la columna PRO_ESTUSA (Estado de los Estados Unidos donde se encuentra el Proveedor) un valor que no se encuentre en la columna EST_ABREVI de la tabla ESTADOS_USA se lanzará la excepción de que ese Estado no existe.

De esta manera nos aseguramos de que siempre en la columna PRO_ESTUSA tengamos un valor correcto.

Otra forma de conseguir este mismo efecto es con una Foreign Key que relacione a las columnas PRO_ESTUSA y EST_ABREVI. Sólo que si son muchos proveedores podría no justificarse porque la Foreign Key creará un índice que debe ser mantenido, consumiendo tiempo quizás innecesariamente.

Hay muchos otros casos en los cuales usar tablas de validación es muy útil, por ejemplo:

  • Nombres de todos los documentos contables y administrativos
  • Nombres de todos los Bancos del país
  • Nombres de todos los impuestos
  • Nombres de todos los municipios
  • Nombres de todas las sucursales
  • Nombres de todos los países
  • Nombres de todas las monedas extranjeras utilizadas
  • etc.

Una de las ventajas de usar tablas de validación y no dominios es que se puede crear fácilmente un programa que le permita al usuario final agregar más filas. Por ejemplo, si un nuevo Banco empieza a operar en el país el usuario podría agregar el nombre de ese Banco a la tabla de BANCOS. Si usáramos un dominio entonces el Administrador de la Base de Datos tendría que agregar el nombre del Banco al dominio adecuado y siempre es preferible que los metadatos se toquen lo menos posible en una Base de Datos que está en producción.

Conclusión:

Si la cantidad de valores distintos que podemos tener en una columna es fija y es pequeña entonces podemos usar dominios, pero si la cantidad crece es más conveniente usar tablas de validación. En este caso, con un trigger “Before Insert or Update” nos aseguramos de que el valor que se quiere escribir en una columna sea un valor admitido. Además, si usamos tablas de validación le podemos agregar a nuestras aplicaciones la opción de que sean los usuarios quienes agreguen filas a esas tablas.

Artículo relacionado:

El índice del blog Firebird21

 

Insertando valores por defecto

1 comentario

Con Firebird tenemos la posibilidad de insertar valores automáticamente en las columnas. Esto puede resultar muy útil porque nos ahorra tiempo al escribir el comando INSERT (o el comando: UPDATE OR INSERT) y también nos asegura que esas columnas siempre tengan valores, que no se guarde NULL en ellas.

INSERTAR1Captura 1. (Si haces clic en la imagen la verás más grande)

En la Captura 1 podemos ver la estructura de la tabla ALUMNOS. Ninguna columna tiene un valor por defecto entonces si escribimos:

INSERT INTO ALUMNOS
           (ALU_IDENTI, ALU_NOMBRE, ALU_APELLD)
    VALUES (0         , 'JUAN'    , 'PÉREZ')

Esto será lo que obtendremos:

INSERTAR2

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

Como puedes ver en la Captura 2 las columnas ALU_IDENTI, ALU_NOMBRE y ALU_APELLD tienen valores mientras que las demás columnas tienen NULL en ellas.

Modifiquemos ahora la tabla ALUMNOS para ponerle valores por defecto a algunas columnas y veamos que sucede.

INSERTAR3

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

Ahora tenemos cuatro columnas que tienen valores por defecto (son los que se encuentran en “Default Source”). Entonces cuando insertamos una nueva fila:

INSERT INTO ALUMNOS
           (ALU_IDENTI, ALU_NOMBRE, ALU_APELLD)
    VALUES (0         , 'MARÍA'   , 'BENÍTEZ' )

esto es lo que obtenemos:
INSERTAR4

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

 como puedes ver, ahora al insertar una fila también se insertan automáticamente sus valores por defecto.

CURRENT_USER es el usuario actual

CURRENT_TIMESTAMP es la fecha y hora del Servidor

Si no queremos que se inserten los valores por defecto entonces debemos asignarle un valor a las columnas respectivas, como vemos a continuación:

INSERT INTO ALUMNOS
           (ALU_IDENTI, ALU_NOMBRE, ALU_APELLD, ALU_CODDEP, ALU_CODLOC)
    VALUES (0         , 'ESTELA'  , 'MARTÍNEZ', '04'      , '03'      )

Como acá le asignamos valores a las columnas ALU_CODDEP y ALU_CODLOC entonces esos son los que se guardan, no los valores por defecto sino los que asignamos en el comando INSERT.

INSERTAR5

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

La columna ALU_CODDEP tiene ’04’ y la columna ALU_CODLOC tiene ’03’ porque esos valores fueron escritos en el comando INSERT y lo que se escribe en el INSERT siempre tiene preferencia. Los valores por defecto solamente se usan cuando no se especifica un valor para la columna.

Conclusión:

Si usamos valores por defecto tenemos estas ventajas:

  1. Nos aseguramos que la columna tenga un valor (o sea, que no se quede en NULL)
  2. Escribimos menos en el comando INSERT (porque el Firebird automáticamente le asigna un valor a la columna)

En muchos casos resulta muy conveniente registrar quien fue el usuario que insertó una fila y también la fecha y la hora en la cual lo hizo. Si usamos valores por defecto entonces no necesitamos recordar escribirlos, el Firebird lo hará por nosotros. Esta facilidad que nos provee el Firebird de inserción automática de valores en las columnas es muy útil, deberíamos aprovecharla.

Artículo relacionado:

El índice del blog Firebird21

¿Cómo insertar rápidamente filas en una tabla desde otra tabla?

3 comentarios

A veces queremos que en una tabla T1 se inserten datos que se encuentran en una tabla T2. Hay varias formas de conseguir eso, la más rápida de todas es la siguiente:

INSERT INTO
   T1
SELECT
   *
FROM
   T2

Por supuesto que debes reemplazar T1 y T2 por los verdaderos nombres de tus respectivas tablas. Esto funciona siempre y cuando ambas tablas tengan la misma estructura, si ese no es el caso entonces hay que especificar las columnas involucradas.

INSERT INTO
   T1
   (T1Columna1,
    T1Columna2,
    T1Columna3)
SELECT
   T2Columna1,
   T2Columna2,
   T2Columna3
FROM
   T2

Los nombres de las columnas pueden ser distintos ya que el Firebird no se fija en el nombre de las columnas para realizar la inserción. Los únicos requisitos son:

  • La cantidad de columnas después del INSERT debe ser igual a la cantidad de columnas después del SELECT
  • Los tipos de datos de cada columna después del INSERT deben ser iguales o compatibles con los tipos de datos de cada columna después del SELECT

NOTA:

Si la estructura de las tablas puede cambiar es preferible poner los comandos dentro de una instrucción EXECUTE STATEMENT para que no muestre el error “object in use”. O sea:

EXECUTE STATEMENT “INSERT INTO T1…”

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

Detectando modificaciones no autorizadas a nuestras tablas

10 comentarios

Si los usuarios pueden insertar, actualizar, o borrar registros de las tablas desde afuera de nuestras aplicaciones (Contabilidad, Producción, Sueldos, Ventas, etc.) eso solamente puede significar problemas, nada bueno obtendremos de sus acciones.

Por ejemplo, un empleado se enteró de cual es el password del usuario SYSDBA y como ese empleado conoce suficiente de Informática entonces se conecta a la Base de Datos como SYSDBA y estando allí … hace lo que se le ocurre.

Algunos ejemplos de lo que podría hacer:

  1. Se aumenta su propio sueldo, digamos en un 8%
  2. Se pone de acuerdo con un cliente de la empresa para marcar como cobrada una Factura que aún no ha sido cobrada
  3. Un alumno se aplazó en una materia, pero la marca como aprobada
  4. Modifica el precio de venta de un producto para que el vendedor cobre una comisión mayor por esa venta

Inclusive si es inteligente, podría aumentar su sueldo y también el de otros empleados más para que sea más difícil deducir que fue él quien lo alteró. Si un solo empleado recibió un aumento fraudulento de sueldo cuando se detecte todas las miradas se dirigirán hacia él; pero si son 30 los empleados que recibieron el aumento fraudulento del sueldo será más difícil encontrar al culpable. Si es lo suficientemente astuto inclusive pondrá en la lista de beneficiarios a aquellas personas con las cuales no se lleva bien: si Juan es el empleado deshonesto y todos saben que él y Raúl son enemigos, si Raúl también recibió el aumento (e inclusive un aumento mayor) será más difícil creer que el culpable es Juan.

Y entonces ¿por qué ocurrió ese aumento fraudulento? para los propietarios de la Empresa la respuesta es fácil … porque la aplicación de Sueldos falló, y por lo tanto el programador es el culpable. Y claro, el pobre programador puede pasarse horas y horas buscando errores en su código fuente y jamás los encontrará, porque el problema no está en su programa sino en la modificación de las tablas desde afuera de su programa.

¿Cómo se puede detectar si una fila se insertó o modificó desde afuera de nuestras aplicaciones?

Una técnica es agregándole a cada tabla una columna para “checksum”. Un checksum es un número que se usa para controlar que los datos que existen en las demás columnas fueron puestos de forma autorizada.

DETECTAR1

(si haces clic en la imagen la verás más grande)

En este ejemplo a la tabla de BANCOS se le agregó una columna llamada BAN_CHECKS donde se guardará el checksum de la fila.

Para generar el checksum un método es el siguiente:

  • Convertir el valor de cada columna a carácter
  • Concatenar todas esas columnas
  • Concatenarle un testigo
  • Grabar el hash

Ejemplo en Visual FoxPro:

Si conoces el lenguaje Visual FoxPro aquí puedes ver una posible implementación:

WITH ThisForm
   M.BAN_CODSUC = .Text1.Value
   M.BAN_IDENTI = .Text2.Value
   M.BAN_NOMBRE = .Text3.Value
   M.BAN_CHECKS = Str(M.BAN_CODSUC, 2) + Str(M.BAN_IDENTI, 3) + M.BAN_NOMBRE + "ASU-PAR-123456"
ENDWITH

lcComando = "EXECUTE PROCEDURE Grabar_Banco(?M.BAN_CODSUC, ?M.BAN_IDENTI, ?M.BAN_NOMBRE, ?M.BAN_CHECKS)"

=SQL_Exec(gnHandle, lcComando)

Y este es el stored procedure Grabar_Banco:

SET TERM ^ ;

CREATE PROCEDURE GRABAR_BANCO(
   CodSuc TYPE OF COLUMN BANCOS.BAN_CODSUC,
   Identi TYPE OF COLUMN BANCOS.BAN_IDENTI,
   Nombre TYPE OF COLUMN BANCOS.BAN_NOMBRE,
   CheckS TYPE OF COLUMN BANCOS.BAN_CHECKS)
AS
BEGIN

   UPDATE OR INSERT INTO BANCOS
            (BAN_CODSUC, BAN_IDENTI, BAN_NOMBRE, BAN_CHECKS)
     VALUES (:CodSuc   , :Identi   , :Nombre   , Hash(:CheckS)) ;

END^

SET TERM ; ^

¿Qué es un testigo?

Son los caracteres adicionales que se le agregan a un string para que los intrusos no obtengan el mismo resultado del hash que obtenemos nosotros. En el ejemplo el testigo es ASU-PAR-123456

Aunque los intrusos obtengan y graben un hash en la columna BAN_CHECKS jamás obtendrán el mismo resultado porque ellos no le están agregando el testigo al string.

Por ejemplo, ellos escriben:

INSERT INTO BANCOS VALUES(0, 0, ‘BANCO ITAÚ’, HASH(‘0 0 BANCO ITAÚ’))

Pero nosotros escribimos:

INSERT INTO BANCOS VALUES(0, 0, ‘BANCO ITAÚ’, HASH(‘0 0 BANCO ITAÚ ASU-PAR-123456’))

Y como los strings que son argumentos de la función HASH() son distintos también lo serán los valores devueltos por dicha función. Si ellos no saben que le agregamos un testigo al string (o lo saben, pero no saben cual es ese testigo) jamás obtendrán el mismo resultado de la función HASH()

Detectando una inserción o modificación no autorizada:

Al escribir: SELECT * FROM BANCOS esto es lo que obtenemos:

DETECTAR2

(si haces clic en la imagen la verás más grande)

¿Cómo podemos averiguar si todas las columnas tienen valores legítimos o alguna es fraudulenta?

Escribiendo el comando:

SELECT
   HASH(CAST(BAN_CODSUC AS CHAR(2)) || CAST(BAN_IDENTI AS CHAR(3)) || BAN_NOMBRE || 'ASU-PAR-123456') AS MiCheck,
   BAN_CHECKS
FROM
   BANCOS

Y esto es lo que obtenemos:

DETECTAR3

(si haces clic en la imagen la verás más grande)

 Si te fijas con atención verás que en la última fila los números no coinciden. ¿Por qué no coinciden? Porque fue ingresada de forma fraudulenta, o sea desde afuera de nuestra aplicación.

Si solamente quieres ver las filas fraudulentas podrías escribir:

SELECT
   BAN_CODSUC,
   BAN_IDENTI,
   BAN_NOMBRE
FROM
   BANCOS
WHERE
   HASH(CAST(BAN_CODSUC AS CHAR(2)) || CAST(BAN_IDENTI AS CHAR(3)) || BAN_NOMBRE || 'ASU-PAR-123456') <> BAN_CHECKS

Y en ese caso obtendrías esto:

DETECTAR4

(si haces clic en la imagen la verás más grande)

 Conclusión:

Si usas la función HASH() en una columna de checksum y a la función HASH() además del string con los datos le envías un testigo podrás demostrar que el valor que tiene una columna fue puesto desde afuera de tu aplicación. Y por lo tanto, tu programa no es el culpable de cualquier cosa mala que haya pasado.

Para tu mayor protección podrías firmar un contrato con tu cliente donde especificas claramente que te desligas de toda  responsabilidad si alguna fila fue insertada o modificada desde afuera de tu aplicación.

Artículos relacionados:

La función HASH()

El índice del blog Firebird21

Older Entries Newer Entries