InletDownload

SQL Server error 102

Incorrect syntax near

SQL Server couldn’t parse the batch, so none of it ran. The quoted text is where the parser gave up, which is often right after the real mistake; most often it’s syntax from MySQL or PostgreSQL, or a batch separator problem.

Incorrect syntax near 'LIMIT'.

Tested on SQL Server 2022 RTM-CU27 (16.0.4295.3); same messages on 2019 RTM-CU32-GDR and 2025 RTM-CU9, except where noted · Updated 9 October 2026

What it means

SQL Server parses a whole batch before running any of it. Error 102 means the parser reached a piece of text that can’t come next in T-SQL, so the batch was rejected and nothing in it ran, not even the statements before the mistake.

Msg 102, Level 15, State 1, Server 7732422b7f56, Line 1
Incorrect syntax near 'LIMIT'.

The text in quotes is where parsing failed, and Line counts from the start of the batch (not the file). The actual mistake is often right before that point: LIMIT 10 without an ORDER BY fails near '10', because SQL Server first reads LIMIT as a table alias.

Related messages come from the same parser: 156 Incorrect syntax near the keyword '…' when the unexpected word is a reserved word, 105 Unclosed quotation mark after the character string, 111 for CREATE PROCEDURE in the wrong place and 319 for a WITH that needs a semicolon before it.

Common causes

  1. Syntax from another database. The usual suspects, and what SQL Server says:

    WrittenError on SQL ServerT-SQL
    … LIMIT 10102 near '10' or 'LIMIT'SELECT TOP (10) …, or ORDER BY … OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY
    `name`102 near '`'[name] or "name"
    a || b102 near '|' (2019, 2022)CONCAT(a, b) or a + b; SQL Server 2025 accepts ||
    INSERT … RETURNING id102 near 'RETURNING'INSERT … OUTPUT inserted.id VALUES …
    id int AUTO_INCREMENT102 near 'AUTO_INCREMENT'id int IDENTITY(1,1)
    WHERE name = "Ada"207 Invalid column name 'Ada'WHERE name = 'Ada'
    x::text243 Type x is not a defined system type.CAST(x AS nvarchar(…))
    ILIKE, WHERE TRUE4145 An expression of non-boolean type …LIKE (case-insensitive under the usual default collations), WHERE 1 = 1
  2. GO sent to the server. GO isn’t T-SQL: sqlcmd, SSMS and other tools split a script into batches there and never send it. A driver or ORM that sends a script containing GO gets Incorrect syntax near 'GO'.

  3. CREATE PROCEDURE, VIEW, FUNCTION or TRIGGER after other statements in the same batch. These must each be alone in their batch: error 111, 'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.

  4. A missing semicolon before WITH or THROW. T-SQL rarely needs semicolons, but the statement before a common table expression (WITH x AS (…)) or a THROW must end with one. Without it you get 319 for WITH, and 102 near 'THROW'.

  5. An apostrophe inside a string: 'O'Brien' ends the string after O (102 near 'Brien', then 105 for the quote left open).

  6. Typos: a missing or extra comma (SELECT id, name, FROM gives 156 near the keyword 'FROM'), an unclosed parenthesis, a reserved word such as order or user used as a column name without brackets.

How to fix it

Translate the other dialect

Use the T-SQL column from the table above. For paging, OFFSET … FETCH needs an ORDER BY:

SELECT id, name
FROM dbo.shoppers
ORDER BY id
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

Quote identifiers with square brackets ([order]), or with double quotes while QUOTED_IDENTIFIER is on (the default). With it off, double quotes make a string, so "name" returns the text name and FROM "dbo"."shoppers" fails with 102. Strings always take single quotes, with an apostrophe doubled: 'O''Brien'.

Split batches yourself when you can’t use GO

If your code runs a script through a driver, split it on lines that contain only GO and send each part as its own batch, or put each CREATE PROCEDURE/VIEW/FUNCTION in its own call. Inside a batch, EXEC (N'CREATE VIEW …') also gives the CREATE a batch of its own (in the test below, a PRINT, then that EXEC, then a SELECT from the new view ran as one batch).

Put the CREATE first

In a script run by sqlcmd or SSMS, put GO before (and after) each CREATE PROCEDURE, VIEW, FUNCTION and TRIGGER:

DROP PROCEDURE IF EXISTS dbo.get_shopper;
GO
CREATE PROCEDURE dbo.get_shopper @id int AS
  SELECT id, name FROM dbo.shoppers WHERE id = @id;
GO

CREATE OR ALTER PROCEDURE (SQL Server 2016 SP1 and later) removes the need for the DROP, but it still has to be first in its batch.

End the statement before WITH and THROW

Terminate the previous statement, or every statement, with a semicolon:

DECLARE @n int = 1;
WITH totals AS (
  SELECT shopper_id, SUM(total) AS spent FROM dbo.purchases GROUP BY shopper_id
)
SELECT * FROM totals;
BEGIN CATCH
  PRINT 'failed';
  THROW;
END CATCH

Writing ;WITH at the start of the line works too, and is common in older code.

Reproduce it

On SQL Server 2022 (16.0.4295.3) with sqlcmd:

SELECT * FROM seo_sqlerr_data.shoppers LIMIT 10;
SELECT * FROM seo_sqlerr_data.shoppers ORDER BY id LIMIT 10;
SELECT `name` FROM seo_sqlerr_data.shoppers;

each in its own batch:

Msg 102, Level 15, State 1, Server 7732422b7f56, Line 1
Incorrect syntax near '10'.
Msg 102, Level 15, State 1, Server 7732422b7f56, Line 1
Incorrect syntax near 'LIMIT'.
Msg 102, Level 15, State 1, Server 7732422b7f56, Line 1
Incorrect syntax near '`'.

name || '!' failed near '|' on SQL Server 2019 and 2022, and returned Ada! on SQL Server 2025 (17.0.5005.3). A batch containing GO, sent to the server as text with EXEC (@batch), the way a driver would send it:

Msg 102, Level 15, State 1, Server 7732422b7f56, Line 2
Incorrect syntax near 'GO'.

CREATE PROCEDURE after a DROP PROCEDURE IF EXISTS in the same batch, and a CTE after a SELECT with no semicolon:

Msg 111, Level 15, State 1, Server 7732422b7f56, Procedure get_shopper, Line 3
'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.
Msg 319, Level 15, State 1, Server 7732422b7f56, Line 2
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.

CREATE VIEW and CREATE FUNCTION after a PRINT gave 'CREATE VIEW' must be the first statement in a query batch. and the same for 'CREATE FUNCTION'. A TRY … CATCH whose catch block had PRINT 'failed' and THROW without a semicolon failed with 102 near 'THROW', and the SELECT 1 / 0 in its TRY block never ran; with the semicolon, it printed failed and re-raised the divide-by-zero error. SQL Server 2019 and 2025 printed the same messages, apart from ||.

In Inlet

Query tabs run T-SQL a batch at a time and split batches at GO (and GO 5 runs a batch five times), so a script with GO between its batches runs as it is. When SQL Server refuses a batch, Inlet shows its message with SQL Server error 102, state 1, severity 15 and links to this page. With your own Anthropic API key, Ask Claude (⌘L) writes T-SQL, so it can translate a MySQL or PostgreSQL query for you; it sends the schema and the SQL, never rows.

Related

Sources