SQL Server error 207
Invalid column name (SQL Server error 207)
SQL Server couldn’t find a column with that name in the tables your statement uses. Usually it’s a typo or the wrong table, but a string in double quotes, a SELECT alias used in WHERE, and a column added earlier in the same batch all give the same error.
Invalid column name 'ownr'.
Tested on SQL Server 2022 (16.0.4295.3); also 2019 (15.0.4490.9) and 2025 (17.0.5005.3) · Updated 9 October 2026
What it means
When SQL Server compiles a statement, it looks up every column name in the tables, views and derived tables the statement names. Error 207 means one of them isn’t there, as written. The message gives the name it looked for:
Msg 207, Level 16, State 1, Line 1
Invalid column name 'ownr'.
The error comes at compile time, so the statement (and, for some causes, the whole batch) doesn’t run at all: nothing is half-done.
Common causes
- A typo, or the column is in another table.
o.ownerwhenowneris inaccounts, notorders. - A string in double quotes. With
QUOTED_IDENTIFIER ON(the default for most drivers),"open"is a column name, not a string. Strings take single quotes:'open'. - A
SELECTalias used inWHERE,GROUP BYorHAVING. SQL Server evaluatesWHEREbefore theSELECTlist, so the alias doesn’t exist yet. (ORDER BYruns afterSELECT, so aliases work there.) - A column added in the same batch.
ALTER TABLE … ADD notefollowed by a statement that usesnotein one batch fails: the whole batch is compiled before theALTERruns. - Case, on a case-sensitive database. With a
_CS_or_BINcollation,totalandTotalare different columns. - The schema changed under your code: a renamed or dropped column, or a different version of the database than you think.
How to fix it
Check the column’s real name and table
SELECT c.name AS column_name, TYPE_NAME(c.user_type_id) AS type_name
FROM sys.columns AS c
WHERE c.object_id = OBJECT_ID('dbo.orders')
ORDER BY c.column_id;
EXEC sp_help 'dbo.orders'; shows the same and more. In a join, prefix every column with its
table’s alias, so a column in the wrong table fails clearly and a column in both doesn’t become
ambiguous.
Put strings in single quotes
SELECT id, total FROM orders WHERE status = 'open'; -- not "open"
Double quotes are for identifiers: "order date" is the same as [order date]. sqlcmd is the
exception: it starts with QUOTED_IDENTIFIER OFF unless you pass -I, so "open" works there as
a string and then fails in your application. Don’t rely on it.
Repeat the expression, or wrap the query
Either repeat the expression in WHERE:
SELECT id, total * 1.2 AS gross FROM orders WHERE total * 1.2 > 20;
or compute it in a derived table (or CROSS APPLY, or a CTE) and filter outside:
SELECT id, total, gross
FROM (SELECT id, total, total * 1.2 AS gross FROM orders) AS o
WHERE gross > 20;
Split the batch after ALTER TABLE
Put the ALTER TABLE in its own batch (GO after it, in tools that understand GO), or run the
later statement through EXEC so it’s compiled after the column exists:
ALTER TABLE orders ADD note varchar(50) NULL;
GO
UPDATE orders SET note = 'checked';
Match the case on case-sensitive databases
Check the collation, and write names exactly as they were created:
SELECT DATABASEPROPERTYEX(DB_NAME(), 'Collation') AS collation;
A collation with _CS_ (case-sensitive) or _BIN/_BIN2 (binary) makes identifiers
case-sensitive in that database.
Reproduce it
On SQL Server 2022 (RTM-CU27, 16.0.4295.3), tables seo_sqlerr_conn.accounts (id, owner, balance)
and seo_sqlerr_conn.orders (id, account_id, total, status), with sqlcmd -I
(QUOTED_IDENTIFIER ON), one statement per batch:
SELECT ownr FROM seo_sqlerr_conn.accounts;
SELECT id, total FROM seo_sqlerr_conn.orders WHERE status = "open";
SELECT id, total * 1.2 AS gross FROM seo_sqlerr_conn.orders WHERE gross > 20;
SELECT o.id, o.owner FROM seo_sqlerr_conn.orders AS o JOIN seo_sqlerr_conn.accounts AS a ON a.id = o.account_id;
Msg 207, Level 16, State 1, Server 7732422b7f56, Line 1
Invalid column name 'ownr'.
Msg 207, Level 16, State 1, Server 7732422b7f56, Line 1
Invalid column name 'open'.
Msg 207, Level 16, State 1, Server 7732422b7f56, Line 1
Invalid column name 'gross'.
Msg 207, Level 16, State 1, Server 7732422b7f56, Line 1
Invalid column name 'owner'.
An ALTER TABLE and an UPDATE of the new column in one batch, inside a transaction:
BEGIN TRAN;
ALTER TABLE seo_sqlerr_conn.orders ADD note varchar(50) NULL;
UPDATE seo_sqlerr_conn.orders SET note = 'checked';
ROLLBACK;
Msg 207, Level 16, State 1, Server 7732422b7f56, Line 3
Invalid column name 'note'.
None of the batch ran: afterwards @@TRANCOUNT was 0 and COL_LENGTH('seo_sqlerr_conn.orders', 'note') was NULL, so even the ALTER hadn’t happened. The derived-table version of the alias
query returned rows 1 and 2. With SET QUOTED_IDENTIFIER OFF, status = "open" returned rows 2 and
3. And sqlcmd without -I reported QUOTED_IDENTIFIER as 0 for the session.
On a temporary SQL Server 2022 container, in a database created with Latin1_General_100_CS_AS and a
table dbo.Orders (Id, Total), SELECT Id, total FROM dbo.Orders got
Invalid column name 'total'. (and dbo.orders got
error 208). SQL Server 2019 (15.0.4490.9) and 2025
(17.0.5005.3) gave the same errors.
In Inlet
Inlet’s sidebar reads schemas, tables and views from SQL Server’s system views, and a table’s
definition (its CREATE TABLE) shows every column’s exact name and case. Query tabs run T-SQL a batch at a time and GO splits batches, so an
ALTER TABLE followed by GO works there as it does in sqlcmd. With your own Anthropic API key,
Ask Claude (⌘L) writes T-SQL from the schema. When a statement fails with 207, the error links to
this page.