Probablemente ya has usado vistas para consultar datos y si no lo has hecho seguro que pronto lo harás, ya que eso es lo correcto. Tener las consultas precompiladas aumenta la velocidad de respuesta.

Sin embargo, ¿sabías que también puedes usar las vistas para insertar, actualizar, o borrar filas?

En un entorno multiusuario, donde muchas personas pueden estar al mismo tiempo conectadas a una Base de Datos es importantísimo limitar lo que cada una de esas personas puede hacer. De lo contrario, alguien podría estar haciendo algo que debería tener prohibido. Por ejemplo, un vendedor no debería tener la posibilidad de cambiar el precio de venta de un producto porque eso se presta a corrupción. Ni tampoco poder cambiar el porcentaje de comisión que cobra por cada venta.

Si necesitas que un usuario pueda insertar, actualizar, o borrar filas de una tabla puedes hacerlo de dos formas:

  1. Otorgándole derechos sobre esa tabla
  2. Otorgándole derechos sobre una vista, la cual se encargará de realizar las operaciones sobre dicha tabla

El problema de hacerlo con la primera forma es que el usuario podrá también ver y cambiar columnas que no debería poder ver o cambiar. Si le das el derecho de consulta sobre la tabla PRODUCTOS hace un SELECT * FROM PRODUCTOS y ve todas las filas y todas las columnas de esa tabla.

Mediante la segunda forma, en cambio, puedes controlar muchísimo mejor lo que puede y lo que no puede hacer. Si le das el derecho de consulta sobre la vista V_PRODUCTOS  la cual contiene un SELECT PRD_CODIGO, PRD_NOMBRE FROM PRODUCTOS, entonces solamente podrá ver el código y el nombre de cada producto y nada más.

Desde el punto de vista del Firebird puedes tratar a una vista como si fuera un usuario. Es decir que a una vista puedes otorgarle derechos (privilegios, permisos) sobre una tabla.

Y a los usuarios humanos les otorgas derechos sobre la vista, no sobre la tabla.

Por lo tanto, en lugar de escribir esto:

GRANT ALL ON PRODUCTOS TO ALICIA

GRANT ALL ON PRODUCTOS TO CLAUDIA

GRANT ALL ON PRODUCTOS TO MIRTHA

Sería mucho mejor que escribas esto:

GRANT ALL ON PRODUCTOS TO V_PRODUCTOS

GRANT ALL ON V_PRODUCTOS TO ALICIA

GRANT ALL ON V_PRODUCTOS TO CLAUDIA

GRANT ALL ON V_PRODUCTOS TO MIRTHA

Y fíjate en la primera línea, allí se trata a la vista V_PRODUCTOS como si fuera una persona, ¡¡¡se le están otorgando derechos sobre una tabla!!!. Los derechos se le otorgan a la vista, no a una persona.

¿Qué significa todo esto?

Que ni ALICIA, ni CLAUDIA, ni MIRTHA podrán hacer algo con la tabla PRODUCTOS, no tienen derechos ahí, ni siquiera para consultarla. Pero sí tienen derechos sobre la vista V_PRODUCTOS y por lo tanto estarán limitadas a lo que la vista haga.

Hasta ahí todo bien pero ¿cómo hago para insertar, actualizar, o borrar filas usando vistas?

Muy simple, las vistas también tienen triggers. Entonces es en esos triggers donde escribirás el código que insertará, actualizará, o borrará filas de la/s tabla/s subyacentes. Aunque en realidad no es obligatorio que uses triggers pero sí es conveniente porque te da más control.

VISTAS1

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

VISTAS2

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

VISTAS3

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

Como puedes ver en la Captura 3, esta vista solamente nos permite insertar o actualizar las columnas PRD_IDENTI, PRD_CODIGO, y PRD_NOMBRE, pero no podemos hacer lo mismo con las columnas PRD_PRECTO y PRD_PREVTA. ¿Por qué no? porque en el trigger solamente podemos usar las columnas que pertenecen a la vista. Ni la columna PRD_PRECTO ni la columna PRD_PREVTA pertenecen a la vista, por lo tanto no las podemos usar en el trigger. Si lo intentas, obtendrás un mensaje de error.

En otras palabras, si a un usuario le otorgamos derechos sobre la vista V_PRODUCTOS él solamente podrá ver, insertar, y actualizar las columnas PRD_IDENTI, PRD_CODIGO, y PRD_NOMBRE, y ninguna columna más, porque ninguna otra columna pertenece a la vista.

Por lo tanto, si necesitamos que un usuario pueda acceder a las columnas PRD_PRECTO y PRD_PREVTA entonces deberemos crear otra vista, que le otorgue acceso a esas columnas.

¿Pero hacerlo así no nos obliga a trabajar más?

Pues sí, pero no puedes tenerlo todo fácil en la vida. Se trabaja más pero en contrapartida tu aplicación será mucho más segura y mucho más confiable. Si cualquiera puede meter las pezuñas en tus tablas eso tarde o temprano te provocará grandes problemas. Así que mejor evitarlos desde el principio.

UPDATE OR INSERT INTO V_PRODUCTOS
         (PRD_IDENTI, PRD_CODIGO, PRD_NOMBRE)
  VALUES (0         , '1234'    , 'Producto xxx');

Como puedes ver en el código fuente de arriba, la inserción, actualización, o borrado se hace de la forma normal, las diferencias son:

  1. Se escribe el nombre de una vista, no el nombre de una tabla
  2. Solamente se pueden usar las columnas que pertenecen a la vista

Conclusión:

Usar vistas para realizar todas las operaciones de manipulación de tablas (inserción, actualización, borrado, consulta) es lo mejor, es lo correcto, es lo ideal. ¿Por qué? porque eso nos da un control total, 100%, sobre lo que cada usuario puede hacer o no hacer.

De esta manera los usuarios nunca, y por ningún motivo, acceden directamente a las tablas. Todos los accesos lo hacen a través de las vistas. Y en nuestras vistas podemos usar la cláusula WHERE para establecer condiciones. Por lo tanto, solamente podrán hacer lo que específicamente queremos que puedan hacer. Y nada más.

Artículo relacionado:

El índice del blog Firebird21