MySQL - 업데이트 전 트리거

MySQL 업데이트 전 트리거 소개

안녕하세요, 데이터베이스 열정가 여러분! 오늘은 MySQL의 흥미로운 세계, 업데이트 전 트리거에 대해 다룰 것입니다. 프로그래밍에 새로운 사람이라면 걱정 마세요; 이 여정에서 친절한 안내자로서 모든 것을 단계별로 설명해 드리겠습니다. 이 튜토리얼이 끝나면, 프로처럼 트리거를 만드는 법을 배울 것입니다!

MySQL - Before Update Trigger

업데이트 전 트리거란?

고급 예술 전시장에서 경비원으로 일하는 상상해 보세요. 사람들이 전시실에 들어가기 전에 가방을 검사하는 일이 있습니다. 그게 exactamente MySQL의 업데이트 전 트리거가 하는 일입니다! 데이터베이스의 개인 경비원처럼, 기록이 업데이트되기 직전에 모든 것이 적절한지 확인하는 특별한 프로그램입니다.

MySQL 업데이트 전 트리거 문법

아래는 업데이트 전 트리거의 기본 구조입니다. 처음에는 조금 두려울 수 있지만, 함께 풀어보겠습니다!

CREATE TRIGGER trigger_name
BEFORE UPDATE ON table_name
FOR EACH ROW
BEGIN
-- 트리거 코드는 여기에 작성합니다
END;

이 마법의 문구를 해독해 보겠습니다:

  1. CREATE TRIGGER trigger_name: 트리거에 이름을 지정합니다. 지혜롭게 선택하세요!
  2. BEFORE UPDATE: 업데이트가 발생하기 전에 트리거를 실행하도록 합니다.
  3. ON table_name: 보호하고 싶은 테이블을 지정합니다.
  4. FOR EACH ROW: 트리거가 업데이트되는 각 행에 대해 실행됩니다.
  5. BEGINEND: 트리거의 실제 코드를 감싸는 키워드입니다.

간단한 예제

사람이 직원의 급여를 변경하려고 시도할 때 로그를 남기는 간단한 트리거를 만들어 보겠습니다. employees 테이블을 사용하고, salary_changes 로그 테이블을 생성합니다.

-- 먼저 테이블을 생성해 보겠습니다
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(50),
salary DECIMAL(10, 2)
);

CREATE TABLE salary_changes (
id INT AUTO_INCREMENT PRIMARY KEY,
employee_id INT,
old_salary DECIMAL(10, 2),
new_salary DECIMAL(10, 2),
change_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 이제 트리거를 생성해 보겠습니다
DELIMITER //
CREATE TRIGGER before_salary_update
BEFORE UPDATE ON employees
FOR EACH ROW
BEGIN
IF OLD.salary != NEW.salary THEN
INSERT INTO salary_changes (employee_id, old_salary, new_salary)
VALUES (OLD.id, OLD.salary, NEW.salary);
END IF;
END;//
DELIMITER ;

이를 해독해 보겠습니다:

  1. 두 개의 테이블을 생성합니다: employees는 직원 정보를 저장하고, salary_changes는 급여 업데이트를 로그합니다.
  2. 트리거 이름은 before_salary_update입니다.
  3. 트리거 내부에서 급여가 실제로 변경되는지 확인합니다 (IF OLD.salary != NEW.salary).
  4. 급여가 변경되면 salary_changes 테이블에 새로운 레코드를 추가합니다.
  5. OLD은 현재 값을 가리키고, NEW은 설정될 새로운 값을 가리킵니다.

클라이언트 프로그램을 사용한 업데이트 전 트리거

이제 실제 세계에서 트리거를 어떻게 사용할 수 있는지 보겠습니다. 소型企业의 급여 시스템을 개발 중이라고 가정해 봅시다. 모든 급여 변경 사항을 감사 목적으로 적절히 로그하려고 합니다.

다음은 MySQL 데이터베이스에 연결하고 직원의 급여를 업데이트하는 간단한 Python 스크립트입니다:

import mysql.connector

# 데이터베이스에 연결합니다
db = mysql.connector.connect(
host="localhost",
user="your_username",
password="your_password",
database="your_database"
)

cursor = db.cursor()

# 직원 급여 업데이트 함수
def update_salary(employee_id, new_salary):
sql = "UPDATE employees SET salary = %s WHERE id = %s"
values = (new_salary, employee_id)
cursor.execute(sql, values)
db.commit()
print(f"직원 {employee_id}의 급여가 업데이트되었습니다")

# 직원의 급여를 업데이트해 보겠습니다
update_salary(1, 55000)

# 연결을 닫습니다
db.close()

이 스크립트를 실행할 때:

  1. MySQL 데이터베이스에 연결합니다.
  2. update_salary 함수는 주어진 직원의 급여를 업데이트합니다.
  3. UPDATE 문이 실행될 때 before_salary_update 트리거가 자동으로 발생합니다.
  4. 트리거는 급여가 변경되는지 확인하고 salary_changes 테이블에 로그를 남깁니다.
  5. 이 모든 것이 employees 테이블에 실제 업데이트가 적용되기 전에 일어납니다.

트리거 작업 확인

스크립트를 실행한 후, 트리거가 작동한지 확인하기 위해 salary_changes 테이블을 쿼리합니다:

SELECT * FROM salary_changes;

직원 1의 이전과 새로운 급여가 새로운 항목으로 표시되어야 합니다.

고급 트리거 기술

기본적인 내용을 이해했으므로, 업데이트 전 트리거에서 사용할 수 있는 몇 가지 고급 기술을 살펴보겠습니다.

데이터 검증

트리거를 사용하여 비즈니스 규칙을 강제할 수 있습니다. 예를 들어, 급여 인하를 허용하지 않고 싶다면:

DELIMITER //
CREATE TRIGGER prevent_salary_decrease
BEFORE UPDATE ON employees
FOR EACH ROW
BEGIN
IF NEW.salary < OLD.salary THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '급여는 인하될 수 없습니다';
END IF;
END;//
DELIMITER ;

이 트리거는 누군가가 직원의 급여를 줄이려고 시도할 때 오류를 발생시킵니다.

NEW 값을 변경

트리거를 사용하여 업데이트되기 전에 데이터를 변경할 수도 있습니다:

DELIMITER //
CREATE TRIGGER round_salary
BEFORE UPDATE ON employees
FOR EACH ROW
BEGIN
SET NEW.salary = ROUND(NEW.salary, -3);
END;//
DELIMITER ;

이 트리거는 새로운 급여를 천 단위로 반올림합니다.

최선의 관행과 고려 사항

  1. 트리거를 간단하게 유지: 복잡한 논리는 디버깅을 어렵게 만듭니다.
  2. 성능에 주의: 트리거는 영향을 받는 각 행에 대해 실행되므로, 큰 테이블에서는 속도를 저하시킬 수 있습니다.
  3. 무한 루프를 피하: 자신을 다시 트리거할 수 있는 트리거를 만들지 마세요.
  4. 트리거를 문서화: 트리거 코드를 주석 달고, 트리거가 무엇을 하는지에 대한 문서를 유지하세요.

결론

축하합니다! MySQL의 업데이트 전 트리거 세계에 첫 걸음을 뗀 것입니다. 이 강력한 도구는 데이터베이스 연산에 추가적인 제어와 자동화를 제공합니다. 대단한 힘을 가지는 만큼, 책임감 있게 사용해야 합니다!

데이터베이스 여정을 계속하면서, 트리거를 사용하여 실제 문제를 해결할 수 있는 무수한 창의적인 방법을 찾을 것입니다. 연습을 계속하고, 호기심을 유지하며, 실험을 두려워하지 마세요. 누가 알겠는가? 당신은 팀에서 다음 데이터베이스 마법사가 될 수도 있습니다!

기쁜 트리거 작업을 하고, 쿼리가 항상 기대하는 결과를 반환하길 바랍니다!

Credits: Image by storyset