문제

청소에 이 답변 나는 조금 배웠다 TRIGGERS와 MySQL에 저장된 절차, 그러나 기절했지만 BEFORE INSERT 그리고 BEFORE UPDATE 트리거는 데이터를 수정할 수 있으며 삽입/업데이트가 실패 할 수없는 것 같습니다 (예 : 검증). 이 특별한 경우에 나는 기본 키 복제본을 유발하는 방식으로 데이터를 조작 하여이 작업을 수행 할 수 있었는데,이 경우에는 의미가 있었지만 반드시 일반적으로 의미가 없습니다.

MySQL에서 이런 종류의 기능이 가능합니까? 다른 RDBMS에서 (내 경험은 슬프게도 MySQL로 제한됨)? 아마도 a THROW EXCEPTION 스타일 구문?

도움이 되었습니까?

해결책

이것으로부터 블로그 게시물

MySQL 트리거 : 트리거로 삽입, 업데이트 또는 삭제를 어떻게 중단합니까? efnet의 #mysql에서 누군가가 물었습니다.

비즈니스 규칙이 실패하면 트리거가 작업을 중단시키는 방법은 무엇입니까?

MySQL 5.0 및 5.1에서는 트리거를 실패하고 의미있는 오류 메시지를 전달하기 위해 속임수에 의지해야합니다. MySQL 저장 프로 시저 FAQ는 오류 처리에 대해 다음과 같이 말합니다.

SP 11. SPS는 "응용 프로그램 오류를 높이는" "Rain"명령문이 있습니까? 죄송합니다. 현재는 아닙니다. SQL 표준 신호 및 사임 명세서는 TODO에 있습니다.

아마도 MySQL 5.2에는 MySQL 저장 프로 시저 에서이 해킹을 쓸모 없게하는 신호 명령문이 포함되어있을 것입니다. 해킹은 무엇입니까? MySQL이 존재하지 않는 열을 사용하도록 강요 할 것입니다. 못생긴? 예. 작동합니까? 확신하는.

CREATE TRIGGER mytabletriggerexample
BEFORE INSERT
FOR EACH ROW BEGIN
IF(NEW.important_value) < (fancy * dancy * calculation) THEN
    DECLARE dummy INT;

    SELECT Your meaningful error message goes here INTO dummy 
        FROM mytable
      WHERE mytable.id=new.id
END IF; END;

다른 팁

여기 내가 한 방식이 있습니다. 참고 SET NEW='some error';. MySQL은 "variable 'new'가 '오류 :이 항목을 삭제할 수 없음으로 설정할 수 없습니다.이 항목과 함께 판매 테이블에 레코드가 있습니다."

코드에 이것을 덫을 놓은 다음 결과 오류를 표시 할 수 있습니다 :)

DELIMITER $$
DROP TRIGGER IF EXISTS before_tblinventoryexceptionreasons_delete $$
CREATE TRIGGER before_tblinventoryexceptionreasons_delete
BEFORE DELETE ON tblinventoryexceptionreasons
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblinventoryexceptionreasons = old.idtblinventoryexceptionreasons) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory exception reasons table with this item.';
  END IF;
END$$
DELIMITER ;

DELIMITER $$
DROP TRIGGER IF EXISTS before_storesalesconfig_delete $$
CREATE TRIGGER before_storesalesconfig_delete
BEFORE DELETE ON tblstoresalesconfig
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblstoresales WHERE tblstoresales.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the sales table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinventory WHERE tblinventory.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory exceptions table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.';
  END IF;
END$$
DELIMITER ;

DELIMITER $$
DROP TRIGGER IF EXISTS before_tblinvoice_delete $$
CREATE TRIGGER before_tblinvoice_delete
BEFORE DELETE ON tblinvoice
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblinvoice = old.idtblinvoice) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.';
  END IF;
END$$
DELIMITER ;

MySQL 트리거에서 오류 처리를 검색 할 때이 기사가 맨 위로 올라 오기 때문에 지식을 공유 할 것이라고 생각했습니다.

오류가 있으면 MySQL을 사용하도록 강요 할 수 있습니다. 신호, 그러나 당신이 그것을 sqlexception으로 클래스로 지정하지 않으면, 모든 sqlstates가 나쁜 것으로 간주되는 것은 아니기 때문에 아무 일도 일어나지 않을 것입니다. 사임 중첩 된 시작/끝 블록이있는 경우.

대안 적으로, 아마도 방아쇠 내에서 종료 핸들러를 선언하고 예외를 사임합니다.

CREATE TRIGGER `my_table_AINS` AFTER INSERT ON `my_table` FOR EACH ROW
BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
        RESIGNAL;
    DECLARE EXIT HANDLER FOR SQLWARNING
        RESIGNAL;
    DECLARE EXIT HANDLER FOR NOT FOUND
        RESIGNAL; 
    -- Do the work of the trigger.
END

그리고 몸에 오류가 발생하면 상단으로 다시 던져 오류가 발생합니다. 이것은 저장된 절차와 그 내용에도 사용할 수 있습니다.

이것은 버전 5.5+와 함께 작동합니다.

이것은 예외를 올림으로써 삽입을 중단합니다 ( http://www.experts-exchange.com/database/mysql/q_23788965.html)

DROP PROCEDURE IF EXISTS `MyRaiseError`$$

CREATE PROCEDURE `MyRaiseError`(msg VARCHAR(62))
BEGIN
DECLARE Tmsg VARCHAR(80);
SET Tmsg = msg;
IF (CHAR_LENGTH(TRIM(Tmsg)) = 0 OR Tmsg IS NULL) THEN
SET Tmsg = 'ERROR GENERADO';
END IF;
SET Tmsg = CONCAT('@@MyError', Tmsg, '@@MyError');
SET @MyError = CONCAT('INSERT INTO', Tmsg);
PREPARE stmt FROM @MyError;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$

용법:

call MyRaiseError('Here error message!');

트리거에서 작동하지 않습니다 (동적 SQL은 저장된 기능 또는 트리거에서 허용되지 않습니다)

나는 매우 더러운 솔루션을 사용합니다.

If NEW.test=1 then CALL TEST_CANNOT_BE_SET_TO_1; end if;

test = 1 MySQL이 다음과 같은 예외를 던지면 다음과 같습니다.

프로 시저 administratie.test_cannot_be_set_to_1은 존재하지 않습니다

정교하지는 않지만 빠르고 유용합니다.

MS SQL에서는 적절한 구문을 사용하여 작동하게 할 수 있습니다.

IF UPDATE(column_name)
BEGIN
  RAISEERROR
  ROLLBACK TRAN
  RETURN
END

http://msdn.microsoft.com/en-us/magazine/cc164047.aspx

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top