2014-09-02 3 views
0

Почему приведенный ниже код выполняет исключение запроса (DELETE FROM ...), даже давая ошибку в запросе на вставку?Транзакция PHP и Oracle

Сообщение об ошибке:

Массив ([0] => ОРА-00001:. Restrição exclusiva (INTRANETDESENVOLVIMENTO.PK_TB100442_MAIL_BACKUP) violada Linha: 260 )

Я последовал этому примеру: http://php.net/manual/pt_BR/function.oci-rollback.php

Моя функция:

public function minimizarSGMail() 
{ 
    $conn = oci_connect(IC::get('database.username'), IC::get('database.password'), IC::get('database.tns')); 
    $linhas = 5; 
    $dias = 90; 
    $erro = array(); 

    // Prepara o sql de insert 
    $stid = oci_parse($conn, "INSERT INTO TB100442_MAIL_BACKUP (
      SELECT * FROM (
       SELECT * FROM TB100442_MAIL WHERE 
        DATA_INSERCAO <= TO_DATE(SYSDATE-{$dias}) AND 
        ROWNUM <= {$linhas} 
        ORDER BY ID_MAIL DESC 
      ) 
     )" 
    ); 

    $r = oci_execute($stid, OCI_NO_AUTO_COMMIT); 
    if (!$r) { 
     $e = oci_error($stid); 
     array_push($erro, htmlentities($e['message'] . '. Linha: ' . __LINE__)); 
    } 

    // Prepara o sql de exclusao 
    $stid = oci_parse($conn, "DELETE FROM TB100442_MAIL WHERE ID_MAIL IN (
      SELECT ID_MAIL FROM (
       SELECT ID_MAIL FROM TB100442_MAIL WHERE 
        DATA_INSERCAO <= TO_DATE(SYSDATE-{$dias}) 
        AND ROWNUM <= {$linhas} 
        ORDER BY ID_MAIL DESC 
      ) 
     )" 
    ); 

    $r = oci_execute($stid, OCI_NO_AUTO_COMMIT); 
    if (!$r) { 
     $e = oci_error($stid); 
     array_push($erro, htmlentities($e['message'] . '. Linha: ' . __LINE__)); 

     // Rollback das mudancas em ambas as tabelas 
     oci_rollback($conn); 
    } 

    // Commita as mudancas em ambas as tabelas 
    $r = oci_commit($conn); 
    if (!r) { 
     $e = oci_error($conn); 
     array_push($erro, htmlentities($e['message'] . '. Linha: ' . __LINE__)); 
    } 

    echo '<pre>'; 
    print_r($erro); 
    die; 
} 
+0

если я перевожу ошибку правильно, вы нарушили уникальный ключ ограничения где-то, вероятно, первичный ключ. –

+0

Исправить @MarcB. Первый запрос нарушает ограничение целостности, поэтому я бы не хотел, чтобы второй запрос был выполнен. – bferronato

+0

ваш второй запрос не находится в 'if (! $ R)', поэтому КАК этот первый запрос получается, вы пытаетесь запустить второй запрос в любом случае. –

ответ

0

Правильный код:

public function minimizarSGMail() 
{ 
    $conn = oci_connect(IC::get('database.username'), IC::get('database.password'), IC::get('database.tns')); 
    $linhas = 5; 
    $dias = 90; 
    $return = array(); 

    // Prepara o sql de insert 
    $insert = oci_parse($conn, "INSERT INTO TB100442_MAIL_BACKUP (
      SELECT * FROM (
       SELECT * FROM TB100442_MAIL WHERE 
       DATA_INSERCAO <= TO_DATE(SYSDATE-{$dias}) AND 
       ROWNUM <= {$linhas} 
       ORDER BY ID_MAIL DESC 
      ) 
     )" 
    ); 

    // Prepara o sql de exclusao 
    $delete = oci_parse($conn, "DELETE FROM TB100442_MAIL WHERE ID_MAIL IN (
      SELECT ID_MAIL FROM (
       SELECT ID_MAIL FROM TB100442_MAIL WHERE 
        DATA_INSERCAO <= TO_DATE(SYSDATE-{$dias}) 
        AND ROWNUM <= {$linhas} 
        ORDER BY ID_MAIL DESC 
      ) 
     )" 
    ); 

    // Executa o sql de INSERT, sem commit 
    if(oci_execute($insert, OCI_NO_AUTO_COMMIT)) { 

     // Executa o sql de DELETE, sem commit 
     if(!oci_execute($delete, OCI_NO_AUTO_COMMIT)) { 

      $e = oci_error($delete); 
      array_push($return, htmlentities($e['message'] . '. Linha: ' . __LINE__)); 
     } 
    } else { 

     $e = oci_error($insert); 
     array_push($return, htmlentities($e['message'] . '. Linha: ' . __LINE__)); 
    } 

    // Realiza o rollback dos sqls caso haja erro 
    if(count($return) > 0) { 
     oci_rollback($conn); 
    } 

    // Commita as transacoes 
    if(!oci_commit($conn)) { 
     $e = oci_error($conn); 
     array_push($return, htmlentities($e['message'] . '. Linha: ' . __LINE__)); 
    } 

    oci_free_statement($insert); 
    oci_free_statement($delete); 
    oci_close($conn); 

    return $return; 

} 
Смежные вопросы