Programação em Transact-SQL: Triggers/Gatilhos

Propaganda
Laboratório 5
Base de Dados II
2008/2009
Plano de Trabalho
Lab. 4: Programação em Transact-SQL
Referências
MICROSOFT SQL SERVER
- Triggers (gatilhos).
- Exercícios
1. Conceito.
- Os Stored Procedures permitem realizar a maior parte das operações envolvidas em
actividades de administração do dia-a-dia dum sistema de gestão de bases de dados.
- Contudo, estes procedimentos não são reactivos em relação a eventos tais como
saber se este ou aquele registo de dados de uma tabela foi inserido, alterado ou
simplesmente removido.
- Os gatilhos (ou triggers) são procedimentos especiais que são sensíveis a eventos,
ou seja, que reagem a eventos. Têm por função garantir as regras de negócio ou de
integridade no momento em que ocorrem eventos de modificação de dados numa
base de dados.
- A grande diferença entre procedimentos e gatilhos está na forma como eles são
invocados. Os procedimentos são invocados directa e explicitamente através das
ferramentas do SQL Server ou de uma qualquer aplicação cliente, ao passo que os
gatilhos são activados a partir de eventos de actualização (INSERT, UPDATE e
DELETE) que ocorram em tabelas ou vistas.
- Um gatilho faz parte integrante da definição duma tabela para a qual foi definido,
sendo só invocado quando uma das operações de actualização da tabela é efectuada.
- Os utilizadores não têm qualquer controlo sobre a invocação e consequente
execução de um gatilho, já que é o SQL Server que desencadeia a sua execução.
- Os gatilhos são tratados como transações, ou seja, se acontecer um problema, é
desfeito tudo que esse trigger tiver feito.
- A utilização de gatilhos é vantajosa em determinadas circunstâncias :
- Podem ser utilizados para efectuar alterações em cascade; por exemplo, se
apagar a factura eliminar automaticamente todas as linhas.
- Podem ser utilizados para colocar restrições mais complexas que as definidas
numa instrução de check, pois podem utilizar validações de colunas que tenham
ligação com outras tabelas (ao contrário do check).
- O gatilho tem a possibilidade de saber o estado do registo antes e depois de
uma determinada alteração, e efectuar acções de acordo com esse estado.
- Em resumo: um gatilho é um procedimento que é automaticamente executado em
resposta a um determinado evento. Esses eventos poder ser de INSERT, UPDATE
ou DELETE. Aliás, é possível executar um gatilho diferente por cada evento de
INSERT, UPDATE ou DELETE.
2. Sintaxe.
CREATE TRIGGER trigger_name
ON table
[WITH ENCRYPTION]
{
{FOR { [DELETE] [,] [INSERT] [,] [UPDATE] }
[WITH APPEND]
[NOT FOR REPLICATION]
AS
sql_statement [...n]
}
|
{FOR { [INSERT] [,] [UPDATE] }
[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]
}
}
Arguments
trigger_name
Is the name of the trigger. A trigger name must conform to the rules for identifiers and
must be unique within the database. Specifying the trigger owner name is optional.
table
Is the table on which the trigger is executed; sometimes called the trigger table.
Specifying the owner name of the table is optional. Views cannot be specified.
WITH ENCRYPTION
Encrypts the syscomments entries that contain the text of CREATE TRIGGER.
{ [DELETE] [,] [INSERT] [,] [UPDATE] } | { [INSERT] [,] [UPDATE]}
Are keywords that specify which data modification statements, when attempted against
this table, activate the trigger. At least one option must be specified. Any combination
of these in any order is allowed in the trigger definition. If more than one option is
specified, separate the options with commas.
WITH APPEND
Specifies that an additional trigger of an existing type should be added. Use of this
optional clause is needed only when the compatibility level is less than or equal to 65. If
the compatibility level is greater than or equal to 70, the WITH APPEND optional
clause is not needed to add an additional trigger of an existing type (this is the default
behavior of CREATE TRIGGER with the compatibility level setting greater than or
equal to 70.) .
NOT FOR REPLICATION
Indicates that the trigger should not be executed when a replication process modifies the
table involved in the trigger.
AS
Are the actions the trigger is to take.
sql_statement
Is the trigger condition(s) and action(s). Trigger conditions specify additional criteria
that determine whether the attempted DELETE, INSERT, or UPDATE statements
cause the trigger action(s) to be carried out.
The trigger actions specified in the Transact-SQL statements go into effect when the
user action (DELETE, INSERT, or UPDATE) is attempted.
Triggers can include any number and kind of Transact-SQL statements except
SELECT. A trigger is designed to check or change data based on a data modification
statement; it should not return data to the user. The Transact-SQL statements in a
trigger often include control-of-flow language. A few special tables are used in
CREATE TRIGGER statements:
• deleted and inserted are logical (conceptual) tables. They are structurally
similar to the table on which the trigger is defined (that is, the table on which the
user action is attempted) and hold the old values or new values of the rows that
may be changed by the user action. For example, to retrieve all values in the
deleted table, use:
SELECT *
FROM deleted
n
Is a placeholder indicating that multiple Transact-SQL statements can be included in
the trigger. For the IF UPDATE (column) statement, multiple columns can be included
by repeating the UPDATE (column) clause.
IF UPDATE (column)
Tests for an INSERT or UPDATE action to a specified column and is not used with
DELETE operations. More than one column can be specified. Because the table name is
specified in the ON clause, do not include the table name before the column name in an
IF UPDATE clause. To test for an INSERT or UPDATE action for more than one
column, specify a separate UPDATE(column) clause following the first one.
UPDATE(column) can be used anywhere inside the body of the trigger.
column
Is the name of the column to test for either an INSERT or UPDATE action. This
column can be of any data type supported by SQL Server.
IF (COLUMNS_UPDATED())
Tests, in an INSERT or UPDATE trigger only, whether the mentioned column or
columns were inserted or updated. COLUMNS_UPDATED returns a varbinary bit
pattern that indicates which columns in the table were inserted or updated.
COLUMNS_UPDATED can be used anywhere inside the body of the trigger.
bitwise_operator
Is the bitwise operator to use in the comparison.
updated_bitmask
Is the integer bitmask of those columns actually updated or inserted. For example, table
t1 contains columns C1, C2, C3, C4, and C5. To check whether columns C2, C3, and
C4 are all updated (with table t1 having an UPDATE trigger), specify a value of 14. To
check whether only column C2 is updated, specify a value of 2.
comparison_operator
Is the comparison operator. Use the equals sign (=) to check whether all columns
specified in updated_bitmask are actually updated. Use the greater than symbol (>) to
check whether any or some of the columns specified in updated_bitmask are updated.
column_bitmask
Is the integer bitmask of those columns to check whether they are updated or inserted.
3. Criação.
Podemos criar mais do que um gatilho por tabela ou vista, mas devemos saber que nesta
circunstância não temos grande controlo sobre a ordem pela qual os gatilhos são
disparados.
Apesar disto, o SQL Server dá-nos a possibilidade de indicar quais dos gatilhos são o
primeiro e o último a serem activados. Isto consegue-se à custa do procedimento
sp_settriggerorder.
O SQL Server permite definir 2 tipos diferentes de gatilhos:
•
•
AFTER. Só é disparado após todas as operações especificadas na caracterização do
gatilho terem sido executadas com sucesso. Este é o tipo de gatilho por omissão.
Podemos criar quantos gatilhos quisermos deste tipo para cada uma das operações
de INSERT, DELETE e UPDATE sobre uma tabela, mas não sobre uma vista.
INSTEAD OF. Estes gatilhos são executados em vez da instrução Transact-SQL de
manipulação de dados que provocou a sua activação. Podemos definir no máximo
um gatilho deste tipo para cada uma das operações de INSERT, DELETE e
UPDATE sobre uma tabela ou uma vista.
Há 2 formas de criar gatilhos no SQL Server:
• Procedure Wizard. Não existe!
• Enterprise Manager.
• Query Analyser. Há 4 maneiras possíveis:
- Sem template.
- Menu Principal. File -> New -> escolher template na pasta Create Trigger.
- Barra de ferramentas. Ícone New -> Create Trigger -> escolher template de
trigger.
- Navegador de objectos. Situa-se na sub-janela à esquerda do Query
Analyser. Aí podemos escolher o template do trigger.
Sintaxe simplificada.
CREATE TRIGGER <nome do gatilho>
ON <tabela>
FOR <tipo de operação> AS
<Bloco de Instruções SQL>
EXERCÍCIOS I
(base de dados Livro&Livro)
Exercício 1. (Query Analyser. Sem template. Gatilho para INSERT).
Crie um gatilho que lance uma mensagem de alerta sempre que seja lançada uma nova
promoção de livros na Livro&Livro.
-- T-SQL 6.21:
-- Gatilho que alerta o lançamento de uma nova promoção de
-- um livro.
-- Gatilho para a geração de alertas de promoções de livros.
CREATE TRIGGER AlertaLançamentoPromoção
ON [Livros-Promoções]
FOR INSERT AS
RAISERROR ('Inserção de uma nova promoção de livros na
base de dados.',16, 1)
---
Este gatilho é activado quando é executada uma operação de inserção sobre a tabela LivrosPromoções. A instrução RAISEERROR é utilizada para apresentar mensagens de erro
definidas pelo utilizador. Neste caso, a mensagem de erro é simplesmente uma mensagem
de alerta.
Exercício 2. (Gatilho para INSERT)
Crie um gatilho de actualização do acumulado de compras de um cliente.
-- T-SQL 6.22: Gatilho de actualização do acumulado de
-- compras de um cliente.
--- Gatilho para actualizar o acumulado de compras de um
-- cliente, após o registo de uma nova venda.
CREATE TRIGGER [inserçãoVenda] ON [dbo].[Vendas]
FOR INSERT
AS
UPDATE Clientes
SET [Valor-Acumulado-Compras] = [Valor-Acumulado-Compras] +
(SELECT [Total-C/-Imposto] FROM inserted)
WHERE Número = (SELECT Cliente FROM inserted)
---
Porquê é que usámos a tabela inserted em vez da tabela Vendas na
inquirição embutida SELECT [Total-C/-Imposto] FROM inserted ?
A tabela inserted conjuntamente com a tabela deleted são tabelas
especiais do SQL Server. As funções são, respectivamente, o
armazenamento de uma cópia do último registo inserido e do último registo
removido da tabela em que o gatilho está definido.
No nosso exercício acima, a tabela inserted contém o último registo inserido
na tabela de Vendas.
Exercício 3. (Exercício 2 só com um SELECT e variáveis locais. Gatilho para INSERT)
Neste caso, são as variáveis locais as responsáveis pelo transporte dos valores da tabela
Vendas utilizados na instrução UPDATE.
-- T-SQL 6.23: Utilização de variáveis locais na implementação de um
-- gatilho.
--- Gatilho para actualizar o acumulado de compras de um cliente, após o
-- registo de uma nova venda.
CREATE TRIGGER [inserçãoVenda] ON [dbo].[Vendas]
FOR INSERT
AS
DECLARE @ClienteVenda int, @TotalVenda money
SELECT @ClienteVenda = Cliente, @TotalVenda = [Total-C/-Imposto]
FROM inserted
UPDATE Clientes
SET [Valor-Acumulado-Compras] = [Valor-Acumulado-Compras]
+ @TotalVenda
WHERE Número = @ClienteVenda
---
Exercício 4. (Gatilho para DELETE)
Crie um gatilho para acerto do valor acumulado de compras de um cliente quando uma das
suas vendas é removida da base de dados.
-- T-SQL 6.24 ñ Gatilho para acerto do valor acumulado de compras
-- de um cliente.
--- Gatilho para acerto do valor acumulado de compras de um cliente.
CREATE TRIGGER [anulaçãoVenda] ON [dbo].[Vendas]
FOR DELETE
AS
UPDATE Clientes
SET [Valor-Acumulado-Compras] = [Valor-Acumulado-Compras]
- (SELECT [Total-C/-Imposto] FROM deleted)
WHERE Número = (SELECT Cliente FROM deleted)
---
Exercício 5. (Gatilho para UPDATE)
Crie um gatilho para corrigir os dados duma venda.
CREATE TRIGGER [anulaçãoVenda] ON [dbo].[Vendas]
FOR UPDATE
AS
UPDATE Clientes
SET [Valor-Acumulado-Compras] = [Valor-Acumulado-Compras]
- (SELECT [Total] FROM deleted)
+ (SELECT [Total] FROM inserted)
WHERE Número = (SELECT Cliente FROM deleted)
Neste exemplo podemos observar a utilização das duas tabelas especiais. A tabela deleted é
usada para retirar o valor errado da venda à tabela de clientes, ao passo que a tabela
inserted é usada para fornecer o valor correcto da venda.
Download