Estoy tratando de crear un trigger que las actualizaciones de la otra tabla con PL/SQL y estoy teniendo algunos problemas. (He leído este pero no ayuda mucho).

Aquí está mi situación, tengo digamos 2 tablas :

Clientes Tabla

CustomerID número de Clave Principal, ItemsDelivered número

Elementos Tabla

CustomerID número, ItemID número, ItemDelivered Varchar(15)

Digamos que cuando somenone coloca una orden de compra tenemos un nuevo registro en la tabla de Artículos que se parece a esto:

| CustomerID | ItemID | ItemDelivered | 
|         1  |    1   |    False      |

Quiero un desencadenador que se plantean la ItemsDelivered contador cada vez que alguien actualiza el ItemDelivered collumn a «True».

create or replace Trigger UpdateDelivered  
   After Update On Items For
     Each Row 
Declare  
   Counter Customers.ItemsDelivered%Type; 
Begin
  If (:Old.ItemDelivered ='False' And :New.ItemDelivered='True') Then
     Select ItemsDelivered into Counter From Customers where CustomerdID =:New.CustomerID; 
     Update....
  end if; 
END;

Aquí está mi problema, si sólo la ItemDelivered columna que se actualiza no es Nueva.CustomerID!

Hay alguna forma de obtener el Idcliente de la fila que acaba de actualizar?
(He intentado unirse con insertar tabla virtual, pero estoy recibiendo un error que la tabla no existe)

  • De edad.CustomerID es lo que usted está buscando, supongo. Pero, ¿realmente quieres hacer esto? Acaba de unirse y de la cuenta cuando usted necesita la cuenta. Finalmente, usted va a empezar a tener problemas de integridad tratando de mantener las columnas calculadas como «ItemsDelivered».
  • por favor explique lo que usted quiere hacer ,por qué quieres :Nuevo.customerID ? y yo thnk desea que el :EDAD.customerID ?
  • Gracias mucho por su ayuda! El antiguo parámetro trabajó como un encanto!! Mi situación es un poco diferente de la que he descrito, he simplificado un poco. La cosa que yo quiero hacer en realidad es para aumentar el sueldo de una persona cada vez que vaya de «No casados» a «Casado» .Gracias realmente mucho,estoy muy agradecida por la ayuda:)
InformationsquelleAutor VGe0rge | 2012-04-06

2 Comentarios

  1. 3

    En una fila de nivel de disparo en un UPDATE, tanto :new.customerID y :old.customerID debe ser definido. Y a menos que usted está actualizando el CustomerID, los dos tendrán el mismo valor. Dado que, parece que quieres

    create or replace Trigger UpdateDelivered  
       After Update On Items For
         Each Row 
    Begin
      If (:Old.ItemDelivered ='False' And :New.ItemDelivered='True') Then
         Update Customers
            set itemsDelivered = itemsDelivered + 1
          where customerID = :new.customerID;
      end if; 
    END;

    Que se dice, sin embargo, el almacenamiento de este tipo de contador y su mantenimiento con un desencadenador es generalmente una problemática para el diseño de un modelo de datos. Viola básica de normalización y que potencialmente conduce a todo tipo de condiciones de carrera. Por ejemplo, si usted y el código del disparador de la forma en que se muestra inicialmente donde SELECT para obtener el conteo original y, a continuación, hacer una actualización, podrá introducir errores en un entorno multi-usuario, porque alguien podría estar también en el proceso de marcar un elemento entregado y ni transacción podría ver la otra sesión de cambios y su contador de prepararse para el valor incorrecto. Y aun en el caso de implementar código libre de errores, tienes que introducir un mecanismo de serialización (en este caso, el bloqueo de fila en el CUSTOMERS tabla llevado a cabo por el UPDATE) que hace que las diferentes sesiones de tener que esperar en cada uno de los otros– que va a limitar la escalabilidad y el rendimiento de la aplicación.

    Para demostrar que el :old.customerID y la :new.customerID ambos estarán definidos y ambos serán iguales

    SQL> desc items
     Name                                      Null?    Type
     ----------------------------------------- -------- ----------------------------
     CUSTOMERID                                         NUMBER
     ITEMID                                             NUMBER
     ITEMDELIVERED                                      VARCHAR2(10)
    
    
    SQL> ed
    Wrote file afiedt.buf
    
      1  create or replace
      2  trigger updateDelivered
      3    after update on items
      4    for each row
      5  begin
      6    if( :old.itemDelivered = 'False' and :new.itemDelivered = 'True' )
      7    then
      8      dbms_output.put_line( 'New CustoerID = ' || :new.customerID );
      9      dbms_output.put_line( 'Old CustomerID = ' || :old.customerID );
     10    end if;
     11* end;
    SQL> /
    
    Trigger created.
    
    SQL> select * from items;
    
    CUSTOMERID     ITEMID ITEMDELIVE
    ---------- ---------- ----------
             1          1 False
    
    SQL> update items
      2     set itemDelivered = 'True'
      3   where customerID = 1;
    New CustoerID = 1
    Old CustomerID = 1
    
    1 row updated.
    • Gracias mucho por su tiempo! Pensé que el viejo y el nuevo tiene el mismo valor pero no! Cuando actualizo solo el ItemDelivered columna de la nueva.customerID no tiene ningún valor!He probado eso y no funcionó! Estoy de acuerdo con usted sobre el contador cosa, no voy a usar esto para un contador,este fue un ejemplo simplificado. Tienen un buen tiempo:)
    • He actualizado mi respuesta con una demostración de que el :old.customerID y :new.customerID ambos estarán definidos y ambos serán iguales cuando se está actualizando el itemDelivered columna.
  2. 1

    Si desea almacenar el número de elementos en la base de datos, me gustaría recomendar un par de factores desencadenantes. Usted podría usar un después de la fila disparador para grabar el número de elemento (tal vez en una variable de tabla en el paquete) y un después de la declaración de gatillo que realmente actualizar el contador, el cálculo de los elementos entregados directamente a partir de la fecha base. Que es, por

    select sum(itemsDelivered) from Customers where itemId = :itemId;

    De esta manera, evitar los peligros de la corrupción de los contadores, ya que siempre se ajuste a lo que debería ser. Es probablemente una Buena Idea para mantener los datos obtenidos en una tabla separada.

    Hemos construido nuestro sistema viejo completamente de disparadores de base de datos en el que se actualizan los datos en el aparte «Derivados» de las tablas, y funcionó muy bien. Tenía la ventaja de que todos nuestros manipulación de datos puede realizarse mediante la inserción, actualización y eliminación de las tablas de base de datos sin necesidad de conocer las reglas de negocio. Por ejemplo, para poner a un estudiante en una clase, que sólo había que insertar una fila en la mesa de registro; después de la instrucción select, la matrícula, cuotas, ayuda financiera, y todo lo demás ya estaban calculados.

    • Esta es una solución mucho mejor , debo decir!En ese tiempo, no quiero un contador en realidad, pero voy a intentarlo cada vez que yo quiero uno. Gracias por tu tiempo:)
    • Tenga en cuenta que usted tiene el mismo tipo de condiciones de carrera con este tipo de enfoque. Si hay dos sesiones que están marcando el mismo elemento entregado a dos clientes diferentes en aproximadamente el mismo tiempo, las dos transacciones no va a ver unos a otros y usted puede fácilmente almacenar la información de resumen que difiere de la de detalle. Usted podría utilizar un rápido actualizable vista materializada que se actualiza en consignación para almacenar la información de resumen que siempre estará sincronizado con el detalle de los datos.
    • En realidad, no. La clave es que siempre calcular los valores derivados de cero, nunca de sus valores actuales. De esa manera siempre están en consonancia con la base de datos. Mantener los datos obtenidos en tablas separadas que nunca son humanos-actualizado también minimiza los problemas de bloqueo.

Dejar respuesta

Please enter your comment!
Please enter your name here