How do I change the owner of a SQL Server database? - sql-server

When I accidentally click on the Database Diagrams tab, I get one of the following errors:
Database diagram support objects
cannot be installed because this
database does not have a valid owner.
To continue, first use the Files page
of the Database Properties dialog box
or the ALTER AUTHORIZATION statement
to set the database owner to a valid
login, then add the database diagram
support objects.
--- or ---
The database does not have one or more
of the support objects required to use
database diagramming. Do you wish to
create them?
What's the syntax for changing the owner of this database to 'sa'?

To change database owner:
ALTER AUTHORIZATION ON DATABASE::YourDatabaseName TO sa
As of SQL Server 2014 you can still use sp_changedbowner as well, even though Microsoft promised to remove it in the "future" version after SQL Server 2012. They removed it from SQL Server 2014 BOL though.

to change the object owner try the following
EXEC sp_changedbowner 'sa'
that however is not your problem, to see diagrams the Da Vinci Tools objects have to be created (you will see tables and procs that start with dt_) after that

This is a prompt to create a bunch of object, such as sp_help_diagram (?), that do not exist.
This should have nothing to do with the owner of the db.

Here is a way to change the owner on ALL DBS (excluding System)
EXEC sp_msforeachdb'
USE [?]
IF ''?'' <> ''master'' AND ''?'' <> ''model'' AND ''?'' <> ''msdb'' AND ''?'' <> ''tempdb''
BEGIN
exec sp_changedbowner ''sa''
END
'

Related

SQL xp_create_subdir for non-admin

I'd like to give a non-admin the ability to create folders on the SQL server's local hard disk using xp_create_subdir. Reason - need to create a folder structure so that manufacturing equipment can FTP large files. Meta data for the files is stored in SQL.
Server is SQL 2016 Express. OS is Windows 10 Pro.
I've found lots of explanations of how to get this to work but can't figure out what I'm missing. Using the SA account I've created a stored procedure like this:
use [DBname]
CREATE PROCEDURE dbo.usp_CreateDirectory
#directoryFullPath varchar(500)
WITH EXECUTE AS owner
AS
BEGIN
SET NOCOUNT ON;
EXEC master.dbo.xp_create_subdir #directoryFullPath;
END
GO
GRANT EXECUTE ON dbo.usp_CreateDirectory TO [TestUser]
GO
Code to run the stored procedure:
DECLARE #RC int
DECLARE #directoryFullPath varchar(500)
set #directoryFullPath = 'd:\FTP_Root\2020\08\22\'
EXECUTE #RC = dbo.usp_CreateDirectory
#directoryFullPath
GO
In Windows I've given NT Service\MSSQL${InstanceName} full access to d:\FTP_Root\
What am I missing? Running xp_create_subdir 'C:\FTP_Root\2020\08\22' in MSSMS works fine.
Running the stored procedure as SA or the non-admin TestUser gives this result:
Msg 229, Level 14, State 5, Procedure xp_create_subdir, Line 1 [Batch
Start Line 2] The EXECUTE permission was denied on the object
'xp_create_subdir', database 'mssqlsystemresource', schema 'sys'.
I found this on another site: https://www.sqlservercentral.com/forums/topic/xp_create_subdir-for-non-sysadmins
The headlines here are two main points
Although this post is old,
In order to solve this issue, you should make sure that your database is Trustworthy - since the SP xp_create_subdir is on different DB
You still need to set "with Execute as 'dbo'
alter database [DBNAME] set trustworthy on
- Guy-456224
And DO understand the security ramifications of using SET TRUSTWORTHY ON. It may not be a problem or... it may. "It Depends" but you won't know until you read about it.
- Jeff Moden
I completely agree with Jeff on this one. If you remotely care about security, understand what the TRUSTWORTHY setting does before adjusting it.
I think the larger question here is to ask why SQL Server needs to create the directory? Powershell could both query the database for the Directory Path and create the Directory. You could have a SQL Server Agent job that will execute this under the security context of either a SQL Server Proxy account, or the SQL Agent service account (I would pick the proxy account personally, but that's just me).

How to get Database Name in a Logon SQL Trigger

How to get Database Name in a Logon Trigger
tried several tsql code
CREATE TRIGGER tr_stop_excel_users
ON ALL SERVER FOR LOGON
AS
BEGIN
IF (SELECT DB_NAME() FROM sys.databases) = 'TESTDB' and ORIGINAL_LOGIN() <> N'xx\xxxxxxx' AND APP_NAME() LIKE '%Microsoft Office%' OR APP_NAME() LIKE '%EXCEL%' OR APP_NAME() LIKE '%ACCESS%
ROLLBACK;
END
above the DB_NAME always yields master
I am trying to get Database Name in a Logon Trigger and its not working in any way I try….below the DB_NAME is always master…what I am trying to do here is to block users who are using excel to query the TESTDB database….
If you are using Db_Name in LOGON trigger, you will get the default database name. So as you get the master, it shows that login's default database is master.
If you need to get other names, you need to change your connection string in application, or provide database name in SSMS Login prompt screen, or any other places where you can provide the database name(Go to Options/Connection Properties/Connect to Database in Login prompt screen in SSMS)
If you do not provide database name, login will connect to its default database, that is set in Security/Login/Default Database
Solution for you
Using Db_Name is not a good option for you, I recommend you to use APP_NAME function instead.
Same problem discussed in StackExchange: https://dba.stackexchange.com/questions/40155/prevent-users-from-using-power-pivot-excel-connections-to-a-database

Is it possible to use a trigger on a table only on executed queries through Management Studio?

I have a trigger on a table that logs user activity to an audit table. This has proven useful, but I have not found a way to differentiate between queries executed by my applications (ASP.NET) and those executed through Management Studio.
I have been planning to make sure to run an insert query instead on the audit table whenever my applications attempt to execute any stored procedures on my database, but I realise that the trigger will fire anyway.
Is there a way of limiting the trigger to only work when a query is executed by a user of SQL Server Management Studio (SSMS), or will the trigger always fire, and as such I should reconsider how I log my user's activity?
Just as a post script, I cannot utilise the auditing tools that SSMS usually allows, as I am hosting my databases on an Amazon RDS instance.
You can have DDL Trigger for logon in order to control users and AAP_Name() of each user.
Following query is a sample code of DDL Trigger:
CREATE TRIGGER [ddl_login_Audit] ON ALL SERVER
FOR LOGON AS
begin
DECLARE #LogonTriggerData xml,
#HostName varchar(500),
#AppName varchar(500)
SET #LogonTriggerData = eventdata()
SET #HostName = HOST_NAME()
SET #AppName = APP_NAME()
IF (#APPName = 'Your application name') BEGIN
ROLLBACK
End
END
GO
I tried Mehdi Lotfi's solution, but it appears that Amazon RDS will only allow certain user levels to use this trigger.
I could mess around for a while to allow greater permissions for the executing user, but at the moment I am reluctant to do so.
Instead however, I used APP_Name() to determine my application name, set in my web.config file as part of my ASP.Net application, and then proceeded with the trigger only if the APP_Name() was equal to Microsoft SQL Server Management Studio - Query.
For example:
DECLARE #CurrentApp varchar(128)= APP_NAME()
--Table to audit
SELECT #TableName = 'TableName'
-- Check app name
IF #CurrentApp = 'Microsoft SQL Server Management Studio : Query'
BEGIN
-- ...Continue with trigger
END

Database Diagram Support Objects cannot be Installed ... no valid owner

I tried to create a database diagramm with SQL Server 2008, but an error occurs:
Database diagram support objects
cannot be installed because this
database does not have a valid owner.
To continue, first use the Files page
of the Database Properties dialog box
or the ALTER AUTHORIZATION statement
to set the database owner to a valid
login, then add the database diagram
support objects.
Then I tried the following:
EXEC sp_dbcmptlevel 'Ariha', '90';
GO
ALTER AUTHORIZATION ON DATABASE::Ariha TO [WIN-NDKPHUPPNFL\Administrator]
GO
USE Ariha
GO
EXECUTE AS USER = N'dbo' REVERT
GO
Next erorr pops up:
Msg 15404, Level 16, State 11, Line 1
Could not obtain information about
Windows NT group/user
'WIN-NDKPHUPPNFL\Administrator', error
code 0x534.
The Problem is the name of the PC has changed into "DevPC" I also changed this in the update script, but still the same error 15404.
What can I do to fix this annoying error?
In SQL Server Management Studio do the following:
Right Click on your database, choose properties
Go to the Options Page
In the Drop down at right labeled "Compatibility Level" choose "SQL Server 2005(90)"
3-1. choose "SQL Server 2008" if you receive a comparability error.
Go to the Files Page
Enter "sa" in the owner textbox.
5-1 or click on the ellipses(...) and choose a rightful owner.
Hit OK
after doing this, You will now be able to access the Database Diagrams.
You should consider SQL authentication account for database ownership; then you don't have to worry about accounts coming and going, databases or instances moving to different servers, and your next PC name change. I have several systems where we use:
ALTER AUTHORIZATION ON DATABASE::Ariha TO [sa];
Or if you want to change the owner to that local Administrator account, then it should be:
ALTER AUTHORIZATION ON DATABASE::Ariha TO [DevPC\Administrator];
Because renaming the machine to DevPC has eliminated the local account that used to be named WIN-ND...\Administrator and this has also invalidated the current owner of the database.
If SELECT ##SERVERNAME; is not accurate (it should say DevPC), then in order to ensure that your server rename has taken hold within SQL Server, you may also want to issue the following:
EXEC sys.sp_dropserver #server = N'old server name';
GO
EXEC sys.sp_addserver #server = N'DevPC', #local = N'local';
GO
USE [ECMIS]
GO
EXEC dbo.sp_changedbowner #loginame = N'sa', #map = false
GO
It works.
Enter "SA" instead of "sa" in the owner textbox. This worked for me.
I had the same problem.
I wanted to view my diagram, which I created the same day at work, at home. But I couldn't because of this message.
I found out that the owner of the database was the user of my computer -as expected. but since the computer is in the company's domain, and I am not connected to the company's network, the database couldn't resolve the owner.
So what I did is change the owner to a local user and it worked!!
Hope this helps someone.
You change the user by right-click on the database, properties, files, owner
Select your database - Right Click - Select Properties
Select FILE in left side of page
In the OWNER box, select button which has three dots (…) in it
Now select user ‘sa and Click OK
This fixed it for me. It sets the owner found under the 'files' section of the database properties window, and is as scripted by management studio.
USE [your_db_name]
GO
EXEC dbo.sp_changedbowner #loginame = N'sa', #map = false
GO
According to the sp_changedbowner documentation this is deprecated now.
Based on Israel's answer. Aaron's answer is the non-deprecated variation of this.
I just experienced this. I had read the suggestions on this page, as well as the SQL Authority suggestions (which is the same thing) and none of the above worked.
In the end, I removed the account and recreated (with the same username/password). Just like that, all the issues went away.
Sadly, this means I don't know what went wrong so I can't share any thing else.
1.Right click on your Database ,
2.Then select properties .
3.Select the option in compatibility levels choose sql 2008[100] if you are working with Microsoft sql 2008.
4.Then select the file and write ( sa ) in owner`s textbox
100% works for me.
An easier way to solve this issues would be to right click the name of your database, choose "New Query", type " exec sp_changedbowner 'sa' " and execute the query. Then you'll be good to go.
you must enter as administrator right click to microsofft sql server management studio and run as admin
Only need to execute it in query editor
ALTER AUTHORIZATION ON DATABASE::YourDatabase TO [domain\account];
The real problem is that the default owner(dbo) doesn't have a login mapped to it at all.As I tried to map the sa login to the database owner I received another error stating "User,group, or role 'dbo' already exists...".However if you try this code it will actually works :
EXEC sp_dbcmptlevel 'yourDB', '90';
go
ALTER AUTHORIZATION ON DATABASE::yourDB TO "yourLogin"
go
use [yourDB]
go
EXECUTE AS USER = N'dbo' REVERT
go
right click on your Database , then select properties .
select the option in compatibility levels choose sql 2005[90] instead of 2008 if you are working with Microsoft sql 2008.
then select the file and write ( sa ) in owner`s textbox.
it will work probably

Hide SQL database from Management Studio

How can you hide databases you do not have access rights to when logging into SQL Server 2005 / 2008?
Currently if a user connects, they see all the databases on the server, meaning they have to scan though the list to find their database.
After hours of trying to figure out how to create a user account which only has access to 1 DB, and can only see that DB. I think i figured it out!!!!
Create a user account ( make sure its not mapped to any Database, otherwise you will get the final error Msg 15110, Level 16, State 1 and note proposed solution)
USE [master]
GO
CREATE LOGIN [us4]
WITH PASSWORD=N'123',
DEFAULT_DATABASE=[master],
CHECK_EXPIRATION=OFF,
CHECK_POLICY=OFF
Right Click on the upper section of the SQL (SQLSERVER Name)>Properties>Permissions>Click on the user account, and select Deny to view databases.
use [master]
GO
DENY VIEW ANY DATABASE TO [us4]
Right Click on the newly created DB, Properties,Files, and change the Owner to the newly created account.(important note: ALTER ROLE [db_owner] ADD MEMBER [us4] does not work)
USE [dbname]
GO
EXEC dbo.sp_changedbowner #loginame = N'us4', #map = false
At this point, once the user logs in he will see the Master,tempdb and will also see the new DB which he is a DB Owner of..You may want to go to Tools>Option and enabled the option to hide system objects so that you don't show the master,tempdb,etc. You may also need SP1 if this option does not work
Msg 15110, Level 16, State 1, Line 1
The proposed new database owner is already a user or aliased in the database.
proposed solution to Msg 15110: to resolve above error simply delete the user from database security node and try again
Hope that helps...
Nikhil
This actually won't work the way that makes sense or that you might expect that it would.
You REVOKE VIEW ANY DATABASE from the public role, but then the user has to be the database owner of the database or it can't be seen, but it still can be accessed.
The problem is a Database Engine Security shortcoming and not likely to be fixed in the current or future release of SQL Server.
Erland Sommarskog opened the following connect item for this a while ago, and it recently was discussed on twitter and with Microsoft by the SQL MVP's.
Vote for the connect and help make it more of a priority for Microsoft to fix:
Connect Feedback
Basically the permissions are stored at the database level, so it would require enumerating each database to determine if the user has connect rights to display the database in the object explorer, which is an expensive task to perform and how the older EM used to do things.
The proposes solution is for this information to be maintained at the server level as well, which is a major change.
You would need to revoke the permission 'VIEW ANY DATABASE' from the role PUBLIC (SQL SERVER 2005 onwards)
Add user to DB as Db owner after removing VIEW ANY DATABASE rights
This will show only the database owned by the login in SSMS.
USE master; GO
DENY VIEW ANY DATABASE TO [loginname]; GO
USE [your db]; GO
DROP USER [loginname]; GO
USE master; GO
ALTER AUTHORIZATION ON DATABASE::[your db]TO [loginname]; GO
Note: this requires the login to exists already
There appears to be a server-side setting on MS SQL 2005 and 2008 to restrict the databases a user may see. I found the following text at sql-server-performance.com
In SQL Server 2005 it is possible with a new server side role that has been created. VIEW ANY DATABASE permission is a new, server-level permission. A login that is granted with this permission can see metadata that describes all databases, regardless of whether the login owns or can actually use a particular database. Please note By default, the VIEW ANY DATABASE permission is granted to the public role. Therefore, by default, every user that connects to an instance of SQL Server 2005 can see all databases in the instance.

Resources