Troubleshooting Guide: SQL Server Error 166
Why This Error Happens
Error 166 occurs when a Transact-SQL statement—commonly CREATE VIEW, CREATE PROCEDURE, CREATE FUNCTION, or CREATE TRIGGER—references an object using a three-part or four-part naming convention (e.g., DatabaseName.SchemaName.ObjectName) in a context where SQL Server’s parser strictly requires a two-part name (SchemaName.ObjectName). This is a syntax restriction rather than a permissions or connectivity issue; SQL Server 2025 enforces this rule because certain DDL statements are scoped to the current database context only and cannot resolve cross-database prefixes at compile time. It frequently surfaces after migrating legacy scripts from older SQL Server versions or when copy-pasted code retains a hardcoded database prefix that is no longer valid in the target environment.
Step-by-Step Resolution Guide
Step 1: Identify the Offending Statement
- Open the exact script or stored procedure definition that triggered Error 166 in SSMS or Azure Data Studio.
- Look for
CREATE VIEW,CREATE PROC,CREATE FUNCTION, orCREATE TRIGGERstatements. - Search specifically for object references formatted as
DatabaseName.dbo.TableNameorDatabaseName.SchemaName.ObjectName.
Step 2: Remove the Database Name Prefix
- Edit the statement to strip the leading database name, leaving only
SchemaName.ObjectName(e.g., changeMyDB.dbo.Customerstodbo.Customers). - Ensure you run a
USE [DatabaseName];statement immediately before theCREATEstatement so SQL Server executes it in the correct database context. - Save the corrected script to a
.sqlfile for version control before re-execution.
Step 3: Re-Execute the Script in the Correct Context
- In SSMS, confirm the active database dropdown (top toolbar) matches the target database before running the query.
- Execute the corrected script:
USE [YourDatabaseName];
GO
CREATE VIEW dbo.vw_Sample AS SELECT * FROM dbo.SourceTable;
GO
- If the error persists, check for nested references inside the view/procedure body that may also carry an illegal prefix.
Step 4: Audit Related Objects for the Same Pattern
- Run a metadata search using
sys.sql_modulesto catch other objects with the same bad pattern:
SELECT OBJECT_NAME(object_id), definition
FROM sys.sql_modules
WHERE definition LIKE '%YourDatabaseName.%';
- Correct and redeploy any additional objects found using the same two-part naming fix from Step 2.
Alternative or Verification Steps
- Verify the fix by re-running
sp_helptext 'ObjectName'or queryingsys.objectsto confirm the object was created successfully without error. - If the object must reference data in another database, use a fully qualified name only inside the query body (e.g., inside a
SELECTstatement) rather than in theCREATEheader, since cross-database references are permitted in DML but not in the object’s naming declaration.