2012-05-27 12 views
26

Tengo una tabla MySQL que tiene un campo para direcciones de correo electrónico que se define como único. Para este ejemplo, digamos que todo lo que hace mi formulario es permitir que un usuario inserte su dirección de correo electrónico en la tabla.comprobar entrada duplicada vs uso PDO errorInfo resultado

Dado que el campo del correo electrónico es único, la consulta debería fallar si intentan ingresar el mismo correo electrónico dos veces. Tengo curiosidad acerca de las concesiones entre los dos escenarios:

1) Ejecute una declaración rápida SELECT antes de realizar la inserción. Si la selección arroja resultados, informe al usuario y no ejecute la instrucción INSERT.

2) ejecuta la instrucción INSERT, y compruebe si hay un error de entrada duplicada

// snippet uses PDO 
if (!$prep->execute($values)) 
{ 
    $err = $prep->errorInfo(); 
    if (isset($err[1])) 
    { 
     // 1062 - Duplicate entry 
     if ($err[1] == 1062) 
      echo 'This email already exists.'; 
    } 
} 

También, por favor suponer el uso normal, lo que significa que las entradas duplicadas deben ser mínimos. Por lo tanto, en el primer escenario, obviamente tiene la sobrecarga de ejecutar una consulta adicional para cada inserción, mientras que en el segundo depende del manejo de errores.

Además, tengo curiosidad por escuchar ideas sobre el estilo de codificación. Mi corazón dice '¡Sé un programador defensivo! ¡Comprueba los datos antes de insertarlos! mientras mi cerebro dice 'Hmmm, tal vez sea mejor dejar que MySQL se encargue de verificar los datos por ti'.

EDIT - Tenga en cuenta que esto no es una pregunta "¿Cómo hago esto?" Sino una pregunta "¿Por qué debería hacer esto de una manera particular?". El pequeño fragmento de código que incluí funciona, pero lo que me interesa es la mejor manera de resolver el problema.

+2

¿Has pensado en utilizar 'Exception'? – Leri

+0

¿En cuanto a esto? Por supuesto que manejo excepciones, pero a menos que me falta algo, el manejo de excepciones está fuera del alcance de mi pregunta. – JoshBramlett

Respuesta

8

INSERT + verificar el estado debería ser un mejor enfoque. Con SELECT + INSERT puede hacer que otro subproceso inserte el mismo valor entre SELECT y INSERT, lo que significa que también deberá envolver esas dos instrucciones en un bloqueo de tabla.

Es fácil equivocarse por el lado de demasiada defensa en su codificación. Python tiene el dicho de que "es más fácil pedir perdón que pedir permiso", y esta filosofía no es realmente específica de Python.

47

Usted podría ser la ejecución de este bloque con un intento de captura:

try { 
    $prep->execute($values); 
    // do other things if successfully inserted 
} catch (PDOException $e) { 
    if ($e->errorInfo[1] == 1062) { 
     // duplicate entry, do something else 
    } else { 
     // an error other than duplicate entry occurred 
    } 
} 

También podría mirar en alternativas como "INSERT IGNORE", y "INSERT ... ON DUPLICATE KEY UPDATE" - aunque creo esos son específicos de MySQL e irían en contra de la portabilidad de usar PDO, si eso es algo que le preocupa.

Editar: Para responder más formalmente a su pregunta, para mí, la solución n. ° 1 (el programador defensivo) en pleno uso elimina efectivamente el punto de la restricción única en primer lugar. Así que estoy de acuerdo con su idea de dejar que MySQL se encargue de la verificación de datos.

+10

'PDOException-> errorInfo [1]' también es específico de MySQL, es 'Código de error específico del controlador', de acuerdo con los documentos PHP. Es necesario que compruebe lo siguiente 'PDOException-> errorInfo [0]', que es el código SQLSTATE, que debería ser más o menos (aunque a menudo menos) portátil. – lanzz

+0

@lanzz ¿no sería mejor comprobar el resultado de $ e-> getCode()? –

+0

@aron.duby: Sí, pero al igual que muchos otros casos con los desastrosos documentos PHP, el método ['PDOException :: getCode()'] (http://bg2.php.net/manual/en/exception.getcode.php) es en realidad completamente indocumentado, y esta funcionalidad se describe extrañamente en los documentos de la clase 'PDOException' principal, en la descripción de la propiedad ** protected **' code (que sería completamente inaccesible desde el exterior de la clase 'PDOException', por lo que nadie lo haría intenta buscar documentación al respecto). – lanzz

Cuestiones relacionadas