patternsqlMinor
Extraordinarily inconsistent behavior from Sql Server regarding cached table definitions
Viewed 0 times
cachedinconsistentsqlbehaviorregardingextraordinarilyserverfromtabledefinitions
Problem
Pre-warning: This question may not make sense at first blush, hopefully though anyone can play along by trying this out on their local Sql Server instance.
With all that in mind, consider two scripts:
And the oddness that is
`Drop Table If Exists #Temp;
Select A
,B
,C
,D
,E
,F
,G
Into #Temp
From dbo.MyMysteryTable;
Drop Table If Exists dbo.MyMysteryTable;
Create Table dbo.MyMysteryTable
(
A SmallInt Not Null
,B VarChar(32) Not Null
,Cx VarChar(128) Not Null
,D SmallDateTime Null
,E SmallInt Not Null
,F Char(1) Not Null
,G VarChar(16) Not Null
);
-- Insert #1
Insert dbo.MyMysteryTable(A, B, Cx, D, E, F, G)
Select *
From #Temp;
With all that in mind, consider two scripts:
Create.sql:Drop Table If Exists dbo.MyMysteryTable;
Create Table dbo.MyMysteryTable
(
A SmallInt Not Null
,B VarChar(32) Not Null
,C VarChar(128) Not Null
,D SmallDateTime Null
,E SmallInt Not Null
,F Char(1) Not Null
,G VarChar(16) Not Null
);
Insert dbo.MyMysteryTable(A, B, C, D, E, F, G)
Values (1, 'B1', 'C1', Null, 1, '1', 'G1')
,(2, 'B2', 'C2', Null, 2, '2', 'G2');
And the oddness that is
WTF.sql (a script where I'm basically rebuilding the table and renaming column C to Cx and then adding a new row to it.):`Drop Table If Exists #Temp;
Select A
,B
,C
,D
,E
,F
,G
Into #Temp
From dbo.MyMysteryTable;
Drop Table If Exists dbo.MyMysteryTable;
Create Table dbo.MyMysteryTable
(
A SmallInt Not Null
,B VarChar(32) Not Null
,Cx VarChar(128) Not Null
,D SmallDateTime Null
,E SmallInt Not Null
,F Char(1) Not Null
,G VarChar(16) Not Null
);
-- Insert #1
Insert dbo.MyMysteryTable(A, B, Cx, D, E, F, G)
Select *
From #Temp;
Solution
The reason that the following succeeds (if you comment out Insert 2)...
Is because
By the time the statement is recompiled (just before execution) the column exists in
For statements like this that both would cause compilation errors due to referencing non existent columns in existing objects and are eligible for deferred compile as they also reference entirely non existent objects I've previously found it a bit "hit and miss" whether you will get the compile time error before compilation is deferred.
e.g. below the reference to the non existent table is sufficient to "save" statement 1 but statement 2 still throws a compile time error despite it.
-- Insert #1
Insert dbo.MyMysteryTable(A, B, Cx, D, E, F, G)
Select *
From #Temp;Is because
#Temp does not exist when the batch is compiled so the statement is subject to deferred compile.By the time the statement is recompiled (just before execution) the column exists in
MyMysteryTable so there is no problem.For statements like this that both would cause compilation errors due to referencing non existent columns in existing objects and are eligible for deferred compile as they also reference entirely non existent objects I've previously found it a bit "hit and miss" whether you will get the compile time error before compilation is deferred.
e.g. below the reference to the non existent table is sufficient to "save" statement 1 but statement 2 still throws a compile time error despite it.
DROP TABLE IF EXISTS dbo.T1, #T1;
CREATE TABLE dbo.T1(C1 INT);
GO
CREATE TABLE #T1(C1 INT);
ALTER TABLE dbo.T1 ADD C2 INT;
/* Statement 1
SELECT T1.C2
FROM dbo.T1
WHERE NOT EXISTS(SELECT * FROM #T1)
*/
/* Statement 2
SELECT A.C2
FROM dbo.T1 A
JOIN dbo.T1 B
ON A.C2 = B.C2
WHERE NOT EXISTS(SELECT * FROM #T1)
*/Code Snippets
-- Insert #1
Insert dbo.MyMysteryTable(A, B, Cx, D, E, F, G)
Select *
From #Temp;DROP TABLE IF EXISTS dbo.T1, #T1;
CREATE TABLE dbo.T1(C1 INT);
GO
CREATE TABLE #T1(C1 INT);
ALTER TABLE dbo.T1 ADD C2 INT;
/* Statement 1
SELECT T1.C2
FROM dbo.T1
WHERE NOT EXISTS(SELECT * FROM #T1)
*/
/* Statement 2
SELECT A.C2
FROM dbo.T1 A
JOIN dbo.T1 B
ON A.C2 = B.C2
WHERE NOT EXISTS(SELECT * FROM #T1)
*/Context
StackExchange Database Administrators Q#323034, answer score: 4
Revisions (0)
No revisions yet.