This article has been archived. It is offered "as is" and will no longer be updated.
SQL Server Books Online states that ownership chains are checked for stored procedures and views that cross databases. You can see this easily when the owner of the dependent objects in each database maps to the same login. However, if you have users in both databases that have the same user name, but are not mapped to the same login (as often happens with the database owner [DBO]), it may seem that the ownership chains are being incorrectly checked. For example, if the DBO of each database is mapped to the same login, and the owner of the objects in the databases is the DBO, permissions are not checked. However, if the DBO of each database is mapped to a different login, the ownership chains are checked. This can happen with users other than the DBO if your user names are different from your login names.
A user in a database can be granted permissions on a view or stored procedure. If that view or stored procedure accesses objects in another database which is owned by a user mapped to a different login, the permissions of the underlying objects are checked. If the user does not have permissions to the objects in the other database, the following error is returned:
However, if the underlying mapped login of objects in the query is the same, permissions are not checked, and the query executes without the above error even if the user does not have permissions to the underlying tables.
To see an example of this, follow these steps:
Set up a reproduction environment with two different databases; db1 is the "Base" database with the data and db2 contains a view that selects from the table in db1.
USE masterGOCREATE DATABASE db1CREATE DATABASE db2EXEC sp_addlogin Owner1EXEC sp_addlogin Owner2EXEC sp_addlogin TestUserGO-- setup database #1, DBO is Owner1USE db1EXEC sp_changedbowner Owner1EXEC sp_adduser TestUserCREATE TABLE BaseTable (TableColumn CHAR(20))INSERT BaseTable VALUES ('Select Succeeded')GO-- setup database #2USE db2EXEC sp_adduser TestUserGOCREATE VIEW CrossDatabaseView AS SELECT * FROM db1.dbo.BaseTableGOGRANT SELECT ON CrossDatabaseView TO publicGO
Execute the following code to see the different results based on whether the DBO is the same or different:
SET NOCOUNT ONGOPRINT '***** results with both DBOs the same *****'PRINT ''USE db2EXEC sp_changedbowner Owner1SETUSER 'TestUser'GOSELECT * FROM CrossDatabaseViewGOSETUSERGOPRINT ''PRINT '***** results with each DBO different *****'PRINT ''USE db2EXEC sp_changedbowner Owner2SETUSER 'TestUser'GOSELECT * FROM CrossDatabaseViewGOSETUSERGO
Clean up the databases and logins created for this example: