Cannot find the principal 'dbo', because it does not exist or you do not have permission

10.9k views Asked by At

This question is focussed on why this has happened.

We restored a database from another server that has failed. The restore succeeded, but when we try and run any stored procedure (using 'sa' login, or Windows-based login with full admin access), we got this error:

Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission.

Lots of SO users have had the same issue, so I followed the related answers. For example, both of the following snippets:

EXEC sp_changedbowner 'dbo';
ALTER AUTHORIZATION ON DATABASE::MyDb TO dbo;

...result in this:

Cannot find the principal 'dbo', because it does not exist or you do not have permission.

On the previous server (and my restoration dev server) there is no dbo user to reassociate as the owner. I'm not sure how to locate the principal, but it is listed in the Schema.

  1. What causes 'dbo' to not be found, or what has happened to the dbo principal?
  2. Can it be reinstated/recreated?
  3. Does dbo have to link to an actual login account?
1

There are 1 answers

1
Dan Guzman On

The database owner is a server-level principal (i.e. login) or Windows user (not necessarily with a login). As noted in the comments, dbo is a database principal rather than a server principal (assuming you don't happen to have a login named dbo).

The owner is stored in the master database and visible as the owner_sid column of the sys.databases catalog view:

SELECT name AS DatabaseName, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName
FROM sys.databases
WHERE name = N'MyDb';

The database owner is also stored in the database itself as the well-known dbo user:

SELECT SUSER_SNAME(sid) AS OwnerName, sid
FROM sys.database_principals AS dp
WHERE name = N'dbo';

When a database is restored and it doesn't already exist, the owner (authorization) is initially set to the person who restored the database. However, the dbo entry in the database itself remains unchanged. This results in a mismatch between the owner in sys.databases and the sys.database_principals dbo user. It is necessary to execute ALTER AUTHORIZATION ON DATABASE with the desired owner after a restore to correct the mismatch.

Below is a script that demonstrates the issue when the individual executing the restore is not logged in as sa.

CREATE DATABASE MyDb; --database is owned by current login

ALTER AUTHORIZATION ON DATABASE::MyDb TO sa; --sa is an example; can be any login

--shows owners are same (sa)
SELECT name AS DatabaseName, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName
FROM sys.databases
WHERE name = N'MyDb';

SELECT SUSER_SNAME(sid) AS OwnerName, sid
FROM MyDb.sys.database_principals AS dp
WHERE name = N'dbo';

BACKUP DATABASE MyDb TO DISK=N'C:\Backups\MyDb.bak' WITH INIT;

DROP DATABASE MyDb;

RESTORE DATABASE MyDb FROM DISK=N'C:\Backups\MyDb.bak';

--shows owners are different (current user and sa)
SELECT name AS DatabaseName, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName
FROM sys.databases
WHERE name = N'MyDb';

SELECT SUSER_SNAME(sid) AS OwnerName, sid
FROM MyDb.sys.database_principals AS dp
WHERE name = N'dbo';

ALTER AUTHORIZATION ON DATABASE::MyDb TO sa; --sa is an example; can be any login

--shows owners are same (sa)
SELECT name AS DatabaseName, owner_sid, SUSER_SNAME(owner_sid) AS OwnerName
FROM sys.databases
WHERE name = N'MyDb';

SELECT SUSER_SNAME(sid) AS OwnerName, sid
FROM MyDb.sys.database_principals AS dp
WHERE name = N'dbo';

Below is an excerpt from the documentation regarding the database owner principal.

The new owner principal must be one of the following:

A SQL Server authentication login.
A Windows authentication login representing a Windows user (not a group).
A Windows user that authenticates through a Windows authentication login representing a Windows group.