Pregunta

Estoy tratando con una tabla MySQL que define la columna JobName como ÚNICA.Si alguien intenta guardar un nuevo trabajo en la base de datos usando un nombre de trabajo que ya está en la base de datos, MySQL genera una advertencia.

Me gustaría poder detectar esta advertencia, como si fuera un error, en mi script PHP y tratarla adecuadamente.Idealmente, me gustaría saber qué tipo de advertencia ha arrojado MySQL para poder bifurcar el código para manejarla.

es posible?Si no es así, ¿es porque MySQL no tiene esta capacidad, PHP no tiene esta capacidad, o ambas?

¿Fue útil?

Solución

Para que las advertencias se "marquen" en PHP de forma nativa, se requerirían cambios en el controlador mysql/mysqli, lo que obviamente está más allá del alcance de esta pregunta.En su lugar, básicamente tendrá que verificar cada consulta que realice en la base de datos para detectar advertencias:

$warningCountResult = mysql_query("SELECT @@warning_count");
if ($warningCountResult) {
    $warningCount = mysql_fetch_row($warningCountResult );
    if ($warningCount[0] > 0) {
        //Have warnings
        $warningDetailResult = mysql_query("SHOW WARNINGS");
        if ($warningDetailResult ) {
            while ($warning = mysql_fetch_assoc(warningDetailResult) {
                //Process it
            }
        }
    }//Else no warnings
}

Obviamente, esto va a ser tremendamente costoso de aplicar en masa, por lo que es posible que deba pensar detenidamente cuándo y cómo pueden surgir advertencias (lo que puede llevarle a refactorizar para eliminarlas).

Para referencia, MySQL MOSTRAR ADVERTENCIAS

Por supuesto, podría prescindir de la consulta inicial para el SELECT @@warning_count, lo que le ahorraría una consulta por ejecución, pero lo incluí para que esté completo y pedante.

Otros consejos

Primero, deberías desactivar las advertencias para que tus visitantes no vean tu mysql errores.Segundo, cuando llamas mysql_query(), debes verificar si devolvió falso.Si es así, llame mysql_errno() para descubrir qué salió mal.Haga coincidir el número devuelto con los códigos de error en esta página.

Parece que este es el número de error que estás buscando:

Error:1169 ESTADOSQL:23000 (ER_DUP_UNIQUE)

Mensaje:No se puede escribir, debido a una restricción única, en la tabla '%s'

ini_set('mysql.trace_mode', 1)

puede ser lo que estás buscando.

Los errores de PHP se pueden manejar con un controlador de errores de PHP personalizado, pero también puede desactivar la visualización de errores de PHP, ya que generalmente se registran en un archivo de registro (depende de su configuración de PHP).

Dependiendo del marco que esté utilizando (si lo hay), le sugiero que realice una consulta para verificar el nombre del trabajo usted mismo y crear la información adecuada para el usuario con el resto de las validaciones del formulario.

Dependiendo de la cantidad de nombres de trabajos, puede enviar los nombres a la vista que contiene el formulario y usar javascript para indicar cuál se utiliza.

Si esto no tiene sentido para usted, entonces, para resumir mi punto de vista, es este:No diseñe su programa y/o usuario para intentar hacer cosas ilegales y detectar los errores cuando lo hagan y manejarlos luego.Es mucho mejor, en mi humilde opinión, diseñar su sistema para que no cree errores.Mantenga los errores en errores reales :)

Actualizado para eliminar las cosas sobre las funciones errno que ahora me doy cuenta de que no se aplican en su situación...

Una cosa en MySQL de la que hay que tener cuidado UPDATE declaraciones: mysqli_affected_rows() devolverá cero incluso si el WHERE cláusula coincide con filas, pero el SET La cláusula en realidad no cambió los valores de los datos.Solo menciono esto porque ese comportamiento causó un error en un sistema que una vez miré: el programador usó ese valor de retorno para verificar si había errores después de una actualización, suponiendo que un cero significaba que había ocurrido algún error.Simplemente significaba que el usuario no cambió ningún valor existente antes de hacer clic en el botón Actualizar.

Así que supongo que usando mysqli_affected_rows() Tampoco se puede confiar en que encuentre tales advertencias, a menos que tenga algo como un update_time columna en su tabla a la que siempre se le asignará un nuevo valor de marca de tiempo cuando se actualice.Sin embargo, ese tipo de solución parece un poco torpe.

Puede detectar violaciones de clave única utilizando el error de declaración mysqli no.La declaración mysqli devuelve el error 1062, es decir ER_DUP_ENTRY.Puede buscar el error 1062 e imprimir un mensaje de error adecuado.Si desea imprimir su columna (nombre del trabajo) también como parte de su mensaje de error, debe analizar la cadena de error de la declaración.

  if($stmt = $mysqli->prepare($sql)){
            $stmt->bind_param("sss",
            $name,
            $identKey,
            $domain);


            $stmt->execute();
            if($mysqli->affected_rows != 1)  {
                        //This will return errorno 1062
                trigger_error('mysql error >> '.$stmt->errno .'::' .$stmt->error, E_USER_ERROR);
                exit(1);
            }
            $stmt->close();
        } else {

            trigger_error('mysql error >> '. $mysqli->errno.'::'.$mysqli->error,E_USER_ERROR);
        }

Es posible obtener las advertencias, y de forma más eficiente con mysqli que con mysql.

Aquí está el código sugerido en el manual. página en php.net para la propiedad mysqli->warning_count:

$mysqli->query($query);

if ($mysqli->warning_count) {
    if ($result = $mysqli->query("SHOW WARNINGS")) {
        $row = $result->fetch_row();
        printf("%s (%d): %s\n", $row[0], $row[1], $row[2]);
        $result->close();
    }
}

Nota sobre la supresión de advertencias:Generalmente, no es una buena idea evitar que se muestren advertencias, ya que es posible que se esté perdiendo algo importante.Si es absolutamente necesario ocultar las advertencias por algún motivo, puede hacerlo de forma individual colocando un @ firme delante de la declaración.De esa manera, no tendrá que desactivar todos los informes de advertencia y podrá limitarlos a una instancia específica.

Ejemplo:

 // this suppresses warnings that might result if there is no field titled "field" in the result
 $field_value = @mysql_result($result, 0, "field");
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top