Comments
4 comments
-
@repo: If the stored procedure uses dynamic SQL (e.g.,
EXEC
orsp_executesql
), the ownership chain is broken, and explicit permissions are required on the objects referenced in the dynamic SQL -
Thanks for pointing that out, Cathy. That makes sense. If dynamic SQL is involved, then the normal ownership chaining rules wouldn’t apply, and you’d need explicit permissions on the referenced objects. I’m running into a similar issue on Azure SQL DB where a stored proc works fine on SQL Server but throws a SELECT permission error on Azure. I’ll double-check whether there’s any dynamic SQL in the proc that's causing the break in the chain. Appreciate the insight!
-
I've run into a similar issue before when switching environments. In Azure SQL Database, especially when using MS Entra ID (formerly Azure AD) for auth, permission checks can behave slightly differently compared to on-prem SQL Server. Even if a stored procedure exists and runs fine on SQL Server with no explicit SELECT permissions on underlying tables, Azure SQL can enforce stricter permission boundaries depending on how the procedure is created.
The key factor is ownership chaining. In SQL Server, ownership chaining allows the proc to access tables without requiring direct SELECT permissions as long as everything is owned by the same schema/owner. In Azure SQL, this often breaks if there's any mismatch or if you're running under contained database users with different authentication contexts. Also, WITH EXECUTE AS might behave differently or need to be explicitly declared to bypass such errors.
One way we diagnosed a similar issue was by running a kind of "speed test" on procedure execution across different environments — not unlike how we monitor differences in german train speed between regional rail networks. The underlying engine is the same, but conditions (permissions, latency, resource governance) impact behavior in subtle ways.
You might want to double-check procedure ownership, the EXECUTE AS context, and whether the AD user has implicit rights via role membership in Azure. That should clear up the SELECT issue. Hope that helps.
-
You're definitely not alone—this is one of those subtle differences between on-prem SQL Server and Azure SQL Database that catches people off guard.
In SQL Server 2022, if your stored procedure and the underlying tables are owned by the same user (like
dbo
), you get the benefit of ownership chaining. That means users can run the stored proc without needing direct SELECT permissions on the tables—it just works.But in Azure SQL Database, especially when using Entra ID (formerly Azure AD) authentication and contained database users, that ownership chain can break down. Even if your schema and permissions are identical (as confirmed with SQL Compare/Data Compare), Azure SQL might still require explicit SELECT permissions on the table.
What's odd in your case is that SELECT is failing, but DELETE and UPDATE are not. That makes me wonder:
- Is the SELECT being done on a view, or maybe through dynamic SQL inside the proc? Both of those can bypass ownership chaining.
- Are the proc and the tables definitely owned by the same principal (check with
sys.objects
orOBJECTPROPERTY()
just to be sure)? - Is the proc running under the caller’s context, or using something like
EXECUTE AS
?
You could try:
- Adding
EXECUTE AS OWNER
to the proc definition - Explicitly granting SELECT on the table to the Entra ID user or role (just to confirm it resolves the error)
- Double-checking that the login context in Azure really maps the same way as it does in SQL Server
In short: you're not wrong—your approach aligns with least privilege and standard best practices. Azure SQL just enforces things a bit differently due to how it handles identity and containment.
Would love to hear if you find a clean workaround!
Check Object ownership :
SELECT
o.name AS object_name,
o.type_desc,
s.name AS schema_name,
u.name AS owner
FROM sys.objects o
JOIN sys.schemas s ON o.schema_id = s.schema_id
JOIN sys.database_principals u ON o.principal_id = u.principal_id
WHERE o.name IN ('YourProcName', 'YourTableName');
Try redefining the stored procedure with
EXECUTE AS OWNER
to enforce the proper context:CREATE OR ALTER PROCEDURE YourProcName WITH EXECUTE AS OWNER AS BEGIN -- your logic here END
To confirm it’s a permissions issue, you can temporarily grant SELECT directly:
GRANT SELECT ON dbo.YourTableName TO [your_EntraID_user_or_role];
Add comment
Please sign in to leave a comment.
I have a c# desktop application that has the option to connect to a primary or secondary database, Primary is SQL Server 2022 Standard using AD integration, the Secondary is Azure DB S2 using MS EntraID Interactive, using our “local” AD sync'd to EntraID. I use SQL Compare and SQL Data Compare to make sure they are identical for testing, and they are identical for this question. Problem I'm having is that when I switch between SQL Server and Azure DB, I'm getting a SELECT permissions error in Azure DB to view a table while running a stored proc. Same proc on SQL Server, no error. I was always told the if all users are using Stored Procs, then select permissions on tables directly is not necessary, and removing them follows least privilege. But they seem to be necessary in Azure DB. Can anyone confirm this? Why the change? Am I missing something? Oddly, the stored proc also uses DELETE and UPDATE on tables which have not generated permission errors.