2010-06-16 17 views
6

Tengo una instrucción INSERT muy simple que se ejecuta desde un script PHP que se ejecuta en un servidor web Apache de Linux. Puedo ejecutar bien la consulta desde SQL Management Studio y normalmente funciona bien desde PHP también. Sin embargo, de vez en cuando obtengo un mensaje de error de mi script PHP que dice que la consulta falló y la función mssql_get_last_message() devuelve 'La declaración ha sido cancelada'.¿Qué hace que SQL Server devuelva el mensaje 'La declaración ha finalizado'?

¿Qué fuentes pueden hacer que este mensaje sea devuelto por SQL Server?

Respuesta

11

Ha encontrado una de las partes más molestas de SQL Server. Hay situaciones en las que se puede generar un error y SQL generará dos mensajes de error: el primero para explicar el error y el segundo para decir algo útil como "La declaración ha finalizado" (que, técnicamente, es el número de error). 3621). El problema es que SQL, y casi todo lo demás que lo toca, como PHP, solo puede ver/recoger/procesar/o utilizar el último mensaje de error de unlcear. El que es realmente útil se pierde.

La manera más rápida de descubrir qué está pasando es ejecutar la secuencia de comandos que conducen al error de SSMS. Esto, aparentemente, no funcionará para ti.

Una manera más complicada de resolverlo es iniciar SQL Profiler para rastrear el evento Exception, y luego ejecutar su proceso. Esto debería mostrar todos los errores que ocurrieron. Al lanzar otros eventos relevantes (SP: Starting, SP: StmtStarting, SQL: BatchStarting, lo que sea aplicable al código que envíe a la base de datos) se mostrará qué comando está generando el error.

1

para obtener un código de error numérico de mssql se puede hacer una selección que se ve algo como

SELECT @@ ERROR COMO ErrorCode
que debe devolver el código de error correcto.

También puede probar este código que se publica en PHP.NET.

function query($sQuery, $hDb_conn, $sError, $bDebug) 
{ 
    if(!$rQuery = @mssql_query($sQuery, $hDb_conn)) 
    { 
     $sMssql_get_last_message = mssql_get_last_message(); 
     $sQuery_added = "BEGIN TRY\n"; 
     $sQuery_added .= "\t".$sQuery."\n"; 
     $sQuery_added .= "END TRY\n"; 
     $sQuery_added .= "BEGIN CATCH\n"; 
     $sQuery_added .= "\tSELECT 'Error: ' + ERROR_MESSAGE()\n"; 
     $sQuery_added .= "END CATCH"; 
     $rRun2= @mssql_query($sQuery_added, $hDb_conn); 
     $aReturn = @mssql_fetch_assoc($rRun2); 
     if(empty($aReturn)) 
     { 
      echo $sError.'. MSSQL returned: '.$sMssql_get_last_message.'.<br>Executed query: '.nl2br($sQuery); 
     } 
     elseif(isset($aReturn['computed'])) 
     { 
      echo $sError.'. MSSQL returned: '.$aReturn['computed'].'.<br>Executed query: '.nl2br($sQuery); 
     } 
     return FALSE; 
    } 
    else 
    { 
     return $rQuery; 
    } 
} 
+0

Entonces, con su ejemplo, si detecto mi mensaje 'La declaración ha finalizado', ¿debería poder enviar la consulta que proporcionó para obtener el código de error? –

+0

No importa, su solución, en teoría, suena bien. Sin embargo, la variable @@ ERROR se sobrescribirá si otra consulta ingresa en la base de datos antes de que pueda consultarla. En un servidor ocupado esto es muy probable. –

+0

El problema que está teniendo es aparentemente un problema conocido con el controlador mssql. Mire http://php.net/manual/en/function.mssql-get-last-message.php, especialmente los comentarios en la parte inferior.La gente ha estado luchando con este problema durante mucho tiempo. – Gary

0

Puede usar el código en el mensaje para saber cuál es el error. Por ejemplo:

[2627:. La instrucción se ha terminado]

En este caso, el código de error es 2627, por lo que si se ejecuta el sql continuación sabrá el mensaje

SELECT msg.text 
    FROM sys.messages msg 
INNER JOIN sys.syslanguages lng ON lng.msglangid = msg.language_id 
WHERE msg.message_id = 2627 
    AND lng.alias = 'English' 

Violación de% ls constraint '%. * Ls'. No se puede insertar una clave duplicada en el objeto '%. * Ls'. El valor duplicado de la clave es% ls.

Esta es una forma de saber el error de mensaje correcto. En mi ejemplo, el error es la violación de la clave primaria

Cuestiones relacionadas