debugsqlModerate
Why doesn't this invalid subquery raise a syntax error?
Viewed 0 times
thiswhyerrorsyntaxdoesnsubqueryraiseinvalid
Problem
Is there any explanation so as to why SSMS did not raise any compilation error for the below delete query with a subquery that is invalid on its own?
Below is the sequence of steps to reproduce the behavior:
Seed data:
Create a backup table:
Below statement should ideally not execute and, even if it executes, should only delete rows with
The message shows that 5 rows were deleted, but I expected only 3 rows to be deleted:
Attempt to execute the sub-query as a standalone fails :
Invalid column name 'id'
Below one executes as expected :
Output :
Below is the sequence of steps to reproduce the behavior:
CREATE TABLE [dbo].[delete_test]
(
[id] [int] IDENTITY(1,1) NOT NULL,
[name] [nchar](10) NOT NULL
) ON [PRIMARY];Seed data:
insert dbo.delete_test(name) values(N'a'),(N'b'),(N'c'),(N'd'),(N'e');Create a backup table:
select id, name
into dbo.delete_test_backup
from dbo.delete_test where id > 2;Below statement should ideally not execute and, even if it executes, should only delete rows with
id values that have been backed up :delete dbo.delete_test where id in (
select id delete_test_backup
);The message shows that 5 rows were deleted, but I expected only 3 rows to be deleted:
(5 row(s) affected)Attempt to execute the sub-query as a standalone fails :
select id delete_test_backup ;Invalid column name 'id'
Below one executes as expected :
select id from dbo.delete_test_backup ;Output :
id
--
3
4
5Solution
This is the same as:
In other words, you have merely assigned a column alias to
According to the ANSI standard, what SQL Server is supposed to do in this case - when it has a subquery and does not find
See:
* Microsoft decided to eradicate all of Connect instead of archiving the content, and also disappeared the knowledge base article for some reason.
To avoid the problem, always use table aliases, which allow you to be 100% explicit about which table a column comes from (not naming every key column
(
SELECT id AS delete_test_backup
)In other words, you have merely assigned a column alias to
id, and there is no reference at all to a table called delete_test_backup.According to the ANSI standard, what SQL Server is supposed to do in this case - when it has a subquery and does not find
id at that scope - is traverse to the outer scope(s) until it finds one. If it does, it assumes that's the one you meant.See:
- Best practices : Properly referencing columns
- KB #298674
- Connect #735178
- Connect #624370
- Connect #392492
- Connect #362016
- Connect #265772
- Connect #772612
* Microsoft decided to eradicate all of Connect instead of archiving the content, and also disappeared the knowledge base article for some reason.
To avoid the problem, always use table aliases, which allow you to be 100% explicit about which table a column comes from (not naming every key column
id helps, too). Of course you can leave these prefixes out accidentally, just like you left out the FROM, but the following syntax would have failed as you expect, and most other omissions would have left you with a parsing error rather than accidental execution:(
SELECT x.id FROM delete_test_backup AS x
)Code Snippets
(
SELECT id AS delete_test_backup
)(
SELECT x.id FROM delete_test_backup AS x
)Context
StackExchange Database Administrators Q#163647, answer score: 10
Revisions (0)
No revisions yet.