programing

트리거 최적화

bestprogram 2023. 9. 9. 09:46

트리거 최적화

이 트리거를 최적화하려면 어떻게 해야 합니까?완벽하게 작동하지만 개선할 수 있다고 생각합니다.

CREATE TRIGGER `update_request_missions_after_insert` BEFORE INSERT ON `request_missions`
 FOR EACH ROW
IF ((SELECT id FROM request_missions ORDER BY id DESC LIMIT 1)+1) >= 1  AND 
   ((SELECT id FROM request_missions ORDER BY id DESC LIMIT 1)+1) <= 9 THEN
        SET New.rm_number = CONCAT(DATE_FORMAT(CURDATE(),'%y'), '-',
            CONCAT('00000',(SELECT id FROM request_missions ORDER BY id DESC LIMIT 1)+1));
    END IF

결과는 다음과 같습니다.rm_number열, 다음과 같습니다.

id >=1 및 id <= 9의 경우

19-000001
19-000002
...
19-000009

감사합니다 빌 카윈 코드는 이제 더 깨끗해졌습니다. 올해의 문제를 '%Y'로 바꿨습니다. 코드는 지금:

CREATE TRIGGER `update_request_missions_after_insert` BEFORE INSERT ON `request_missions`
FOR EACH ROW
BEGIN
  DECLARE next_id INT;
  SELECT COALESCE(MAX(id),0) + 1 INTO next_id FROM request_missions;
  IF next_id BETWEEN 1 AND 9 THEN
    SET NEW.rm_number = CONCAT(DATE_FORMAT(CURDATE(),'%Y'), '-', '00000', next_id);
  ELSEIF next_id BETWEEN 10 AND 99 THEN
    SET NEW.rm_number = CONCAT(DATE_FORMAT(CURDATE(),'%Y'), '-', '0000', next_id);
  ELSEIF next_id BETWEEN 100 AND 999 THEN
    SET NEW.rm_number = CONCAT(DATE_FORMAT(CURDATE(),'%Y'), '-', '000', next_id);
  ELSEIF next_id BETWEEN 1000 AND 9999 THEN
    SET NEW.rm_number = CONCAT(DATE_FORMAT(CURDATE(),'%Y'), '-', '00', next_id);
  ELSEIF next_id BETWEEN 10000 AND 99999 THEN
    SET NEW.rm_number = CONCAT(DATE_FORMAT(CURDATE(),'%Y'), '-', '0', next_id);
  ELSEIF next_id BETWEEN 100000 AND 999999 THEN
    SET NEW.rm_number = CONCAT(DATE_FORMAT(CURDATE(),'%Y'), '-', next_id);
  END IF;
END

경고: 레이스 상태로 인해 어려움을 겪습니다.예를 들어 두 세션이 동시에 테이블에 삽입되는 경우 둘 다 동일한 next_id를 읽을 수 있습니다.

이 트리거의 목적이 추가되는 각 라인에 대해 'YYYY-ID' 형식의 숫자를 추가하는 것임을 알고 이 문제에 대한 해결책이 있습니까?YYYY:는 현재 Year ID :는 트리거에 표시된 것과 같이 형식화된 현재 행의 ID입니다.

하위 쿼리를 세 번 반복하는 대신 로컬 변수를 사용하는 방법을 제안합니다.그게 당신의 관심사라고 했잖아요.

CREATE TRIGGER `update_request_missions_after_insert` BEFORE INSERT ON `request_missions`
FOR EACH ROW
BEGIN
  DECLARE next_id INT;
  SELECT COALESCE(MAX(id),0) + 1 INTO next_id FROM request_missions;
  IF next_id BETWEEN 1 AND 9 THEN
    SET NEW.rm_number = CONCAT(DATE_FORMAT(CURDATE(),'%y'), '-', '00000', next_id);
  END IF;
END

경고: 레이스 상태로 인해 어려움을 겪습니다.예를 들어, 두 세션이 동시에 테이블에 삽입되는 경우 둘 다 동일한 세션을 읽을 수 있습니다.next_id.

역시 @P.위에 언급된 연어, 결과는 다음과 같이 정의되지 않습니다.next_id는 > 9 입니다.당신이 뭘 하려는 건지 모르겠어요.

더 긴 숫자를 허용하고 0으로 고정된 길이로 패드를 부착할 수 있습니다.

LPAD(next_id, 6, '0')

LPAD() 기능에 대한 설명서를 참조합니다.

사용했습니다.COALESCE(MAX(id),0)테이블에 행이 0개인 경우 NULL이 아닌 값이 하나 이상 반환되는지 확인합니다.

이는 또한 다음과 관련된 사항입니다.

DATE_FORMAT(CURDATE(),'%y')

두 자리 숫자의 연도는 다음으로 넘어갑니다.0081년 만에이것이 바로 Y2K 문제가 만들어진 방법입니다!그때까지는 코드 작업을 하지 않을 거라 알고 있으니 신경 쓰지 않으실 겁니다.하지만 항상 코드를 유지하는 사람이 당신이 사는 곳을 아는 폭력적인 사이코패스인 것처럼 코드를 작성해야 합니다.


새 코드를 다른 답변에 다시 게시합니다.

이것은 next_id 숫자를 최대 999,999까지 처리하는 데 더 나은 솔루션입니다.

CREATE TRIGGER `update_request_missions_after_insert` BEFORE INSERT ON `request_missions`
FOR EACH ROW
BEGIN
  DECLARE next_id INT;
  SELECT COALESCE(MAX(id),0) + 1 INTO next_id FROM request_missions;
  IF next_id < 1000000 THEN
    SET NEW.rm_number = CONCAT(DATE_FORMAT(CURDATE(),'%y'), '-', LPAD(next_id, 6, '0'));
  ELSE
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'RM Number has reached capacity'
  END IF;
END

레이스 조건 문제는 다르며 사용 중에는 해결책이 없습니다.MAX(id)마지막 ID를 찾기 위해서입니다.문제는 테이블에 둘 이상의 클라이언트를 동시에 삽입할 수 있다는 것입니다.각 클라이언트의 세션은 다음에 대해 동일한 값을 읽습니다.MAX(id)사용합니다.

경주 조건에 대해서 읽어봐야 합니다.

당신이 정말로 필요한 것은 어떤 방식으로든AUTO_INCREMENT 값을 을 사용자의드로유을는에의을고프 값에 .rm_number.

유감스럽게도 방아쇠를 당길 방법이 없습니다.BEFORE INSERT 트리거 중에는 새 AUTO_INCREMENT 값이 아직 생성되지 않습니다. 트리거에는 AFTER INSERT거할다수는r'ytg수nu,할는ntrNEW.rm_number삽입이 이미 끝났기 때문입니다.나는 과거에 이것에 대해 적었습니다.

언급URL : https://stackoverflow.com/questions/54275109/trigger-optimisation