2012-07-17 7 views
0

내가 만든 Prepared Statement를 실행할 수있는 방법을 찾을 수 있다면 다음 코드를 사용하여 Insert Before 트리거를 만들려고합니다. 방아쇠.Prepared Statement with Trigger with MySQL with

트리거 내에서 준비된 명령문을 실행할 수있는 다른 방법이 있습니까? 감사합니다

BEGIN 
    SET @CrntRcrd = (SELECT AUTO_INCREMENT FROM information_schema.TABLES 
       WHERE TABLE_SCHEMA=DATABASE() 
       AND TABLE_NAME='core_Test'); 

    SET @PrevRcrd = @CrntRcrd-1; 

    IF (NEW.ID IS NULL) THEN 
     SET NEW.ID = @CrntRcrd; 
    END IF; 

    SET @PrevHash = (SELECT Hash FROM core_Test WHERE [email protected]); 

    SET @ClmNms = (SELECT CONCAT('NEW.',GROUP_CONCAT(column_name 
        ORDER BY ORDINAL_POSITION SEPARATOR ',NEW.'),'') 
        FROM information_schema.columns 
        WHERE table_schema = DATABASE() 
        AND table_name = 'core_Test'); 

    SET @Query = CONCAT("SET @Query2 = CONCAT_WS(',','",@PrevHash,"','", @CrntRcrd, "',", @ClmNms, ");"); 

    PREPARE stmt1 FROM @Query; 
    EXECUTE stmt1; 
    DEALLOCATE PREPARE stmt1; 

    SET NEW.Hash = @Query2; 
END 

UPDATE/설명 : 데이터는 아래 테이블에 저장됩니다. 각 인서트

+------------+-----+------+----------------+ 
| Record (AI)| ID | Data | HASH   | 
+------------+-----+------+----------------+ 
| 1   | 1 | ASDF | =DHFBGKJSDFHBG | (Hash Col 1) 
| 2   | 2 | NULL | =UEGFRYJKSDFHB | (Hash Col 1 + Col 2) 
| 3   | 1 | VBNM | =VKJSZDFVHBFJH | (Hash Col 2 + Col 3) 
| 4   | 4 | TYUI | =KDJFGNJBHMNVB | (Hash Col 3 + Col 4) 
| 5   | 5 | ZXCV | =SDKVBCVJHBJHB | (Hash Col 4 + Col 5) 
+------------+-----+------+----------------+ 

테이블 전체 새로운 행의 CONCAT()에 대한 투과성 행의 해시 값을 appeding하여 그 행에 대한 해시 값을 생성 명령 후 다시 해싱 전체 문자열. 그러면 응용 프로그램의 다른 부분에서 감사 용도로 사용하기 위해 해시 값에 대한 실행 기록이 생성됩니다.

내 제한 조건은 INSERT 행을 나중에 업데이트 할 수 있기 전에 수행해야한다는 것입니다.

UPDATE : 나는 동적으로 CONCAT하려면 열 이름을 전달하는 방법을 찾을 수있을 때까지 나는 현재 다음과 같은 코드를 사용하고는 :

BEGIN 

    SET @Record = (
    SELECT AUTO_INCREMENT FROM information_schema.TABLES 
    WHERE TABLE_SCHEMA=DATABASE() 
    AND TABLE_NAME='core_Test' #<--- UPDATE TABLE_NAME HERE 
); 
    SET @PrevRecrd = @Record-1; 

    IF (new.ID IS NULL) THEN 
    SET new.ID = @Record; 
    END IF; 

    SET @PrevHash = (
    SELECT Hash FROM core_Test #<--- UPDATE TABLE_NAME HERE 
    WHERE [email protected] 
); 

    SET new.Hash = SHA1(CONCAT_WS(',',@PrevHash, @Record, 
    /* --- UPDATE TABLE COLUMN NAMES HERE (EXCLUDE "new.Record" AND "new.Hash") --- */ 
    new.ID, new.Name, new.Data 
)); 

END 

답변

1

짧은 대답은 동적 SQL을 사용할 수 없다는 것입니다 TRIGGER에서.

auto_increment 값의 쿼리와 ID 열에 값을 할당하는 것에 혼란 스럽습니다. ID 열의 값을 설정해야하는 이유를 이해할 수 없습니다. AUTO_INCREMENT로 정의 된 열이 아닌가? 데이터베이스가 할당을 처리합니다.

특히 동시 삽입을 실행할 때 쿼리가 고유 값을 반환하도록 보장되는지 확실하지 않습니다. (테스트하지 않았기 때문에 작동 할 수도 있습니다.)

하지만 코드가 독특합니다.

가장 최근에 삽입 된 행에서 열 값을 가져 오는 것입니다. 트리거가 정의 된 동일한 테이블을 쿼리하는 데는 몇 가지 제한이 있다고 생각합니다.

SELECT @prev_hash := t.hash AS prev_hash 
    FROM core_Test t 
    ORDER BY t.ID DESC LIMIT 1; 

SET NEW.hash = @prev_hash; 

을 그러나 다시, 난 : 나는 그런 일을 할 필요가 있다면 나는 이런 식으로 뭔가를 시도 할 것이다,

(. MySQL은 자유주의 수 있습니다 나는 오라클이 확실히 알) 이것이 작동 할 지 확신하지 못합니다 (테스트해야 할 것입니다). 단순한 경우에 작동하면, 동시 삽입의 경우, 확장 된 삽입의 경우에 항상 작동한다는 증거는 아닙니다.

ID 열의 인덱스를 사용하여 역 스캔 작업을 수행 할 수 있도록 쿼리를 작성했습니다. 이 인덱스를 사용하지 않는 경우에, 나는 최상의 성능을 얻기 위해, 아마 가입으로 (즉, 쿼리를 다시 작성하려고 할 것입니다. MySQL은 5.1 참조 설명서
E.에서

SELECT @prev_hash := t.hash AS prev_hash 
    FROM (SELECT r.ID FROM core_Test r ORDER BY r.ID DESC LIMIT 1) s 
    JOIN core_Test t 
    ON t.ID = s.ID 

발췌저장된 프로그램에 제한 1>
SQL
< 가위질은 문 (DEALLOCATE 준비, PREPARE 실행) 저장 과정에서 사용될 수있다 제조되지만 하지 저장된 함수 또는 트리거 . 따라서 저장된 함수와 트리거는 동적 SQL을 사용할 수 없습니다 (여기서 문을 문자열로 구성한 다음 실행합니다).
</snip>