-- and /* */ both comment out T-SQL. The difference is where they stop.
/* */ stops where you close it. -- runs to the end of the line,[2] and if there is no end of the line, it does not stop.

Building a statement in pieces
Generated SQL is usually assembled from fragments. Here is the same statement built twice, once with each comment style, joined with a space rather than a line break:
|
|
DECLARE @with_double_hyphen nvarchar(max); DECLARE @with_block_comment nvarchar(max); DECLARE @row_count int; SET @with_double_hyphen = N'SELECT @out = COUNT_BIG(1) FROM [sys].[all_objects] ' + N'-- restrict to user tables ' + N'WHERE [type] = ''U'';'; SET @with_block_comment = N'SELECT @out = COUNT_BIG(1) FROM [sys].[all_objects] ' + N'/* restrict to user tables */ ' + N'WHERE [type] = ''U'';'; |
Printed out, the difference looks harmless:
|
|
SELECT @out = COUNT_BIG(1) FROM [sys].[all_objects] -- restrict to user tables WHERE [type] = 'U'; SELECT @out = COUNT_BIG(1) FROM [sys].[all_objects] /* restrict to user tables */ WHERE [type] = 'U'; |
Both are valid T-SQL. Both execute without error. They do not do the same thing.
|
|
EXEC [sys].[sp_executesql] @with_double_hyphen , N'@out int OUTPUT' , @out = @row_count OUTPUT; |
On SQL Server 2019 the double-hyphen version returned 2,448.[3] The block comment version returned 25. On SQL Server 2025, 2,738 against 2.
The WHERE clause is inside the comment. The query counted every object rather than user tables, and reported a number roughly a hundred times too large. No error was raised.
Why this is worse than a syntax error
A syntax error stops the batch and names a line. This does not.
The statement is well formed. It compiles, runs, returns a single integer, and that integer looks like a plausible row count. Nothing downstream can tell it apart from a correct answer. If it feeds an alert threshold, a capacity report, or a conditional branch, the wrong number propagates.
The failure also depends on how the text was assembled rather than on the logic, so it will not reproduce when you paste the query into a new window and run it with the line breaks intact.
Where the line breaks go missing
This does not require anyone to write deliberately terrible code. It happens when text moves through something that treats it as a single string.
Concatenation without CHAR(13). The example above. Fragments joined with a space because that reads naturally when you write it.
Column output that strips line endings. Copying generated SQL out of a grid, an application log, or a message column can flatten it.
Line ending damage in transit. Files that lose their line endings between systems produce exactly this shape. I have written about how easily that happens to .sql files in Your AI Agent Is Quietly Corrupting Your SQL Files.
Minifiers and formatters. Anything that normalizes whitespace can join lines.
In every case, /* */ survives and -- does not.
The other reason
Even in hand-written code that never gets concatenated, -- has a smaller version of the same property.
|
|
WHERE [o].[order_date] >= @start_date -- inclusive AND [o].[order_date] < @end_date; |
Add a trailing comment to a line, then later join those two lines while editing, and the AND disappears into the comment. The query still runs, over a wider date range than intended.
/* */ cannot do that. Its end is explicit, so moving the text around cannot extend it.
The rule
Use /* */ everywhere. Convert -- comments when you touch a file that has them.
|
|
/* Restrict to user tables */ WHERE [o].[type] = 'U'; |
It costs two extra characters and removes a class of failure that produces wrong answers rather than errors.
One practical note: /* */ does nest in T-SQL, so a block comment wrapping code that already contains one behaves as you would expect. That is not true in every SQL dialect, and it is worth checking before relying on it elsewhere.[1]
This is one of a series on the T-SQL conventions I actually use and why. Also in it: ISNULL Truncates Your Replacement Value; COALESCE Doesn’t and One NULL in the List and NOT IN Returns Nothing.
Have you had generated SQL comment out part of itself? I would like to hear how it surfaced. Bluesky or LinkedIn.
References
- Slash Star (Block Comment) (Transact-SQL) - Microsoft Learn. Covers the explicit terminator, multi-line block comments, and nesting behaviour. ↩
- Double Hyphen (Comment) (Transact-SQL) - Microsoft Learn. States that the comment runs to the end of the line, which is the behaviour the concatenated example depends on. ↩
- sp_executesql (Transact-SQL) - Microsoft Learn. Used here to execute the generated statement with an OUTPUT parameter. ↩
Related
Double-Hyphen Comments Can Comment Out Your WHERE Clause
--and/* */both comment out T-SQL. The difference is where they stop./* */stops where you close it.--runs to the end of the line,[2] and if there is no end of the line, it does not stop.Building a statement in pieces
Generated SQL is usually assembled from fragments. Here is the same statement built twice, once with each comment style, joined with a space rather than a line break:
Printed out, the difference looks harmless:
Both are valid T-SQL. Both execute without error. They do not do the same thing.
On SQL Server 2019 the double-hyphen version returned 2,448.[3] The block comment version returned 25. On SQL Server 2025, 2,738 against 2.
The
WHEREclause is inside the comment. The query counted every object rather than user tables, and reported a number roughly a hundred times too large. No error was raised.Why this is worse than a syntax error
A syntax error stops the batch and names a line. This does not.
The statement is well formed. It compiles, runs, returns a single integer, and that integer looks like a plausible row count. Nothing downstream can tell it apart from a correct answer. If it feeds an alert threshold, a capacity report, or a conditional branch, the wrong number propagates.
The failure also depends on how the text was assembled rather than on the logic, so it will not reproduce when you paste the query into a new window and run it with the line breaks intact.
Where the line breaks go missing
This does not require anyone to write deliberately terrible code. It happens when text moves through something that treats it as a single string.
Concatenation without
CHAR(13). The example above. Fragments joined with a space because that reads naturally when you write it.Column output that strips line endings. Copying generated SQL out of a grid, an application log, or a message column can flatten it.
Line ending damage in transit. Files that lose their line endings between systems produce exactly this shape. I have written about how easily that happens to
.sqlfiles in Your AI Agent Is Quietly Corrupting Your SQL Files.Minifiers and formatters. Anything that normalizes whitespace can join lines.
In every case,
/* */survives and--does not.The other reason
Even in hand-written code that never gets concatenated,
--has a smaller version of the same property.Add a trailing comment to a line, then later join those two lines while editing, and the
ANDdisappears into the comment. The query still runs, over a wider date range than intended./* */cannot do that. Its end is explicit, so moving the text around cannot extend it.The rule
Use
/* */everywhere. Convert--comments when you touch a file that has them.It costs two extra characters and removes a class of failure that produces wrong answers rather than errors.
One practical note:
/* */does nest in T-SQL, so a block comment wrapping code that already contains one behaves as you would expect. That is not true in every SQL dialect, and it is worth checking before relying on it elsewhere.[1]This is one of a series on the T-SQL conventions I actually use and why. Also in it: ISNULL Truncates Your Replacement Value; COALESCE Doesn’t and One NULL in the List and NOT IN Returns Nothing.
Have you had generated SQL comment out part of itself? I would like to hear how it surfaced. Bluesky or LinkedIn.
References
Share this:
Related