Tengo una declaración de ACTUALIZACIÓN que escribí que tomará un @CHANGE (valor entero positivo o negativo) y actualizará el CURRENT_INVENTORY para ese tipo de elemento.

UPDATE ITEM_INVENTORY
SET    CURRENT_INVENTORY = MAX(CURRENT_INVENTORY + @CHANGE, 0),
       LAST_UPD_TSTAMP = CURRENT_TIMESTAMP,
       LAST_UPD_SOURCE = @SOURCE
WHERE  LOCATION = @LOCATION
       AND ITEM_TYPE = @ITEM_TYPE;

Me gustaría saber qué es CURRENT_INVENTORY antes y después de ejecutar esta actualización. ¿Hay alguna forma de seleccionar el valor OLD TABLE y FINAL TABLE de CURRENT_INVENTORY?

Quiero mostrar un mensaje como "El inventario de {ubicación} cambió de {antiguo} a {nuevo}". Podría usar un SELECT separado para obtener el valor anterior / actual, hacer los cálculos en mi código y luego ACTUALIZAR la fila en la tabla. Sin embargo, creo que sería susceptible a las condiciones de carrera (ya que el primer SELECT no bloqueará la fila), así que estoy intentando hacerlo en una sola consulta.

No creo que pueda seleccionar tanto ANTIGUO como FINAL, así que creo que las mejores soluciones que tengo son:

  1. Seleccione el valor de OLD TABLE y duplique la lógica de la declaración CASE para derivar el nuevo valor
  2. Seleccione el valor de OLD TABLE y seleccione el nuevo valor (dentro de la misma transacción ahora que mi ACTUALIZACIÓN ha bloqueado la fila)

¿Existe una forma mejor / correcta de lograr esto?

1
Jeff B 16 oct. 2018 a las 18:11

2 respuestas

La mejor respuesta

Puede usar "seleccionar de actualización" para eso (manual de SQL). Ejemplo:

SELECT EMPNO, SALARY, BONUS , OLD_SALARY , OLD_BONUS
    FROM FINAL TABLE
        (UPDATE EMP  INCLUDE  ( OLD_SALARY DECIMAL(9,2)
                              , OLD_BONUS DECIMAL(9,2))
        SET SALARY     = SALARY+1000
        ,   BONUS      = 0
        ,   OLD_SALARY = SALARY
        ,   OLD_BONUS  = BONUS
        WHERE SALARY > 28000);
3
Paul Vernon 16 oct. 2018 a las 15:52

Actualizando la vista en línea en lugar de la tabla:

SELECT CURRENT_INVENTORY, CURRENT_INVENTORY_OLD
FROM FINAL TABLE(
  UPDATE (SELECT *, CURRENT_INVENTORY AS CURRENT_INVENTORY_OLD 
          FROM ITEM_INVENTORY)
  SET CURRENT_INVENTORY = CASE 
                             WHEN CURRENT_INVENTORY + @CHANGE < 0 THEN 0
                             ELSE CURRENT_INVENTORY + @CHANGE
                           END,
       LAST_UPD_TSTAMP = CURRENT_TIMESTAMP,
       LAST_UPD_SOURCE = @SOURCE
  WHERE LOCATION = @LOCATION
    AND ITEM_TYPE = @ITEM_TYPE
);
1
Lukasz Szozda 16 oct. 2018 a las 16:21