HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

Extraordinarily inconsistent behavior from Sql Server regarding cached table definitions

Submitted by: @import:stackexchange-dba··
0
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:

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)...

-- 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.