PDA

Ver la Versión Completa : triggers sobre vistas


marti
16-09-2004, 18:54:59
Deseo hacer un trigger sobre una vista, de forma tal que realice un cálculo sobre algún campo de la vista.

La vista luce asi:


CREATE VIEW ITEM_INVENTARIO_INFO (
ID_ITEM,
ID_BODEGA,
CANTIDAD,
COSTO,
TOTAL_COSTO,
PRIORIDAD
) AS
SELECT CD.ID_ITEM,CD.ID_BODEGA,CD.CANTIDAD,25.0,0.0,5
FROM REMISION C INNER JOIN REMISION_DET CD ON (C.ID_EMPRESA=CD.ID_EMPRESA AND C.ID_SUCURSAL=CD.ID_SUCURSAL AND C.ID_TIPO_DOC = CD.ID_TIPO_DOC AND C.NUMERO = CD.NUMERO)
UNION
SELECT CD.ID_ITEM,CD.ID_BODEGA,CD.CANTIDAD,25.0,0.0,5
FROM FACTURA C INNER JOIN FACTURA_DET CD ON (C.ID_EMPRESA=CD.ID_EMPRESA AND C.ID_SUCURSAL=CD.ID_SUCURSAL AND C.ID_TIPO_DOC = CD.ID_TIPO_DOC AND C.NUMERO = CD.NUMERO)
;



y el trigger luce asi:


CREATE TRIGGER TRIG_ITEM_INVENTARIO_INFO FOR ITEM_INVENTARIO_INFO
ACTIVE AFTER UPDATE POSITION 0
as
BEGIN
NEW.TOTAL_COSTO = NEW.CANTIDAD* NEW.COSTO;
END
^


El motor de la base de datos no genera ningún tipo de error al crear el trigger sobre la vista pero no hace lo que deseo que haga.

La vista me devuelve los siguientes registros


ID_ITEM ID_BODEGA CANTIDAD COSTO TOTAL_COSTO PRIORIDAD
0001 01 20 25 0 5
0001 01 50 25 0 5
0002 01 10 25 0 5
0002 01 20 25 0 5
0003 01 2 25 0 5
0003 01 100 25 0 5

El campo Total deberia tener un valor mayor a cero (cantidad*costo)

Es posible realizar este tipo de actualizaciones con Firebird?

Gracias por su colaboración
:confused:

guillotmarc
17-09-2004, 20:58:46
Hola.

¿ No seria mucho más sencillo incorporar ese calculo en la misma consulta, sin necesidad de ningún trigger ?


CREATE VIEW ITEM_INVENTARIO_INFO (
ID_ITEM,
ID_BODEGA,
CANTIDAD,
COSTO,
TOTAL_COSTO,
PRIORIDAD
) AS
SELECT CD.ID_ITEM,CD.ID_BODEGA,CD.CANTIDAD,25.0,CD.CANTIDAD*25.0,5
FROM REMISION C INNER JOIN REMISION_DET CD ON (C.ID_EMPRESA=CD.ID_EMPRESA AND C.ID_SUCURSAL=CD.ID_SUCURSAL AND C.ID_TIPO_DOC = CD.ID_TIPO_DOC AND C.NUMERO = CD.NUMERO)
UNION
SELECT CD.ID_ITEM,CD.ID_BODEGA,CD.CANTIDAD,25.0,CD.CANTIDAD*25.0,5
FROM FACTURA C INNER JOIN FACTURA_DET CD ON (C.ID_EMPRESA=CD.ID_EMPRESA AND C.ID_SUCURSAL=CD.ID_SUCURSAL AND C.ID_TIPO_DOC = CD.ID_TIPO_DOC AND C.NUMERO = CD.NUMERO)
;


NOTA : Desconozco si los triggers sobre vistas, se pueden usar de la forma que deseas. Aunque no lo veo nada claro. Tal como lo tengo entendido solo són para poder hacer modificables las vistas, es decir que si modificas un registro de la vista, salte el trigger para que tu código pueda indicar que tablas hay que modificar realmente.

Saludos.

marti
20-09-2004, 22:24:20
Gracias por responder guillotmarc, creo que no explique lo suficiente.

El problema que tengo que resolver es el siguiente:
Estoy desarrollando una aplicación que maneja el control de inventarios de una empresa, resulta que el sistema debe costear las existencias de inventario utilizando el método del promedio ponderado.
Básicamente, las transacciones son entradas y salidas del almacén donde está la mercancia, para esto he tratado de resolver el problema usando una
tabla para las facturas de ventas (Salidas del almacén) y devoluciones de facturas de venta (Entrada del almacén)
y otra tabla para los documentos que tiene que ver con las compras de mencancía, estos son Entradas de almacén (Entradas del almacén)
y Devoluciones de compra (Salidas del almacén).
Para realizar el cálculo del costo promedio los transacciones se realizan así:

Fecha detalle |Entradas |Salidas |saldos |costo unit
cant|costo cant|costo cant| costo
-----------------------------------------------------------------------
20/10/03 "compra" 10 150,0000 0 0 10 150,000 15,000

21/10/03 "compra" 40 600,000 0 0 50 750,000 15,000

22/10/03 "venta " 0 0 30 450,000 20 300,000 15,000

23/10/03 "dev.comp" (5) (75,000) 0 0 15 225,000 15,000

22/10/03 "dev.venta" 0 0 (2) (30,000) 17 255,000 15,000



1. En entradas: se registra la cantidad y el costo total de la compra o devolución de compra.

2. En salidas: se registra la cantidad de mercancia vendida; y en la columna del costo el resultado de multiplicar la cantidad por el costo unitario del renglón anterior.

3. En saldos: para obtener los valores de esta columna, a los valores del saldo anterior se le adicionan las entradas o se les disminuyen las salidas.

4. Costo unitario: para obtener el costo unitario se toma la columna de saldo anterior y se divide el costo total entre la cantidad total de cada renglón.
El costo total varia siempre que se compra mercancía a precio diferente; cuando se registra la salida se mantiene el último costo unitario.

Las estructuras de las tablas de ventas y compras lucen más o menos así:


VENTA_DET
-------------
ID_ITEM
CANTIDAD
COSTO
TOTAL

COMPRA_DET
------------
ID_ITEM
CANTIDAD
COSTO
TOTAL


Lo que desea realizar con la vista es hacer el cálculo del costo promedio de forma automática,
debido a que si por algún motivo uno de los registros correspondiente a entradas es retirado no tenga que recorrer toda la tabla para recalcular el costo unitario y mucho menos el saldo.


CREATE VIEW ITEM_INVENTARIO_INFO
(
FECHA ID_ITEM,
CANTIDAD_ENTRADA,
COSTO_ENTRADA,
CANTIDAD_SALIDA,
COSTO_SALIDA,
CANTIDAD_SALDO,
COSTO_SALDO,
COSTO_UNITARIO) AS

SELECT C.FECHA,CD.ID_ITEM,CD.CANTIDAD,CD.COSTO,0.0,0.0,0.0,0.0,0.0
FROM COMPRA C INNER JOIN COMPRA_DET CD ON
(C.ID_EMPRESA=CD.ID_EMPRESA AND C.ID_SUCURSAL=CD.ID_SUCURSAL AND
C.ID_TIPO_DOC = CD.ID_TIPO_DOC AND C.NUMERO = CD.NUMERO)
UNION
SELECT C.FECHA,CD.ID_ITEM,0.0,0.0,CD.CANTIDAD,CD.COSTO,0.0,0.0,0.0
FROM VENTA C INNER JOIN VENTA_DET CD ON
(C.ID_EMPRESA=CD.ID_EMPRESA AND C.ID_SUCURSAL=CD.ID_SUCURSAL AND
C.ID_TIPO_DOC = CD.ID_TIPO_DOC AND C.NUMERO = CD.NUMERO);


Hasta ahora no conozco una forma de hacer una consulta SQL que me permita obtener el valor del costo unitario.
Por esta razon envio algunos campo de la vista en cero y posteriormente con el trigger deseaba poder modificar dichos campos.

Si no es posible hacer esto de que forma podría obtener este resultado?

Cómo hago para que me queden bien organizados los valores que tiene forma de tabla como en el ejemplo de arriba, la verdad intenté de varias formas y no logre que quedará organizado.

Saludos

guillotmarc
21-09-2004, 11:56:48
Hola.

Con el trigger no puedes hacerlo, puesto que no están diseñados para este uso.

Puedes utilizar un procedimiento almacenado.

Ejplo. sencillo de procedimiento almacenado que devuelve un conjunto de datos :


CREATE PROCEDURE "CLIENTES_Lista"
RETURNS (
ID INTEGER,
NOMBRE VARCHAR(50),
APELLIDOS VARCHAR(50))
AS
begin
for select ID, NOMBRE, APELLIDOS
from CLIENTES
into :ID, :NOMBRE, :APELLIDOS
do begin
suspend;
end
end


NOTA: Antes del suspend puedes hacer todos los cálculos necesarios sobre el coste unitario.

Para recoger los datos del procedimiento almacenado puedes hacer algo como :

select * from "CLIENTES_Lista"

Saludos.

marti
21-09-2004, 16:41:17
Hola

Trataré de solicionar el problemas de acuerdo con tus sugerencias.

Gracias por tu valiosa colaboración. :D