---
title: "PRINT, RAISERROR WITH NOWAIT, RAISE NOTICE and DBMS_OUTPUT: When Each Message Reaches the Client"
description: "Measured: when SQL Server PRINT and RAISERROR WITH NOWAIT, PostgreSQL RAISE NOTICE, Oracle DBMS_OUTPUT and MySQL warnings actually reach the client."
url: "https://jamsql.com/blog/2026-09-26-print-raiserror-raise-notice-dbms-output/"
html_url: "https://jamsql.com/blog/2026-09-26-print-raiserror-raise-notice-dbms-output/"
generated: "2026-10-02T21:40:14.964Z"
---

Published: 2026-09-26

# `PRINT`, `RAISERROR WITH NOWAIT`, `RAISE NOTICE` and `DBMS_OUTPUT`: When Each Message Reaches the Client

Every engine has a way to send a line of text from server-side code, and each one delivers it on a different schedule. We timed all four against local servers with the same Node.js drivers Jam SQL Studio uses. SQL Server holds `PRINT` output until the batch ends or a network packet fills (4 KB with the driver’s default); `RAISERROR(…, 0, 1) WITH NOWAIT` sends it at once. PostgreSQL sends `RAISE NOTICE` the moment it runs, but only at or above `client_min_messages`. Oracle’s `DBMS_OUTPUT` is a buffer the client reads after the call returns, never during it. MySQL has no `PRINT` at all; there, a `SELECT` is what reaches the client while a procedure is still running.

## Short answers

-   **SQL Server — “PRINT not showing until the end”.** `PRINT` and `RAISERROR` without `NOWAIT` sit in the server’s output buffer. A `PRINT` before a 3-second `WAITFOR` arrived at **3.003 s**. The same text sent with `RAISERROR('before', 0, 1) WITH NOWAIT` arrived at **0.004 s**.
-   **PostgreSQL — “RAISE NOTICE not showing”.** Notices are not buffered: `RAISE NOTICE` before a `pg_sleep(3)` arrived at **0.001 s**. If one never arrives, check `client_min_messages` (set to `warning`, it drops `NOTICE` but not `INFO`), and check that your client listens for notices.
-   **Oracle — “DBMS\_OUTPUT not showing”.** Without `DBMS_OUTPUT.ENABLE` the lines are discarded. With it, they stay in the session until the client calls `GET_LINES`, which is only possible after the block returns (**3.001 s** in our run). For live progress, use `DBMS_APPLICATION_INFO`; another session saw it within 0.1 s.
-   **MySQL — no PRINT.** `PRINT` is error 1064. `SIGNAL SQLSTATE '01000'` only raises the warning count; the text needs `SHOW WARNINGS`. A `SELECT` inside a procedure reached the client at **0.005 s**, before the procedure’s 3-second sleep ended.

## The measurements

Each row is one statement sent from a Node.js script to a Docker container on the same machine. “Received at” is when the driver handed the message (or row, or error) to our code, measured from the moment the statement was sent. Most experiments put a 3-second sleep between two messages, so a message that is really sent immediately shows up near 0 s and one that waits for the end shows up near 3 s. The method and exact versions are under [How we measured](#how-we-measured).

Engine

Statement

Driver

Received at

Note

SQL Server 2025

`PRINT 'before'; WAITFOR DELAY '00:00:03'; PRINT 'after';`

mssql 12.2.0 / tedious 19.1.3

before 3.003 s, after 3.003 s

Held until the batch ended. Same through `sp_executesql` (3.007 s).

SQL Server 2025

`RAISERROR('before', 0, 1) WITH NOWAIT;` 3 s delay, then the same with `'after'`

mssql 12.2.0 / tedious 19.1.3

before 0.004 s, after 3.004 s

Sent the moment it ran.

SQL Server 2025

`RAISERROR('before', 10, 1);` (no `NOWAIT`), delay, again

mssql 12.2.0 / tedious 19.1.3

before 3.003 s

A low severity alone does not send it early.

SQL Server 2025

`PRINT 'before'; RAISERROR('', 0, 1) WITH NOWAIT;` delay, `PRINT 'after';`

mssql 12.2.0 / tedious 19.1.3

before 0.001 s, after 3.002 s

`NOWAIT` also sends the `PRINT` queued ahead of it.

SQL Server 2025

`SELECT 'before' AS progress;` delay, `SELECT 'after' AS progress;`

mssql 12.2.0 / tedious 19.1.3

first row 3.006 s

Result rows wait in the same buffer, so a `SELECT` is no workaround.

SQL Server 2025

`PRINT 'before'; RAISERROR('sev16 error', 16, 1);` delay, `PRINT 'after';`

mssql 12.2.0 / tedious 19.1.3

error 3.003 s

The batch carried on past the error, and the error waited for the end too.

SQL Server 2025

`RAISERROR('sev16 error', 16, 1) WITH NOWAIT;` delay, `PRINT 'after';`

mssql 12.2.0 / tedious 19.1.3

error 0.002 s

`NOWAIT` works for errors as well.

SQL Server 2025

`PRINT 'before';` delay, `THROW 50001, 'thrown', 1;`

mssql 12.2.0 / tedious 19.1.3

before and error 3.003 s

`THROW` ended the batch; it has no `NOWAIT` option.

SQL Server 2025

`EXEC` of a temporary procedure: `PRINT`, delay, `PRINT`

mssql 12.2.0 / tedious 19.1.3

both 3.006 s

Procedures behave like the batch around them.

SQL Server 2025

60 × `PRINT` of a 100-character line, 100 ms apart

mssql 12.2.0 / tedious 19.1.3

first 14 lines at 1.452 s

Arrived in groups of 13–14 with the default 4,096-byte packet (see below).

PostgreSQL 16.4

`DO $$ BEGIN RAISE NOTICE 'before'; PERFORM pg_sleep(3); RAISE NOTICE 'after'; END $$;`

pg 8.16.3

before 0.001 s, after 3.004 s

Sent as raised. PostgreSQL 19beta1: 0.004 s and 3.007 s.

PostgreSQL 16.4

`SELECT pg_temp.jam_probe();` (a function that raises, sleeps, raises)

pg 8.16.3

notice 0.001 s, result 3.010 s

Same inside a function called from a query.

PostgreSQL 16.4

`RAISE DEBUG`, `LOG`, `INFO`, `NOTICE`, `WARNING` at default settings

pg 8.16.3

INFO, NOTICE, WARNING received

`DEBUG` and `LOG` never arrived (`client_min_messages = notice`).

PostgreSQL 16.4

`SET client_min_messages = warning;` then `NOTICE`, `INFO`, `WARNING`

pg 8.16.3

INFO, WARNING received

`NOTICE` was dropped; `INFO` is always sent.

PostgreSQL 16.4

`RAISE NOTICE 'before'; PERFORM pg_sleep(1); RAISE EXCEPTION 'boom';`

pg 8.16.3

notice 0.000 s, error 1.002 s

The notice was already at the client when the error came.

PostgreSQL 16.4

`SELECT 'before'; SELECT pg_sleep(3); SELECT 'after';` as one query string

pg 8.16.3

first row 3.004 s

Rows were held until the string finished; notices are not. Same on 19beta1.

Oracle 26ai Free

`BEGIN DBMS_OUTPUT.PUT_LINE('before'); DBMS_SESSION.SLEEP(3); DBMS_OUTPUT.PUT_LINE('after'); END;` without `ENABLE`

oracledb 6.10.0 (Thin)

call returned 3.006 s; `GET_LINES`: 0 lines

Disabled: the calls were ignored.

Oracle 26ai Free

Same block after `DBMS_OUTPUT.ENABLE(NULL)`

oracledb 6.10.0 (Thin)

call returned 3.001 s; both lines from `GET_LINES` at 3.002 s

Nothing is available while the block runs.

Oracle 26ai Free

`PUT_LINE('before the error');` then `RAISE_APPLICATION_ERROR(-20001, 'boom');`

oracledb 6.10.0 (Thin)

error 0.002 s; `GET_LINES` still returned the line

The buffer outlives the error, in that session.

Oracle 26ai Free

`ENABLE(2000)`, then 100 lines of 50 characters

oracledb 6.10.0 (Thin)

error 0.001 s; 40 lines readable

`ORU-10027: buffer overflow, limit of 2000 bytes`.

Oracle 26ai Free

A block that raised after `PUT_LINE`; then `ENABLE(NULL)` and a new block

oracledb 6.10.0 (Thin)

`GET_LINES` returned the old line and the new one

Calling `ENABLE` again does not clear unread lines.

Oracle 26ai Free

`DBMS_APPLICATION_INFO.SET_MODULE` / `SET_ACTION` between two 2-second sleeps

oracledb 6.10.0 (Thin), second session polling `V$SESSION`

step 1 seen at 0.105 s, step 2 at 2.007 s

Visible from outside while the block runs (100 ms polling).

MySQL 8.0.46

`PRINT 'hello';`

mysql2 3.16.3

error 0.000 s

`ER_PARSE_ERROR` (1064). Same on 9.5.0.

MySQL 8.0.46

`SIGNAL SQLSTATE '01000' SET MESSAGE_TEXT = 'hello';`

mysql2 3.16.3

OK packet 0.000 s, warning count 1

No text; that needs `SHOW WARNINGS`.

MySQL 8.0.46

`CALL` a procedure: `SIGNAL '01000'` ‘before’, `DO SLEEP(3)`, `SIGNAL '01000'` ‘after’; then `SHOW WARNINGS`

mysql2 3.16.3

OK packet 3.001 s

`SHOW WARNINGS` listed only ‘after’ (code 1642).

MySQL 8.0.46

`CALL`: `SIGNAL '01000'`, `DO SLEEP(1)`, `SELECT 1`; then `SHOW WARNINGS`

mysql2 3.16.3

warning count 0

The later statement cleared the warning; `SHOW WARNINGS` was empty.

MySQL 8.0.46

`CALL`: `SELECT 'before' AS progress`, `DO SLEEP(3)`, `SELECT 'after' AS progress`

mysql2 3.16.3

first row 0.005 s, second 3.006 s

Each result set is sent when it is complete. Same on 9.5.0.

MySQL 8.0.46

`SELECT 'before'; DO SLEEP(3); SELECT 'after';` as one multi-statement string

mysql2 3.16.3

first row 0.001 s

Same without a procedure — the opposite of PostgreSQL.

## SQL Server: PRINT waits for the end of the batch or a full packet

SQL Server sends `PRINT` text, and `RAISERROR` messages of severity 10 or lower, as informational tokens in the same response stream as rows, row counts and errors. In our measurements that stream left the server when the batch finished or when a network packet filled up, whichever came first. A short `PRINT` in a long-running batch therefore sits on the server until the end. The delay is on the server, so it applies to every client; what the client controls is the packet size, which sets how much has to accumulate before a send.

We measured that threshold by printing 60 lines of 100 characters, 100 ms apart, at three packet sizes:

Packet size

Lines per send

First lines arrived at

4,096 bytes (tedious default)

13–14

1.452 s

8,192 bytes

27

2.754 s

16,384 bytes

55

5.558 s

Doubling the packet size doubled the number of lines per send, and a second run gave the same groups within 10 ms. Each 100-character line took roughly 290 bytes of a packet: the text travels as UTF-16, together with the server name, the line number and the other tokens the loop produces. So “PRINT eventually shows up mid-run” and “PRINT only shows up at the end” are both true: it depends on how much the batch has printed, not on time.

The fix Microsoft documents is the `NOWAIT` option of `RAISERROR`, which “sends messages immediately to the client”. With a severity of 0 to 10 it is an informational message, not an error, and it takes `printf`\-style arguments:

```sql
DECLARE @step int = 1;
WHILE @step <= 10
BEGIN
    -- ... one unit of work ...
    RAISERROR('Step %d of 10 done', 0, 1, @step) WITH NOWAIT;
    SET @step += 1;
END;
```

Two things from the measurements are worth knowing:

-   **`NOWAIT` flushes what is queued ahead of it.** A `PRINT` followed by `RAISERROR('', 0, 1) WITH NOWAIT` reached the client in 0.001 s. If you already have a script full of `PRINT`s, one `NOWAIT` line after each important `PRINT` is enough. The empty message itself arrived as a single space.
-   **Severity alone changes nothing.** `RAISERROR('before', 10, 1)` without `NOWAIT` waited 3.003 s, exactly like `PRINT`. Even a severity-16 error waited for the end of the batch unless it also had `NOWAIT`.

**THROW is not a replacement here.** Microsoft’s documentation says new applications should use `THROW` instead of `RAISERROR`, but `THROW` always raises severity 16, takes no `printf` arguments, has no `NOWAIT` option, and ends the batch when there is no `CATCH` block. In our run the `PRINT` before it and the error itself arrived together at 3.003 s. For progress messages, `RAISERROR` with severity 0 and `NOWAIT` is still the tool.

Limits from the Microsoft documentation: a `PRINT` message is truncated at 8,000 characters (4,000 for Unicode), and a `RAISERROR` message at 2,047 characters.

If `PRINT` output never shows at all, not even at the end, the problem is in the client. The messages arrive on a separate channel from rows, and each driver exposes them its own way — node-mssql, for example, emits them as an `info` event on the request. A tool that doesn’t subscribe drops them. Jam SQL Studio did exactly that on its direct-driver path until version 1.5.1.

## PostgreSQL: RAISE NOTICE is sent immediately, rows are not

PostgreSQL sends each notice to the client as its own protocol message as soon as it is raised. In our test the first `RAISE NOTICE` arrived after 0.001 s on PostgreSQL 16.4 and 0.004 s on 19beta1, while `pg_sleep(3)` was still running, including when the notice came from a function called inside a `SELECT`. A notice raised before an exception was already at the client when the error arrived.

Rows behave differently. Three `SELECT`s sent as one query string, with a `pg_sleep(3)` in the middle, delivered their first row at 3.004 s: PostgreSQL held the one-row result of the first statement until the whole string had run. So for progress output in PostgreSQL, notices are the channel that arrives early, which is the reverse of MySQL.

When `RAISE NOTICE` doesn’t show up, it is usually one of these:

-   **`client_min_messages` is above `notice`.** The default is `notice`. With `SET client_min_messages = warning`, our `RAISE NOTICE` vanished while `RAISE INFO` and `RAISE WARNING` still arrived; the PostgreSQL documentation states that `INFO` messages are always sent to the client. The setting can also come from `ALTER ROLE … SET` or `ALTER DATABASE … SET`, so run `SHOW client_min_messages;` in the session that is missing notices.
-   **The level is below the threshold.** `RAISE DEBUG` and `RAISE LOG` never reached the client at the default setting. After `SET client_min_messages = debug1`, both did. `log_min_messages` controls the server log separately.
-   **The client doesn’t listen.** Notices are not part of the query result. node-postgres, for example, emits them as a `notice` event on the client connection, and a tool has to subscribe to see them. Jam SQL Studio added that subscription in 1.5.1.

```sql
SHOW client_min_messages;          -- notice is the default
SET client_min_messages = notice;  -- for this session

DO $$
BEGIN
    RAISE NOTICE 'Processed % rows', 1250;
    RAISE INFO 'INFO is sent at any client_min_messages setting';
END $$;
```

Porting T-SQL? `PRINT 'msg'` maps to `RAISE NOTICE 'msg'`, and `RAISE NOTICE` already behaves like `RAISERROR … WITH NOWAIT`, so no extra option is needed. The [T-SQL vs PL/pgSQL reference](/docs/t-sql-vs-plpgsql/) lists the rest of the mapping, and the [stored-procedure conversion guide](/blog/2026-06-14-convert-sql-server-stored-procedures-to-postgresql/) walks through whole procedures.

## Oracle: DBMS\_OUTPUT is a buffer the client reads afterwards

`DBMS_OUTPUT` is a PL/SQL package, not part of the network protocol. `PUT_LINE` appends to a buffer in your session, and the client has to fetch it with `GET_LINE` or `GET_LINES` in a later call. Oracle’s documentation says it directly: “Messages sent using DBMS\_OUTPUT are not actually sent until the sending subprogram or trigger completes. There is no mechanism to flush output during the execution of a procedure.” Our measurement agreed: nothing was readable until the block returned at 3.001 s, and both lines came back from `GET_LINES` 1 ms later.

In SQL\*Plus, `SET SERVEROUTPUT ON` does the bookkeeping for you: per Oracle’s documentation it has the effect of `DBMS_OUTPUT.ENABLE(buffer_size => NULL)`, an unlimited buffer, and the output is displayed after the block or procedure completes. Any other client, whether a driver, an ORM or a GUI, has to do the same two steps itself:

```sql
-- 1. before the user's block, on the same session
BEGIN DBMS_OUTPUT.ENABLE(NULL); END;

-- 2. the user's block
BEGIN
    DBMS_OUTPUT.PUT_LINE('before');
    DBMS_SESSION.SLEEP(3);
    DBMS_OUTPUT.PUT_LINE('after');
END;

-- 3. afterwards, read the buffer
DECLARE
    l_lines DBMS_OUTPUT.CHARARR;
    l_count INTEGER := 1000;
BEGIN
    DBMS_OUTPUT.GET_LINES(l_lines, l_count);
    -- l_count now holds the number of lines actually returned
END;
```

Why `DBMS_OUTPUT` shows nothing, from what we measured and what the Oracle documentation says:

-   **`ENABLE` was never called.** Without it, `GET_LINES` returned 0 lines. The documentation: “If the package is disabled, all calls to subprograms are ignored.”
-   **The read happened on a different session.** The buffer belongs to one session. A connection pool that runs the block on one connection and the read on another gets nothing back.
-   **The line was never ended.** `PUT` without `PUT_LINE` or `NEW_LINE` is not returned by `GET_LINES`; our partial line was left out.
-   **The buffer overflowed.** `ENABLE(2000)` followed by 100 lines of 50 characters failed with `ORU-10027` after 40 lines. The default when you call `ENABLE` with no argument is 20,000 bytes; `NULL` means no limit.

Two further findings are easy to trip over. The buffer survives an exception: after a block printed a line and then raised `ORA-20001`, `GET_LINES` on the same session still returned that line. And calling `ENABLE` again does not clear it, so a later block’s output came back with the old line in front of it. A tool that reads the buffer only on success can therefore show a failed block’s output under the next block.

**For live progress, use a different channel.** `DBMS_APPLICATION_INFO.SET_MODULE` and `SET_ACTION` update `V$SESSION` right away. A second session polling every 100 ms saw “step 1 of 2” at 0.105 s and “step 2 of 2” at 2.007 s, while the block was still sleeping. The other common options are an autonomous-transaction log table and `SET_SESSION_LONGOPS`. If you want to see intermediate values in a running program, a step-through debugger is the direct route; Jam SQL Studio’s [PL/SQL debugger](/docs/plsql-debugger/) also collects `DBMS_OUTPUT` into Messages when the program finishes or is stopped.

## MySQL: no PRINT, warnings you have to ask for, and SELECT that arrives early

MySQL has no `PRINT`. On both 8.0.46 and 9.5.0 it is a syntax error (1064). The closest things are:

-   **`SIGNAL SQLSTATE '01000'`** raises a warning and execution continues. MySQL allows it outside stored programs as well. The client only receives a warning count in the OK packet; the text needs a separate `SHOW WARNINGS`. It also doesn’t accumulate. After a procedure that signalled ‘before’ and later ‘after’, `SHOW WARNINGS` listed only ‘after’. When a `SELECT` ran after the signal, the warning was gone. That matches MySQL’s diagnostics-area rules: each new statement clears the area, and a statement that raises a condition clears the conditions of earlier ones.
-   **`SELECT`** is the practical progress channel. MySQL sent each result set as soon as it was complete: inside a procedure the first row arrived at 0.005 s, and in a plain multi-statement string at 0.001 s, both before the 3-second sleep ended. The cost is that each progress line becomes its own result set.

```sql
DELIMITER //
CREATE PROCEDURE load_batches()
BEGIN
    SELECT 'step 1 of 2: staging' AS progress;   -- reaches the client now
    -- ... work ...
    SELECT 'step 2 of 2: merge' AS progress;
    -- ... work ...
END //
DELIMITER ;
```

## What Jam SQL Studio shows

Jam SQL Studio 1.5.1 fixed a gap on its direct-driver paths: SQL Server `PRINT` and low-severity `RAISERROR` text, and PostgreSQL `RAISE NOTICE` / `INFO` / `WARNING` text, now appear in **Messages** instead of being dropped. The adapters subscribe to the driver events used in the experiments above (node-mssql’s `info`, node-postgres’s `notice`) and keep every line in arrival order. Oracle `DBMS_OUTPUT` is read with the same `ENABLE` / `GET_LINES` steps. Here is what each engine gets as of version 1.5.3:

Engine

Captured

If the script fails

SQL Server

`PRINT` and `RAISERROR` with severity 10 or lower, as *Info* rows. Higher severities appear as errors.

Lines printed before the failing statement are kept, ahead of the error.

PostgreSQL

`RAISE NOTICE`, `RAISE INFO` and server notices as *Info*; `RAISE WARNING` as *Warning*. Subject to your `client_min_messages`.

Kept, ahead of the error.

Oracle

`DBMS_OUTPUT` from an anonymous `BEGIN` / `DECLARE` block, one *Info* row per line, up to 1,000 lines or 32,767 characters per block. A bare `CALL my_proc()` is not captured; run `BEGIN my_proc; END;` instead.

Not shown. The buffer is read in the same round trip as your block, after it completes, so a block that raises shows only the error.

MySQL

Nothing. Jam SQL Studio does not issue `SHOW WARNINGS`, so `SIGNAL SQLSTATE '01000'` text isn’t shown; run `SHOW WARNINGS` yourself right after the statement, or use a `SELECT`.

—

**Timing.** Jam SQL Studio does not stream messages yet. The adapters collect each line as the driver receives it, and the Messages pane is filled when the run finishes. `RAISERROR … WITH NOWAIT` and `RAISE NOTICE` reach Jam’s driver early, as the table above shows, but they don’t appear on screen before the query completes. For a long script where you need to watch progress live, look at the session from outside: the [Session Browser](/docs/session-browser/) lists running sessions on SQL Server, PostgreSQL, Oracle and MySQL, and on Oracle the `V$SESSION` module and action shown above can be queried from another connection.

**Order.** Messages lists the newest line first. When a script prints alongside several result sets, an **Output** tab appears in the result-set tab strip and keeps the server’s order, with clickable `[Result N]` markers where each result set landed. A script with no result sets shows the lines as a plain Output view under Results. The [Query Editor docs](/docs/query-editor/#print-and-raise-output) describe both views.

**Elsewhere in the app.** Tabs running in a manual transaction capture the same SQL Server and PostgreSQL output. SQL Notebook cells show it on SQL Server and PostgreSQL; an Oracle notebook cell does not capture `DBMS_OUTPUT` yet. AI agents connected over MCP can read a tab’s messages with `query_get_messages` once **Share query results** is turned on in the AI integration settings.

## How we measured

All runs were on 2026-09-26, against Docker containers on the same Linux x86\_64 machine (localhost, so network latency is well under a millisecond). Each engine got a small Node.js 22.23.2 script that loads the driver from Jam SQL Studio’s own dependency tree:

-   **SQL Server 2025 Developer** (RTM-CU8, 17.0.4075.5) with **mssql 12.2.0** over **tedious 19.1.3**. The script runs `new sql.Request(pool)` in stream mode and records `info`, `error`, `row` and `done` events. Most experiments go through `request.batch()`, and the first also through `request.query()`, which wraps the text in `sp_executesql`. Packet size is tedious’s default 4,096 bytes unless noted. The script ran twice; the second run matched the first within 10 ms.
-   **PostgreSQL 16.4 and 19beta1** with **pg 8.16.3**, recording the client’s `notice` events. A second script uses `pg.Query` row events to time individual rows. The function test uses a `pg_temp` function.
-   **Oracle AI Database 26ai Free** (23.26.2.0.0) with **oracledb 6.10.0** in Thin mode, the mode Jam SQL Studio uses. `GET_LINES` is called in a separate `execute()` on the same connection. The `DBMS_APPLICATION_INFO` test polls `V$SESSION` from a second connection every 100 ms.
-   **MySQL 8.0.46 and 9.5.0** with **mysql2 3.16.3**, `multipleStatements: true` as in Jam SQL Studio, recording the query emitter’s `fields`, `result` and `error` events. The procedures live in a throwaway database that the script creates and drops.

The Jam SQL Studio behavior described above comes from its source code (the SQL Server, PostgreSQL and Oracle query adapters and the Query Editor’s execution hook) and from its [public docs](/docs/query-editor/#print-and-raise-output), not from these scripts.

## Quick Answers

Short answers to the common questions about server messages that don’t show up.

### Q: Why does SQL Server PRINT output only show up when the query finishes?

A: SQL Server does not send PRINT messages as they happen. It queues them in the connection's output buffer with the rest of the response and sends that buffer when the batch ends or when a network packet fills. In our test a PRINT before a 3-second WAITFOR reached the client after 3.003 seconds, together with the PRINT after it. The delay happens on the server, so every client sees it; only the flush threshold depends on the packet size the client negotiates.

### Q: How do I make SQL Server send a message immediately?

A: Use RAISERROR with a severity of 0 to 10 and the NOWAIT option, for example RAISERROR('Step %d done', 0, 1, @step) WITH NOWAIT. In our test it reached the client 0.004 seconds after execution started, while the batch was still sleeping. NOWAIT also sends any PRINT output queued ahead of it, so RAISERROR('', 0, 1) WITH NOWAIT after a PRINT works as a flush.

### Q: Why is RAISE NOTICE not showing in PostgreSQL?

A: The usual cause is client\_min\_messages. PostgreSQL only sends messages at or above that level; the default is notice, and a role, database or session set to warning silently drops RAISE NOTICE while RAISE INFO still arrives, because INFO is always sent. RAISE DEBUG and RAISE LOG are below the default and never reach the client unless you lower it. The other cause is a client that does not listen for notices: they arrive as separate protocol messages, not as rows, so a driver or tool has to subscribe to them.

### Q: Why is DBMS\_OUTPUT not showing anything?

A: DBMS\_OUTPUT writes into a buffer in your database session; nothing is sent to the client on its own. The client has to call DBMS\_OUTPUT.ENABLE before the block and read the buffer with GET\_LINE or GET\_LINES afterwards, on the same session. If ENABLE was not called, PUT\_LINE calls are ignored and GET\_LINES returns zero lines. Text written with PUT and never ended with PUT\_LINE or NEW\_LINE is not returned either. Even when everything is set up, the output only becomes available after the call returns.

### Q: Does MySQL have a PRINT statement?

A: No. PRINT is a syntax error (1064) in MySQL 8.0 and 9.5. The closest equivalents are a SELECT, which a stored procedure sends to the client as soon as that result set is complete, and SIGNAL SQLSTATE '01000', which raises a warning whose text you only see by running SHOW WARNINGS afterwards, and only if no later statement cleared it.

### Q: Does Jam SQL Studio show messages while the query is still running?

A: No. As of version 1.5.3, Jam SQL Studio collects PRINT, RAISERROR, RAISE NOTICE and DBMS\_OUTPUT lines in the order the driver receives them and shows them in Messages when the run finishes. RAISERROR WITH NOWAIT and RAISE NOTICE still arrive early at the driver level, but the Messages pane does not stream them yet.

## Summary

Only two of the four mechanisms send text while the code is running: `RAISERROR … WITH NOWAIT` on SQL Server and `RAISE NOTICE` on PostgreSQL. Plain `PRINT` waits for the end of the batch or a full packet. `DBMS_OUTPUT` waits until the call returns and the client reads it. MySQL’s nearest option is a `SELECT`, which it sends as each result set completes. When output is missing rather than late, check the setup: `client_min_messages` on PostgreSQL, `ENABLE` and the session on Oracle, and `SHOW WARNINGS` on MySQL.

### Server Messages in One Place

SQL Server `PRINT`, PostgreSQL `RAISE NOTICE` and Oracle `DBMS_OUTPUT` in the Messages pane, with an Output view that keeps the server’s order. Free for personal use.

[Download Free](/#download) [Where PRINT Output Lands](/docs/query-editor/#print-and-raise-output)

### Related

-   [Query Editor: PRINT and RAISE Output](/docs/query-editor/#print-and-raise-output)
-   [T-SQL vs PL/pgSQL](/docs/t-sql-vs-plpgsql/)
-   [Convert Stored Procedures to PostgreSQL](/blog/2026-06-14-convert-sql-server-stored-procedures-to-postgresql/)
-   [PL/SQL Debugger](/docs/plsql-debugger/)
-   [Session Browser](/docs/session-browser/)

## See PRINT, RAISE NOTICE and DBMS\_OUTPUT in One Messages Pane

Jam SQL Studio captures SQL Server PRINT and low-severity RAISERROR, PostgreSQL RAISE NOTICE / INFO / WARNING, and Oracle DBMS\_OUTPUT from anonymous blocks, and keeps them in server order in the Output view.

[Download Jam SQL Studio Free](/#download) [Where PRINT output lands](/docs/query-editor/#print-and-raise-output)

Free for personal use • No account required • Mac, Windows, Linux