2011-12-14 10 views
15

Tengo el gatillo en una tabla y me gustaría leer el valor UserId cuando se inserta, actualiza o elimina una fila. ¿Como hacer eso? El código siguiente no funciona, me sale error en UPDATEDServidor SQL: activar cómo leer el valor para Insertar, Actualizar, Eliminar

ALTER TRIGGER [dbo].[UpdateUserCreditsLeft] 
    ON [dbo].[Order] 
    AFTER INSERT,UPDATE,DELETE 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    DECLARE 
    @UserId INT, 

    SELECT @UserId = INSERTED.UserId FROM INSERTED, DELETED 

    UPDATE dbo.[User] SET CreditsLeft = CreditsLeft - 1 WHERE Id = @UserId 
END 
+4

* También * incorrecto porque puede haber varias filas en estas tablas, por lo que intentar leer un valor en una variable le dará uno de los valores de esa fila (cuál no está definido). –

+1

Además de escribir un mensaje que cree que solo se cambiará una fila, lo cual es una práctica incorrecta, ha utilizado combinaciones implícitas que también son antipatrón sql. Nunca use uniones implícitas. En este momento tienes una combinación cruzada que probablemente no querías.Es inexcusable escribir dicho código casi 20 años después de que las uniones implícitas fueran reemplazadas por las combinaciones mucho mejores explícitas. – HLGEM

Respuesta

24

Tenga en cuenta que inserted, deleted significa lo mismo que inserted CROSS JOIN deleted y ofrece todas las combinaciones de cada fila. Dudo que esto es lo que quieres.

Algo como esto puede ayudar a empezar ...

SELECT 
    CASE WHEN inserted.primaryKey IS NULL THEN 'This is a delete' 
     WHEN deleted.primaryKey IS NULL THEN 'This is an insert' 
             ELSE 'This is an update' 
    END as Action, 
    * 
FROM 
    inserted 
FULL OUTER JOIN 
    deleted 
    ON inserted.primaryKey = deleted.primaryKey 


Dependiendo de lo que quiere hacer, a continuación referencia a la tabla le interesa con inserted.userID o deleted.userID, etc. .


Por último, tenga en cuenta que inserted y deleted son tablas y pueden (y lo hacen) contener más de un registro.

Si inserta 10 registros a la vez, la tabla inserted contendrá TODOS los 10 registros. Lo mismo se aplica a las eliminaciones y a la tabla deleted. Y ambas tablas en el caso de una actualización.


EDITAR Examplee gatillo después PO edición.

ALTER TRIGGER [dbo].[UpdateUserCreditsLeft] 
    ON [dbo].[Order] 
    AFTER INSERT,UPDATE,DELETE 
AS 
BEGIN 

    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    UPDATE 
    User 
    SET 
    CreditsLeft = CASE WHEN inserted.UserID IS NULL THEN <new value for a DELETE> 
         WHEN deleted.UserID IS NULL THEN <new value for an INSERT> 
                ELSE <new value for an UPDATE> 
        END 
    FROM 
    User 
    INNER JOIN 
    (
     inserted 
    FULL OUTER JOIN 
     deleted 
     ON inserted.UserID = deleted.UserID -- This assumes UserID is the PK on UpdateUserCreditsLeft 
    ) 
     ON User.UserID = COALESCE(inserted.UserID, deleted.UserID) 

END 


Si PrimaryKey de UpdateUserCreditsLeft es algo distinto de identificación de usuario, el uso que en el FULL OUTER JOIN en su lugar.

+1

excelente respuesta, esta me salvó el trabajo hoy – wondergoat77

20

No hay updated tabla dinámica. Solo hay inserted y deleted. En un comando UPDATE, los datos antiguos se almacenan en la tabla dinámica deleted, y los nuevos valores se almacenan en la tabla dinámica inserted.

Piense en un UPDATE como una combinación de DELETE/INSERT.

+0

He cambiado la línea a SELECT @UserId = UserId FROM INSERTED, BORRADO y ahora recibo el error Nombre de columna ambiguo 'UserId'. – Tomas

+1

@Tomas - Vea mi respuesta, no creo que ',' signifique lo que usted piensa que significa. – MatBailie

+0

@Tomas necesita especificar el origen del campo 'UserId'. Por ejemplo, haga algo como 'select @UserId = inserted.UserId from inserted, deleted' –

-4

Ésta es la sintaxis para crear un disparador:

CREATE TRIGGER trigger_name 
ON { table | view } 
[ WITH ENCRYPTION ] 
{ 
    { { FOR | AFTER | INSTEAD OF } { [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] } 
     [ WITH APPEND ] 
     [ NOT FOR REPLICATION ] 
     AS 
     [ { IF UPDATE (column) 
      [ { AND | OR } UPDATE (column) ] 
       [ ...n ] 
     | IF (COLUMNS_UPDATED () { bitwise_operator } updated_bitmask) 
       { comparison_operator } column_bitmask [ ...n ] 
     } ] 
     sql_statement [ ...n ] 
    } 
} 

Si desea utilizar Sobre actualización sólo se puede hacer con la sección IF UPDATE (column). No es posible hacer lo que estás pidiendo.

Cuestiones relacionadas