Pergunta

Estou lidando com uma tabela MySQL que define a coluna JobName como UNIQUE.Se alguém tentar salvar um novo Job no banco de dados usando um JobName que já está no banco de dados, o MySQL lança um aviso.

Gostaria de poder detectar esse aviso, assim como um erro, em meu script PHP e lidar com ele de maneira adequada.Idealmente, eu gostaria de saber que tipo de aviso o MySQL lançou para que eu possa ramificar o código para lidar com ele.

Isso é possível?Se não, é porque o MySQL não tem essa capacidade, o PHP não tem essa capacidade, ou ambos?

Foi útil?

Solução

Para que os avisos sejam "sinalizados" para PHP nativamente, seriam necessárias alterações no driver mysql/mysqli, o que obviamente está além do escopo desta questão.Em vez disso, você terá que basicamente verificar todas as consultas feitas no banco de dados em busca de avisos:

$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, isso será terrivelmente caro para ser aplicado em massa, então você pode precisar pensar cuidadosamente sobre quando e como os avisos podem surgir (o que pode levar você a refatorar para eliminá-los).

Para referência, MySQL MOSTRAR AVISOS

Claro, você poderia dispensar a consulta inicial para o SELECT @@warning_count, o que economizaria uma consulta por execução, mas eu a incluí para ser mais pedante.

Outras dicas

Primeiro, você deve desativar avisos para que seus visitantes não vejam seu MySQL erros.Em segundo lugar, quando você liga mysql_query(), você deve verificar se ele retornou falso.Se isso aconteceu, ligue mysql_errno() para descobrir o que deu errado.Combine o número retornado com os códigos de erro em esta página.

Parece que este é o número do erro que você está procurando:

Erro:1169 SQLSTATE:23000 (ER_DUP_UNIQUE)

Mensagem:Não é possível gravar, devido à restrição exclusiva, na tabela '%s'

ini_set('mysql.trace_mode', 1)

pode ser o que você está procurando.

Os erros de PHP podem então ser tratados com um manipulador de erros de PHP personalizado, mas você também pode simplesmente desativar a exibição de erros de php, pois eles geralmente são registrados em um arquivo de log (depende da configuração do php).

dependendo de qual estrutura (se houver) você está usando, sugiro que você faça uma consulta para verificar o nome do trabalho e crie as informações adequadas para o usuário com o restante das validações do formulário.

Dependendo do número de nomes de trabalhos, você pode enviar os nomes para a visualização que contém o formulário e usar javascript para informar qual uso está sendo usado.

Se isso não faz sentido para você, então, para resumir minha opinião, é o seguinte:não projete seu programa e/ou usuário para tentar fazer coisas ilegais e detectar os erros quando eles o fizerem e então lidar com isso.É muito melhor, na minha opinião, projetar seu sistema para não criar erros.Mantenha os erros como bugs reais :)

Atualizado para remover coisas sobre funções errno que agora percebo que não se aplicam à sua situação ...

Uma coisa no MySQL para se ter cuidado UPDATE declarações: mysqli_affected_rows() retornará zero mesmo se o WHERE cláusula correspondeu às linhas, mas o SET cláusula não alterou realmente os valores dos dados.Mencionei isso apenas porque esse comportamento causou um bug em um sistema que observei uma vez - o programador usou esse valor de retorno para verificar se havia erros após uma atualização, assumindo que um zero significava que algum erro havia ocorrido.Significa apenas que o usuário não alterou nenhum valor existente antes de clicar no botão atualizar.

Então eu acho que usar mysqli_affected_rows() também não pode ser confiável para encontrar tais avisos, a menos que você tenha algo como um update_time coluna em sua tabela que sempre receberá um novo valor de carimbo de data/hora quando atualizada.Esse tipo de solução alternativa parece meio desajeitada.

Você pode detectar violações de chave exclusiva usando o erro de instrução mysqli no.A instrução mysqli retorna o erro 1062, ou seja, ER_DUP_ENTRY.Você pode procurar o erro 1062 e imprimir uma mensagem de erro adequada.Se você deseja imprimir sua coluna (jobName) também como parte de sua mensagem de erro, você deve analisar a string de erro da instrução.

  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);
        }

É possível obter os avisos, e de forma mais eficiente com o mysqli do que com o mysql.

Aqui está o código sugerido no manual página no php.net para a propriedade 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 a supressão de avisos:Geralmente, não é uma boa ideia impedir a exibição de avisos, pois pode estar faltando algo importante.Se for absolutamente necessário ocultar avisos por algum motivo, você poderá fazê-lo individualmente, colocando um @ assine antes da declaração.Dessa forma, você não precisa desativar todos os relatórios de aviso e pode limitá-los a uma instância específica.

Exemplo:

 // this suppresses warnings that might result if there is no field titled "field" in the result
 $field_value = @mysql_result($result, 0, "field");
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top