I am using SQL Server 2017. I am in the role of sa
for the server in question. I have two databases that are used in an ETL process. The ETL is coded in one database, and the raw imported tables are located in the staging database. All ETL is handled in SQL stored procedures that follow a pattern. The first step in each ETL SP is a call to a diagnostics table in the staging database.
My current ETL job is a wrapper around two of these ETL sps; the wrapper itself contains only code that accesses the main db. The first SP can be called and successfully selects the data from the staging db, however, the second SP that has identical code up to the point of failure with the first, fails on accessing the diagnostics table and tells me
The server principal "sa" is not able to access the database "staging" under the current security context.
The problem stays if I comment out the first SP call, so something must be different in the definition of the two SPs, but I cannot spot it. There are plenty of SPs that use the diagnostics staging table, so it is not a general problem (as stated in answers to similar questions that suggest changing security options in the staging database), but must be related to the new SP somehow.
Any suggestions?
CodePudding user response:
There are three things to check/do.
First of all, the login associated with the user in database DB1
must also be associated with a user in DB2
. This provides the login with a security context in database DB2
. The sa
login will map to dbo
in both databases, so this should already be fine.
Second, the security context of the code being executed in DB1
must be "trustworthy". In other words, when the user context goes from DB1
back up to the server level and then down into DB2
via the cross-database call, the new user context has to trust the original login. There are two ways to do this, the quick and dirty and opens-up-possible-security-holes way, and the more complicated but safer way:
Quick and not entirely safe: alter database DB1 set trustworthy on
.
Safe: Use signed modules
Third, in the general case you should check that the owner of DB1
and the owner of DB2
are the same (otherwise you can't cross database ownership chain): select owner_sid from sys.databases where name in ('DB1', 'DB2')
But as with the first point, as a sysadmin you can take ownership of anything.
CodePudding user response:
As too often, I failed to recognize a subtle difference between the two SPs: they both call a logging SP, but this logging procedure has two variants, one with prefix 'sp_' and one with prefix 'usp' (someone reacted to the MS warning not to use sp_ as prefix), and the old one had an 'execute as owner' inside, that caused the error.
Replacing the function call with the new version fixed the error.
Sometimes the error is on the other side of the screen...