2012-03-12 3 views
5

트리거 및 제약 조건을 연구 중입니다.제한 조건에 트리거를 사용하는 SQL

내가 트리거를 사용하는 질문이 있어요 (I가 트리거를 사용하는 방법을 정말 확실하지 않다, 정직하게하려면 ..)

이의 우리가 교사 테이블이 있다고 가정 해 봅시다.

그리고이 교사 테이블은 예를 들어

,

|teacher_id|ssn | first_name | last_name | student_number| max_student 
|1   |1234 | bob  | Smith  | 25   |25 
|2   |1235 | kim  | Johnson | 24   |21 
|3   |1236 | kally  | Jones  | 23   |22 

가의 학생 수의 최대 수는 25이됩니다 가정 해 봅시다 teacher_id, 사회 보장 번호 (SSN), FIRST_NAME, LAST_NAME, class_time을 포함 (최대 학생 수는 교사가 정의하므로 10, 22, 25 ...와 같은 숫자가 될 수 있습니다.)

학생은 밥의 clas를 추가하려고합니다. 에스. 그러나, 나는 학생을 추가하는 것을 거부하는 방아쇠를 만들고 싶습니다. (왜냐하면 밥의 클래스는 이미 가득 찼기 때문입니다.)

그러나 실제로 트리거를 만드는 방법은 확실하지 않습니다.

사람의 도움 트리거 부분을 이해하는 샘플 코드를 만들 수 있습니까?

+2

트리거는 데이터베이스와 관련된 경향이 있으므로 관심있는 데이터베이스를 추가해야합니다. –

+0

StackOverflow에 오신 것을 환영합니다. 코드, XML 또는 데이터 샘플을 게시하는 경우 ** 텍스트 편집기에서 해당 행을 강조 표시하고 편집기 툴바에서 "코드 샘플"버튼 ('{})을 클릭하십시오. 구문 강조! 지저분한' 'orgies와'
' 태그는 필요하지 않습니다. –

+1

이것은 비즈니스 규칙으로, 데이터베이스의 트리거 또는 제약 조건이 아닌 응용 프로그램 소프트웨어에서 구현할 것으로 예상됩니다. 데이터베이스 제약 조건 및 트리거는 일반적으로 참조 무결성을 적용합니다 (즉, 내부적으로 데이터를 일관되게 유지합니다). 클래스가 25를 넘지 않도록하는 것은 아마도 백스톱 일지 모르지만 앱은 실제로 처음부터 시도를 중지해야합니다. –

답변

10

첫째, 나는이 데이터 규칙이므로 중앙 집행해야한다고 생각) ... 트리거에 대해 공부하는 것은 이번이 처음이다. 즉, 모든 응용 프로그램이 불량 데이터를 쓰지 못하게하는 DBMS에 의해 시행되는 데이터베이스 제약 조건 (또는 이에 상응하는 것)이 있어야합니다. 각 응용 프로그램의 개별 코더에 의존하여 불량 데이터를 쓰지 않도록하십시오.

둘째, AFTER 트리거가 적절하다고 생각합니다 (INSTEAD OF 트리거가 아닌).

셋째, 외래 키 및 행 수준 CHECK 제약 조건을 사용하여 강제 적용 할 수 있습니다.

제한 유형 트리거의 경우 아이디어는 일반적으로 트리거 테스트에서이 결과가 비어있는 잘못된 데이터를 반환하는 쿼리를 작성하는 것입니다.

내가 추측 할 수 있도록 테이블의 세부 정보를 많이 게시하지 않았습니다. 나는 student_number이 학생들의 수를 의미한다고 가정합니다; 이 식별자 같은 소리 그대로 그래서 이름을 변경하고 학생들의 식별자를 가정 할 것이다 것은 student_id입니다 :

CREATE TRIGGER student_tally_too_high ON Enrolment 
AFTER INSERT, UPDATE 
AS 
IF EXISTS (
      SELECT * 
      FROM Teachers AS T 
        INNER JOIN (
           SELECT teacher_id, COUNT(*) AS students_tally 
           FROM Enrolment 
           GROUP 
            BY teacher_id  
          ) AS E 
            ON T.teacher_id = E.teacher_id 
            AND E.students_tally > T.students_tally 
     ) 
BEGIN 
RAISERROR ('A teachers''s student tally is too high to accept new students.', 16, 1); 
ROLLBACK TRANSACTION; 
RETURN 
END; 

: SQL 서버에서

WITH EnrolmentTallies 
    AS 
    (
     SELECT teacher_id, COUNT(*) AS students_tally 
     FROM Enrolment 
     GROUP 
      BY teacher_id  
    ) 
SELECT * 
    FROM Teachers AS T 
     INNER JOIN EnrolmentTallies AS E 
     ON T.teacher_id = E.teacher_id 
      AND E.students_tally > T.students_tally; 

는 트리거 정의는 다음과 같을 것 그러나 몇 가지 추가 고려 사항이 있습니다. 테이블에 대해 UPDATE마다 이러한 쿼리를 실행하는 것은 매우 비효율적 일 수 있습니다. 열의 순서를 신뢰할 수 있다고 생각하면 UPDATE() (또는 COLUMNS_UPDATED)을 사용하거나 deletedinserted 개념 테이블을 사용하여 쿼리의 범위와 실행시기를 제한해야합니다. 동시 처리 문제를 방지하려면 트랜잭션을 적절하게 직렬화해야합니다. 관련되어 있지만, 그다지 복잡하지는 않습니다.

Applied Mathematics for Database Professionals  By Lex de Haan, Toon Koppelaars, 11 장 (코드 예제는 Oracle이지만 쉽게 SQL Server에 이식 할 수 있음)을 적극 권장합니다.


트리거 없이도 동일한 결과를 얻을 수 있습니다. 이 아이디어는 (teacher_id, students_tally)에있는 수퍼 키를 등록에서 참조하도록 지정하는 것입니다. 시퀀스는 고유 한 학생 발생 순서가 유지되고 시퀀스가 ​​최대 집계를 초과하지 않을 것이라는 테스트와 함께 유지됩니다.

CREATE TABLE Students 
(
student_id INTEGER NOT NULL, 
UNIQUE (student_id) 
); 

CREATE TABLE Teachers 
(
teacher_id INTEGER NOT NULL, 
students_tally INTEGER NOT NULL CHECK (students_tally > 0), 
UNIQUE (teacher_id), 
UNIQUE (teacher_id, students_tally) 
); 

CREATE TABLE Enrolment 
(
teacher_id INTEGER NOT NULL UNIQUE, 
students_tally INTEGER NOT NULL CHECK (students_tally > 0), 
FOREIGN KEY (teacher_id, students_tally) 
    REFERENCES Teachers (teacher_id, students_tally) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE, 
student_id INTEGER NOT NULL UNIQUE 
    REFERENCES Students (student_id), 
student_teacher_sequence INTEGER NOT NULL 
    CHECK (student_teacher_sequence BETWEEN 1 AND students_tally) 
UNIQUE (teacher_id, student_id), 
UNIQUE (teacher_id, student_id, student_teacher_sequence) 
); 

그런 다음 프록/기능 업데이트에 대한 순서를 유지하기 위해 저장된 일부 'help'를 추가

는 여기에 몇 가지 베어 뼈 SQL의 DDL입니다.

+0

죄송합니다. 테이블에서 max_student를 넣는 것을 잊지 마십시오. 학생들이 수업 등록을 원할 때 등록 제한을 확인할 수있는 TRIGGER를 만들기 위해 공부하고 있습니다. 예를 들어 max_student == student_number 인 경우 학생은 수업을 추가 할 수 없습니다. 어쨌든, 정말 TRIGGER를 이해하는 데 도움이됩니다. 감사 :) –

관련 문제