If I understand you correctly, your question is why the CATCH block does not catch the error with the misspelled table name.
This is a sore point with error handling in SQL Server. (And, not is the only sore point. Sigh. There are quite a few.)
You cannot catch compilation errors in the scope they occur. In a way that make sense, since compilation errors usually are raised before you enter the scope.... But:
CREATE PROCEDURE MyBadSp AS
BEGIN TRY
PRINT 'Starting'
SELECT * FROM NoSuchTable
END TRY
BEGIN CATCH
PRINT 'This is not printed'
END CATCH
go
EXEC MyBadSp
go
DROP PROCEDURE MyBadSp
When you run this, the output is:
Starting Msg 208, Level 16, State 1, Procedure MyBadSp, Line 4 [Batch Start Line 9]
Invalid object name 'NoSuchTable'.
Because of deferred name resolution, the error is not detected at run-time. But you cannot still catch the error. Why? Ask Microsoft.
Note that you can catch these type of errors in an outer scope:
CREATE PROCEDURE MyBadSp AS
BEGIN TRY
PRINT 'Starting'
SELECT * FROM NoSuchTable
END TRY
BEGIN CATCH
PRINT 'This is not printed'
END CATCH
go
CREATE PROCEDURE MyOuterSP AS
BEGIN TRY
PRINT 'Starting Outer'
EXEC MyBadSp
PRINT 'This does not print'
END TRY
BEGIN CATCH
PRINT 'Caught: ' + error_message()
END CATCH
go
EXEC MyOuterSP
go
DROP PROCEDURE MyBadSp, MyOuterSP
This prints:
Starting Outer Starting Caught: Invalid object name 'NoSuchTable'