Trigger Overview

You are viewing an old version of this article. View the current version here.

A trigger, as its name suggests, is a set of statements that run, or are triggered, when an event occurs on a table. 이름에서 알 수 있듯이, 트리거는 테이블에 이벤트가 발생할때 실행되는(또는 '트리거'되는) 명령문의 세트입니다.

이벤트

The event can be an INSERT, an UPDATE or a DELETE. The trigger can be executed BEFORE or AFTER the event. Until MariaDB 10.2.3, a table could have only one trigger defined for each event/timing combination: for example, a table could only have one BEFORE INSERT trigger. 이벤트는 INSERT, UPDATE 또는 DELETE일 수 있습니다. 트리거는 이벤트 시작 전 또는 발생 후에 실행될 수 있습니다. MariaDB 10.2.3까지는 하나의 테이블은 하나의 이벤트/타이밍 조합에 대해 오직 한 가지 트리거만을 정의할 수 있었습니다. 예를 들어, 테이블은 (INSERT 시작 전에 수행되는)BEFORE INSERT 트리거를 단 하나만 가집니다.

The LOAD DATA INFILE and LOAD XML statements invoke INSERT triggers for each row that is being inserted. LOAD DATA INFILELOAD XML문은 삽입되는 데이터 한 행 마다 INSERT 트리거를 발생시킵니다.

The REPLACE statement is executed with the following workflow: REPLACE문은 아래와 같은 흐름으로 실행됩니다

  • BEFORE INSERT;
  • BEFORE DELETE (only if a row is being deleted);
  • AFTER DELETE (only if a row is being deleted);
  • AFTER INSERT.

The INSERT ... ON DUPLICATE KEY UPDATE statement, when a row already exists, follows the following workflow: INSERT ... ON DUPLICATE KEY UPDATE문은 삽입하려는 행이 이미 존재하는 경우 아래의 흐름으로 실행됩니다.

  • BEFORE INSERT;
  • BEFORE UPDATE;
  • AFTER UPDATE.

Otherwise, it works like a normal INSERT statement. 그렇지 않은 경우 일반적인 INSERT문과 동일하게 처리됩니다.

Note that TRUNCATE TABLE does not activate any triggers. TRUNCATE TABLE문은 어떤 트리거도 실행시키지 않습니다.

트리거와 오류

With non-transactional storage engines, if a BEFORE statement produces an error, the statement will not be executed. Statements that affect multiple rows will fail before inserting the current row. 트랜잭션을 지원하지 않는 스토리지 엔진에서는, BEFORE 문에서 오류가 발생하면 해당 구문은 실행되지 않습니다. 트리거가 여러 행에 영향을 미치는 경우에는 현재 행을 삽입하기 전에 실패합니다.

With transactional engines, triggers are executed in the same transaction as the statement that invoked them. 트랜잭션을 지원하는 엔진에서는, 트리거는 해당 트리거를 발생시킨 구문과 동일한 트랜잭션에서 실행됩니다.

If a warning is issued with the SIGNAL or RESIGNAL statement (that is, an error with an SQLSTATE starting with '01'), it will be treated like an error. SIGNAL 또는 RESIGNAL문과 함께 경고가 발생한다면 ( 즉, SQLSTATE가 '01'로 시작하는 오류가 있는 경우) 이는 오류로 취급됩니다.

트리거 생성

Here's a simple example to demonstrate a trigger in action. Using these two tables as an example: 실제 트리거에 대하 ㄴc>> A trigger, as its name suggests, is a set of statements that run, or are triggered, when an event occurs on a table. 이름에서 알 수 있듯이, 트리거는 테이블에 이벤트가 발생할때 실행되는(또는 '트리거'되는) 명령문의 세트입니다.

이벤트

The event can be an INSERT, an UPDATE or a DELETE. The trigger can be executed BEFORE or AFTER the event. Until MariaDB 10.2.3, a table could have only one trigger defined for each event/timing combination: for example, a table could only have one BEFORE INSERT trigger. 이벤트는 INSERT, UPDATE 또는 DELETE일 수 있습니다. 트리거는 이벤트 시작 전 또는 발생 후에 실행될 수 있습니다. MariaDB 10.2.3까지는 하나의 테이블은 하나의 이벤트/타이밍 조합에 대해 오직 한 가지 트리거만을 정의할 수 있었습니다. 예를 들어, 테이블은 (INSERT 시작 전에 수행되는)BEFORE INSERT 트리거를 단 하나만 가집니다.

The LOAD DATA INFILE and LOAD XML statements invoke INSERT triggers for each row that is being inserted. LOAD DATA INFILELOAD XML문은 삽입되는 데이터 한 행 마다 INSERT 트리거를 발생시킵니다.

The REPLACE statement is executed with the following workflow: REPLACE문은 아래와 같은 흐름으로 실행됩니다

  • BEFORE INSERT;
  • BEFORE DELETE (only if a row is being deleted);
  • AFTER DELETE (only if a row is being deleted);
  • AFTER INSERT.

The INSERT ... ON DUPLICATE KEY UPDATE statement, when a row already exists, follows the following workflow: INSERT ... ON DUPLICATE KEY UPDATE문은 삽입하려는 행이 이미 존재하는 경우 아래의 흐름으로 실행됩니다.

  • BEFORE INSERT;
  • BEFORE UPDATE;
  • AFTER UPDATE.

Otherwise, it works like a normal INSERT statement. 그렇지 않은 경우 일반적인 INSERT문과 동일하게 처리됩니다.

Note that TRUNCATE TABLE does not activate any triggers. TRUNCATE TABLE문은 어떤 트리거도 실행시키지 않습니다.

트리거와 오류

With non-transactional storage engines, if a BEFORE statement produces an error, the statement will not be executed. Statements that affect multiple rows will fail before inserting the current row. 트랜잭션을 지원하지 않는 스토리지 엔진에서는, BEFORE 문에서 오류가 발생하면 해당 구문은 실행되지 않습니다. 트리거가 여러 행에 영향을 미치는 경우에는 현재 행을 삽입하기 전에 실패합니다.

With transactional engines, triggers are executed in the same transaction as the statement that invoked them. 트랜잭션을 지원하는 엔진에서는, 트리거는 해당 트리거를 발생시킨 구문과 동일한 트랜잭션에서 실행됩니다.

If a warning is issued with the SIGNAL or RESIGNAL statement (that is, an error with an SQLSTATE starting with '01'), it will be treated like an error. SIGNAL 또는 RESIGNAL문과 함께 경고가 발생한다면 ( 즉, SQLSTATE가 '01'로 시작하는 오류가 있는 경우) 이는 오류로 취급됩니다.

트리거 생성

Here's a simple example to demonstrate a trigger in action. Using these two tables as an example: 다음은 실제 트리거에 대해 설명하는 간단한 예제입니다. 아래의 두 테이블을 예시로 사용합니다:

CREATE TABLE animals (id mediumint(9) 
NOT NULL AUTO_INCREMENT, 
name char(30) NOT NULL, 
PRIMARY KEY (`id`));

CREATE TABLE animal_count (animals int);

INSERT INTO animal_count (animals) VALUES(0);

We want to increment a counter each time a new animal is added. Here's what the trigger will look like: 새 동물이 추가될 때 마다 카운터 값을 증가시키고 싶다고 합시다. 트리거는 아래와 같을 것입니다:

CREATE TRIGGER increment_animal 
AFTER INSERT ON animals 
FOR EACH ROW 
UPDATE animal_count SET animal_count.animals = animal_count.animals+1;

The trigger has: 이 트리거는 아래의 요소를 가집니다:

  • 이름 (이 경우에는 increment_animal)
  • 트리거 시점( 이 경우에는 특정 이벤트 이후(after))
  • 트리거 이벤트 (INSERT)
  • 연관된 테이블 (animals)
  • 실행할 SQL문 (이 경우에는 단순한 UPDATE문)

AFTER INSERT specifies that the trigger will run after an INSERT. The trigger could also be set to run before, and the statement causing the trigger could be a DELETE or an UPDATE as well. AFTER INSERT는 이 트리거가 INSERT이후(after)에 수행됨을 나타냅니다. 트리거는 이전(before)에 수행되도록 설정될 수도 있고, 트리거를 실행시키는 구문을 AFTER INSERT뿐만 아니라 DELETE 또는 UPDATE로 설정할 수도 있습니다.

Now, if we insert a record into the animals table, the trigger will run, incrementing the animal_count table; 이제 우리가 animals테이블에 데이터를 입력할 경우 이 트리거가 실행되어 animal_count 테이블을 증가시킵니다.

SELECT * FROM animal_count;
+---------+
| animals |
+---------+
|       0 |
+---------+

INSERT INTO animals (name) VALUES('aardvark');
INSERT INTO animals (name) VALUES('baboon');

SELECT * FROM animal_count;
+---------+
| animals |
+---------+
|       2 |
+---------+

For more details on the syntax, see CREATE TRIGGER. 문법에 대한 자세한 설명은 CREATE TRIGGER를 참조하세요.

트리거 제거

To drop a trigger, use the DROP TRIGGER statement. Triggers are also dropped if the table with which they are associated is also dropped. 트리거를 제거하기 위해서는 DROP TRIGGER문을 사용하세요. 또한 트리거는 연관된 테이블이 삭제되는 경우에도 함게 삭제됩니다.

 DROP TRIGGER increment_animal; 

트리거 메타데이터

The Information Schema TRIGGERS Table stores information about triggers. Information Schema TRIGGERS 테이블은 트리거에 대한 정보를 저장합니다.

The SHOW TRIGGERS statement returns similar information. SHOW TRIGGERS문은 유사한 정보를 반환합니다.

The SHOW CREATE TRIGGER statement returns a CREATE TRIGGER statement that creates the given trigger. SHOW CREATE TRIGGER문은 해당 트리거를 생성한 CREATE TRIGGER문을 반환합니다.

더 복잡한 트리거

Triggers can consist of multiple statements enclosed by a BEGIN and END. If you're entering multiple statements on the command line, you'll want to temporarily set a new delimiter so that you can use a semicolon to delimit the statements inside your trigger. See Delimiters in the mysql client for more. 트리거는

DROP TABLE animals;

UPDATE animal_count SET animals=0;

CREATE TABLE animals (id mediumint(9) NOT NULL AUTO_INCREMENT, 
name char(30) NOT NULL, 
PRIMARY KEY (`id`)) 
ENGINE=InnoDB;

DELIMITER //
CREATE TRIGGER the_mooses_are_loose
AFTER INSERT ON animals
FOR EACH ROW
BEGIN
 IF NEW.name = 'Moose' THEN
  UPDATE animal_count SET animal_count.animals = animal_count.animals+100;
 ELSE 
  UPDATE animal_count SET animal_count.animals = animal_count.animals+1;
 END IF;
END; //

DELIMITER ;

INSERT INTO animals (name) VALUES('Aardvark');

SELECT * FROM animal_count;
+---------+
| animals |
+---------+
|       1 |
+---------+

INSERT INTO animals (name) VALUES('Moose');

SELECT * FROM animal_count;
+---------+
| animals |
+---------+
|     101 |
+---------+

트리거 오류

If a trigger contains an error and the engine is transactional, or it is a BEFORE trigger, the trigger will not run, and will prevent the original statement from running as well. If the engine is non-transactional, and it is an AFTER trigger, the trigger will not run, but the original statement will. 트리거에 오류가 있고, 엔진이 트랜잭션을 지원하거나 또는 트리거가 BEFORE 트리거이면, 그 트리거는 실행되지 않으며 동시에 트리거를 발생시킨 원문 SQL문도 실행되지 않도록 막습니다. 엔진이 트랜잭션을 지원하지 않고 트리거가 AFTER 트리거이면, 트리거는 실행되지 않지만 원문 SQL문은 수행됩니다.

Here, we'll drop the above examples, and then recreate the trigger with an error, a field that doesn't exist, first using the default InnoDB, a transactional engine, and then again using MyISAM, a non-transactional engine. 여기서는 위의 예제를 삭제하고, 존재하지 않는 필드명을 포함하는 오류가 있는 트리거를 만들어 봅니다. 처음에는 트랜잭션을 지원하는 기본 엔진인InnoDB를 사용하고, 그리고 다시 트랜잭션을 지원하지 않는 MyISAM을 사용해 봅니다.

DROP TABLE animals;

CREATE TABLE animals (id mediumint(9) NOT NULL AUTO_INCREMENT, 
name char(30) NOT NULL, 
PRIMARY KEY (`id`)) 
ENGINE=InnoDB;

CREATE TRIGGER increment_animal 
AFTER INSERT ON animals 
FOR EACH ROW 
UPDATE animal_count SET animal_count.id = animal_count_id+1;

INSERT INTO animals (name) VALUES('aardvark');
ERROR 1054 (42S22): Unknown column 'animal_count.id' in 'field list'

SELECT * FROM animals;
Empty set (0.00 sec)

And now the identical procedure, but with a MyISAM table. MyISAM 테이블에 대해서 동일한 프로시저를 살펴보면 아래와 같습니다.

DROP TABLE animals;

CREATE TABLE animals (id mediumint(9) NOT NULL AUTO_INCREMENT, 
name char(30) NOT NULL, 
PRIMARY KEY (`id`)) 
ENGINE=MyISAM;

CREATE TRIGGER increment_animal 
AFTER INSERT ON animals 
FOR EACH ROW 
UPDATE animal_count SET animal_count.id = animal_count_id+1;

INSERT INTO animals (name) VALUES('aardvark');
ERROR 1054 (42S22): Unknown column 'animal_count.id' in 'field list'

SELECT * FROM animals;
+----+----------+
| id | name     |
+----+----------+
|  1 | aardvark |
+----+----------+

The following example shows how to use a trigger to validate data. The SIGNAL statement is used to intentionally produce an error if the email field is not a valid email. As the example shows, in that case the new row is not inserted (because it is a BEFORE trigger). 다음 예시는 트리거를 사용해 데이터를 검증하는 방법을 보여줍니다. SIGNAL문은 email 필드가 유효한 email이 아닌 경우 의도적으로 오류를 발생시킵니다. 예시가 보여주듯이 새로운 행은 삽입되지 않습니다.(BEFORE 트리거가 실패했기 때문입니다.)

CREATE TABLE user (
	id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	first_name CHAR(20),
	last_name CHAR(20),
	email CHAR(100)
)
	ENGINE = MyISAM;

DELIMITER //
CREATE TRIGGER bi_user
  BEFORE INSERT ON user
  FOR EACH ROW
BEGIN
  IF NEW.email NOT LIKE '_%@_%.__%' THEN
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Email field is not valid';
  END IF;
END; //
DELIMITER ;

INSERT INTO user (first_name, last_name, email) VALUES ('John', 'Doe', 'john_doe.example.net');
ERROR 1644 (45000): Email field is not valid

SELECT * FROM user;
Empty set (0.00 sec)

관련 자료

Comments

Comments loading...
Content reproduced on this site is the property of its respective owners, and this content is not reviewed in advance by MariaDB. The views, information and opinions expressed by this content do not necessarily represent those of MariaDB or any other party.