Cómo depurar procedimientos almacenados con instrucciones de impresión?


Estoy tratando de depurar procedimientos almacenados en SQL Server Management Studio 2008. Quiero insertar algunas sentencias print para probar algunas sentencias IF-que sé que están mal.

Para hacer la depuración, intenté usar el comando PRINT '5'.

He intentado usar el RAISERROR como 'RAISERROR (N'Start',10,1) WITH NOWAIT'.

Pero estos no mostraban ninguna impresión, solo el conjunto de resultados. El mensaje solo dice 1 row affected.

Traté de escribir el código de esta manera (tal vez esto es un incorrecto approach):

SET NOCOUNT ON         
RAISERROR (N'Start',10,1) WITH NOWAIT    
DECLARE @DocHandle INT        
DECLARE @PageSize INT, @PageIndex INT, @TOTL_CONT NUMERIC(5,0), @Paging BIT        
DECLARE @Type INT, @Search varchar(20) , @ORDE nVARCHAR(50), @SORT_ID nVARCHAR(50) 
DECLARE @CreatedOn varchar(25), @SystemGenerate bit   

¿Cuál es la mejor manera de usar instrucciones de impresión para depurar un procedimiento almacenado?

Author: Eric Leschinski, 2013-03-14

5 answers

Si está utilizando MSSQL Server management studio, las instrucciones print se imprimirán en la pestaña mensajes, no en la pestaña Resultados.

introduzca la descripción de la imagen aquí

Las instrucciones Print aparecerán allí.

 20
Author: Kevin Kunderman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-26 09:58:38

Intenta usar:

RAISERROR('your message here!!!',0,1) WITH NOWAIT

También puede intentar cambiar a "Resultados a texto", son solo unos pocos iconos a la derecha de "Ejecutar" en la barra de herramientas predeterminada.

Con ambos de los anteriores en su lugar, y todavía no ve los mensajes, asegúrese de que está ejecutando la misma versión del servidor/base de datos/propietario del procedimiento que está editando. Asegúrese de que está golpeando el comando RAISERROR, que sea el primer comando dentro del procedimiento.

Si todo lo demás falla, puede crear un cuadro:

create table temp_log (RowID int identity(1,1) primary key not null
                      , MessageValue varchar(255))

Entonces:

INSERT INTO temp_log VALUES ('Your message here')

Luego, después de ejecutar el procedimiento (proporcionado no rollbacks) solo select la tabla.

 11
Author: KM.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-14 15:52:33

Aquí hay un ejemplo de uso de la instrucción print. Deben aparecer en la pestaña mensajes como lo indicó una persona anterior.

    Declare @TestVar int = 5;

    print 'this is a test message';
    print @TestVar;
    print 'test-' + Convert(varchar(50), @TestVar);

Imprimir Mensajes

 10
Author: cmartin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-28 20:02:06

Antes de llegar a mi respuesta reiterada; estoy confesando que la única respuesta que aceptaría aquí es esta por KM. supra. Voté en contra de las otras respuestas porque ninguna de ellas respondió realmente a la pregunta formulada o no eran adecuadas. De hecho, la salida de impresión aparece en la ventana de mensaje, pero eso no es lo que se preguntó en absoluto.

¿Por qué no se muestra la salida de la instrucción PRINT durante la ejecución de mi Procedimiento almacenado?
La versión corta de esto la respuesta es que está enviando la ejecución de su sproc al servidor SQL y no va a responder hasta que haya terminado con toda la transacción. Aquí hay una mejor respuesta ubicada en este enlace externo.

  • Para aún más opiniones/observaciones enfoca tu atención en esto, ASÍ que postea aquí.
  • Mira específicamente esta respuesta del mismo post de Phil_factor (¡Ja, ja! Me encanta el humor SQL)
  • Con respecto a la sugerencia de usando RAISERROR CON NOWAIT mira esta respuesta del mismo post de JimCarden

No hagas estas cosas

  1. Algunas personas tienen la impresión de que solo pueden usar una instrucción GO después de su instrucción PRINT, pero NO SE PUEDE usar la instrucción GO DENTRO de un sproc. Así que esa solución está fuera.
  2. No recomiendo SELECCIONAR sus declaraciones de impresión porque solo va a enturbiar su conjunto de resultados con tonterías y si se supone que su sproc será consumido por un programa más tarde, entonces tendrá que saber qué conjuntos de resultados omitir al recorrer los resultados de su lector de datos. Esto es una mala idea, así que no lo hagas.
  3. Otro problema con la SELECCIÓN de sus declaraciones de impresión es que no siempre aparecen inmediatamente. He tenido diferentes experiencias con esto para diferentes ejecuciones, así que no esperes ningún tipo de consistencia con esta metodología.

Alternativa a la IMPRESIÓN dentro de un Procedimiento Almacenado
Realmente esto es una especie de trabajo desagradable en mi opinión porque la sintaxis es confusa en el contexto en el que se está utilizando, pero quién sabe tal vez se actualizará en el futuro por Microsoft. Simplemente no me gusta la idea de generar un error con el único propósito de imprimir información de depuración...

Parece que la única manera de evitar este problema es utilizar, como se ha explicado en numerosas ocasiones ya RAISERROR CON NOWAIT. Estoy dando un ejemplo y señalando un pequeño problema con este enfoque:

ALTER
--CREATE 
    PROCEDURE [dbo].[PrintVsRaiseErrorSprocExample]
AS
BEGIN
    SET NOCOUNT ON;

    -- This will print immediately
    RAISERROR ('RE Start', 0, 1) WITH NOWAIT
    SELECT 1;

    -- Five second delay to simulate lengthy execution
    WAITFOR DELAY '00:00:05'

    -- This will print after the five second delay
    RAISERROR ('RE End', 0, 1) WITH NOWAIT
    SELECT 2;
END

GO

EXEC [dbo].[PrintVsRaiseErrorSprocExample]

Los resultados de ambas sentencias SELECT solo se mostrarán después de que la ejecución haya finalizado y las sentencias print se mostrarán en el orden mostrado anteriormente.

Problema Potencial con este enfoque
Digamos que tienes tu declaración PRINT y la declaración RAISERROR una tras otra, luego ambas imprimen. Estoy seguro de que esto tiene algo que ver con el almacenamiento en búfer, pero tenga en cuenta que esto puede suceder.

ALTER
--CREATE 
    PROCEDURE [dbo].[PrintVsRaiseErrorSprocExample2]
AS
BEGIN
    SET NOCOUNT ON;

    -- Both the PRINT and RAISERROR statements will show
    PRINT 'P Start';
    RAISERROR ('RE Start', 0, 1) WITH NOWAIT
    SELECT 1;

    WAITFOR DELAY '00:00:05'

    -- Both the PRINT and RAISERROR statements will show
    PRINT 'P End'
    RAISERROR ('RE End', 0, 1) WITH NOWAIT
    SELECT 2;
END

GO

EXEC [dbo].[PrintVsRaiseErrorSprocExample2]

Por lo tanto, el trabajo aquí es, no use tanto PRINT como RAISERROR, solo elija uno sobre el otro. Si desea que su salida se muestre durante la ejecución de un sproc, utilice RAISERROR CON NOWAIT.

 10
Author: dyslexicanaboko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:10

Mire este Como en la Documentación de MSDN: Ejecute el Depurador Transact-SQL - es no con instrucciones PRINT, pero tal vez le ayude de todos modos a depurar su código.

Este video de YouTube: SQL Server 2008 T-SQL Debugger muestra el uso del Depurador.

=> Los procedimientos almacenados se escriben en Transact-SQL. Esto le permite depurar todo el código Transact-SQL y, por lo tanto, es como depurar en Visual Studio con la definición de puntos de interrupción y ver el variable.

 -1
Author: Adelphos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-07 16:09:10