<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/book.pdo.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'es',
  ),
  'this' => 
  array (
    0 => 'pdo.transactions.php',
    1 => 'Transacciones y validaci&oacute;n autom&aacute;tica (autocommit)',
    2 => 'Transacciones y validaci&oacute;n autom&aacute;tica (autocommit)',
  ),
  'up' => 
  array (
    0 => 'book.pdo.php',
    1 => 'PDO',
  ),
  'prev' => 
  array (
    0 => 'pdo.connections.php',
    1 => 'Conexiones y gestor de conexi&oacute;n',
  ),
  'next' => 
  array (
    0 => 'pdo.prepared-statements.php',
    1 => 'Consultas preparadas y procedimientos almacenados',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'es',
    'path' => 'reference/pdo/transactions.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="pdo.transactions" class="chapter">
 <h1 class="title">Transacciones y validación automática (autocommit)</h1>

 <p class="para">
  Ahora que se ha establecido la conexión mediante PDO, es necesario comprender
  cómo PDO gestiona las transacciones antes de ejecutar consultas. Si nunca se han utilizado
  transacciones, estas ofrecen 4 características principales:
  Atomicidad, Consistencia, Aislamiento y Durabilidad (ACID). En otras palabras,
  cualquier trabajo realizado en una transacción, incluso si se efectúa por etapas, está
  garantizado de aplicarse a la base de datos sin riesgo y sin interferencia para otras
  conexiones, cuando se valida. El trabajo de las transacciones también puede ser
  automáticamente anulado a solicitud, siempre que no se haya validado nada aún, lo que
  facilita considerablemente la gestión de errores en los scripts.
 </p>
 <p class="para">
  Las transacciones se implementan típicamente para aplicar
  todas las modificaciones de una sola vez; esto tiene el efecto de mejorar
  radicalmente la eficiencia de las actualizaciones. En otras palabras,
  las transacciones hacen que los scripts sean más rápidos y potencialmente más
  robustos (deben usarse correctamente para disfrutar de estos beneficios).
 </p>
 <p class="para">
  Desafortunadamente, no todas las bases de datos soportan transacciones,
  por lo que PDO debe ejecutarse en modo &quot;autocommit&quot; al abrir la conexión por primera vez.
  El modo &quot;autocommit&quot; significa que todas las consultas que se ejecutan tienen sus transacciones
  implícitas, si la base de datos las soporta, o ninguna transacción si la base de datos no las soporta.
  Si se necesita una transacción, debe usarse el método <span class="methodname"><a href="pdo.begintransaction.php" class="methodname">PDO::beginTransaction()</a></span>
  para inicializarla. Si el controlador utilizado no soporta transacciones, se lanzará una
  excepción PDO (de acuerdo con el gestor de errores: esto siempre es un error grave).
  Una vez dentro de una transacción, debe usarse la función <span class="methodname"><a href="pdo.commit.php" class="methodname">PDO::commit()</a></span>
  o la función <span class="methodname"><a href="pdo.rollback.php" class="methodname">PDO::rollBack()</a></span> para terminarla, según el éxito del código
  durante la transacción.
 </p>
 <div class="warning"><strong class="warning">Advertencia</strong>
  <p class="para">
   PDO solo verifica la posibilidad de usar transacciones al nivel del controlador.
   Si ciertas condiciones durante la ejecución impiden que las transacciones funcionen,
   <span class="methodname"><a href="pdo.begintransaction.php" class="methodname">PDO::beginTransaction()</a></span> devolverá <strong><code><a href="reserved.constants.php#constant.true">true</a></code></strong> sin error si el servidor
   acepta iniciar una transacción.
  </p>
  <p class="para">
   Un ejemplo sería usar transacciones en tablas con formato MyISAM
   del servidor de base de datos MySQL.
  </p>
 </div>
 <div class="warning"><strong class="warning">Advertencia</strong>
  <p class="para">
    <em>Commit implícito con declaraciones DDL:</em>
    Algunas bases de datos emiten automáticamente un
    <code class="literal">COMMIT</code> implícito cuando se ejecuta una declaración de lenguaje de definición de base de datos (DDL),
    como <code class="literal">DROP TABLE</code> o <code class="literal">CREATE TABLE</code>,
    dentro de una transacción. Esto significa que todas las modificaciones anteriores realizadas en la
    misma transacción serán <em>automáticamente validadas</em> y no pueden
    ser anuladas.
  </p>
  <p class="para">
    <code class="literal">MySQL</code> y <code class="literal">Oracle</code> son ejemplos de bases de datos que
    presentan este comportamiento.
  </p>
 </div>
 <p class="para">
  <div class="example" id="example-1">
    <p><strong>Ejemplo #1 Ejemplo de Commit implícito</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$pdo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">beginTransaction</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$pdo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">exec</span><span style="color: #007700">(</span><span style="color: #DD0000">"INSERT INTO users (name) VALUES ('Rasmus')"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$pdo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">exec</span><span style="color: #007700">(</span><span style="color: #DD0000">"CREATE TABLE test (id INT PRIMARY KEY)"</span><span style="color: #007700">); </span><span style="color: #FF8000">// Un COMMIT implícito ocurre aquí<br /></span><span style="color: #0000BB">$pdo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">rollBack</span><span style="color: #007700">(); </span><span style="color: #FF8000">// Esto NO anulará el INSERT/CREATE para MySQL o Oracle<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

  </div>
 </p>
 <p class="para">
  <em>Mejor práctica:</em> Evite ejecutar declaraciones DDL dentro de transacciones
  si se usan bases de datos que imponen este comportamiento. Si es necesario, separe las operaciones DDL
  de la lógica transaccional.
 </p>
 <p class="para">
  Cuando el script finaliza o cuando la conexión está a punto de cerrarse,
  si hay una transacción en curso, PDO la anulará automáticamente.
  Esta es una medida de seguridad para garantizar la integridad de los datos
  en caso de que el script finalice de manera inesperada. Si no se valida
  explícitamente la transacción, entonces se presume que algo salió mal
  y la anulación de la transacción ocurre para garantizar la seguridad de los datos.
 </p>
 <div class="warning"><strong class="warning">Advertencia</strong>
  <p class="para">
   La anulación automática ocurre si se inició la transacción mediante
   <span class="methodname"><a href="pdo.begintransaction.php" class="methodname">PDO::beginTransaction()</a></span>. Si se ejecutó manualmente una consulta que
   comienza una transacción, PDO no tiene forma de saberlo y por lo tanto,
   no anulará automáticamente esa transacción si algo salió mal.
  </p>
 </div>
 <p class="para">
  <div class="example" id="example-2">
   <p><strong>Ejemplo #2 Ejecución de un grupo en una transacción</strong></p>
   <div class="example-contents"><p>
    En el siguiente ejemplo, supongamos que vamos a crear un conjunto de entradas
    para un nuevo empleado, cuyo número de ID será 23.
    Además de los datos básicos sobre esta persona, también se debe registrar su
    salario. Es muy simple realizar dos actualizaciones separadas, pero al encerrarlas
    en las llamadas a las funciones
    <span class="methodname"><a href="pdo.begintransaction.php" class="methodname">PDO::beginTransaction()</a></span> y
    <span class="methodname"><a href="pdo.commit.php" class="methodname">PDO::commit()</a></span>, se garantiza que nadie pueda ver estas
    modificaciones hasta que estén completas. Si algo sale mal, el bloque de captura
    anulará todas las modificaciones realizadas desde el inicio de la transacción y
    mostrará un mensaje de error.
   </p></div>
   <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">try {<br />  </span><span style="color: #0000BB">$dbh </span><span style="color: #007700">= new </span><span style="color: #0000BB">PDO</span><span style="color: #007700">(</span><span style="color: #DD0000">'odbc:SAMPLE'</span><span style="color: #007700">, </span><span style="color: #DD0000">'db2inst1'</span><span style="color: #007700">, </span><span style="color: #DD0000">'ibmdb2'</span><span style="color: #007700">,<br />      array(</span><span style="color: #0000BB">PDO</span><span style="color: #007700">::</span><span style="color: #0000BB">ATTR_PERSISTENT </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">true</span><span style="color: #007700">));<br />  echo </span><span style="color: #DD0000">"Conectado\n"</span><span style="color: #007700">;<br />} catch (</span><span style="color: #0000BB">Exception $e</span><span style="color: #007700">) {<br />  die(</span><span style="color: #DD0000">"No se pudo conectar: " </span><span style="color: #007700">. </span><span style="color: #0000BB">$e</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getMessage</span><span style="color: #007700">());<br />}<br /><br />try {<br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">setAttribute</span><span style="color: #007700">(</span><span style="color: #0000BB">PDO</span><span style="color: #007700">::</span><span style="color: #0000BB">ATTR_ERRMODE</span><span style="color: #007700">, </span><span style="color: #0000BB">PDO</span><span style="color: #007700">::</span><span style="color: #0000BB">ERRMODE_EXCEPTION</span><span style="color: #007700">);<br /><br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">beginTransaction</span><span style="color: #007700">();<br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">exec</span><span style="color: #007700">(</span><span style="color: #DD0000">"insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')"</span><span style="color: #007700">);<br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">exec</span><span style="color: #007700">(</span><span style="color: #DD0000">"insert into salarychange (id, amount, changedate)<br />      values (23, 50000, NOW())"</span><span style="color: #007700">);<br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">commit</span><span style="color: #007700">();<br /><br />} catch (</span><span style="color: #0000BB">Exception $e</span><span style="color: #007700">) {<br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">rollBack</span><span style="color: #007700">();<br />  echo </span><span style="color: #DD0000">"Falló: " </span><span style="color: #007700">. </span><span style="color: #0000BB">$e</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getMessage</span><span style="color: #007700">();<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </p>
 <p class="para">
  No hay límite en el número de actualizaciones en una transacción;
  también pueden realizarse consultas complejas y, por supuesto, usar
  estas informaciones para construir otras actualizaciones y consultas; durante la actividad
  de la transacción, se está seguro de que nadie más puede realizar
  modificaciones mientras se está en medio de las propias modificaciones.
  Para más información sobre transacciones, consulte la documentación
  proporcionada por su base de datos.
 </p>
</div>
<?php manual_footer($setup); ?>