I have a situation whereby an application we use has many databases used for storage, and creates new ones on the fly as needed (SQL Server 2008 R2).
ApplicationDatabase
ApplicationDatabase_Storage001
ApplicationDatabase_Storage002
ApplicationDatabase_Storage003
etc...
As needed the application will create a new storage database for itself.
My problem is that I have a sql server account that is used for the ApplicationDatabase, and I want to automatically give it permissions to the storage databases as they are created, but not to any other database that happens to be created in the same sql server instance. I have no control over the creation of the storage databases.
I read In the answer to this question that I can add the account in the model database however this appears to add the permissions for all new databases, when I only want it to apply to the databases mentioned above.
The best solution I could come up with is a SQL server job or external app that runs once a day or so and looks for the existence of each database, applying the permissions on each that it finds, but this does not seem ideal.
You can implement a DDL trigger that will be fired whenever a new database is created. Depending on the properties of the database, like name or storage definition, you can probably run additional scripts on the new database to set up the required security.
http://msdn.microsoft.com/en-us/library/ms186406.aspx
Here's a snippet from the article above:
IF EXISTS (SELECT * FROM sys.server_triggers
WHERE name = 'ddl_trig_database')
DROP TRIGGER ddl_trig_database
ON ALL SERVER;
GO
CREATE TRIGGER ddl_trig_database
ON ALL SERVER
FOR CREATE_DATABASE
AS
PRINT 'Database Created.'
SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)')
GO
DROP TRIGGER ddl_trig_database
ON ALL SERVER;
GO
Regards
Piotr
Related
I have a multi-tenant database, each user has their own schema.
What is the best way to backup a single tenant (table schema)? As far as I know SQL Server does not support backup of a single schema (only the complete database).
I need to backup the structure and data. Also it needs to be automated (Ideally I should be able to call it from SSMS as well).
I was thinking exporting the ddl and data as sql statements. If there is some way to call the "Generate and Publish Scripts" wizard as stored proc I think it would work?
I am currently on Sql Server 2008 R2 but could upgrade.
A couple of ideas.
Using File Groups
Put the tables each tenant has into their own file group. SQL Server has the ability to backup and restore individual file groups. You can also perform some other operations such as taking indivudual tenants offline if required. For example:
CREATE TABLE tenant1.Table1
(Column1 INT, Column2, INT)
ON Tenant1FileGroup
Views & Separate Databases
Probably not the right way to go, but it will work. Have the tables for each tenant in their own database and reference them from the 'master' database with a view in the tenant schema. For example:
Tenant1DB
dbo.Table1
dbo.Table2
Tenant2DB
dbo.Table1
dbo.Table2
MasterDB
tenant1.Table1
tenant1.Table2
tenant2.Table1
tenant2.Table2
Where the objects mentioned above in the MasterDB database are views such as:
CREATE VIEW tenant1.Table1
AS
SELECT * FROM Tenant1DB.dbo.Table1
This way you can easily backup/restore individual tenant databases. Some other benefits of this strategy:
Individual tenants can be restored without bringing the main database into single user mode.
The system will scale out well as the tenant database can be moved to other servers.
Currently i have a list of databases i wish to move on the current server.
DATA:
Current Path: Drive:\MSSQL\DATA\FOLDER
New Path: Drive:\MSSQL\DATA
LOGS:
Current Path: Drive:\MYSSQL\LOGS\FOLDER
New Path: Drive:\MYSSQL\LOGS
Is there a SQL script that can be used to set offline multiple databases, detactch them and attach them to the new location? This is also a production enviroment and are pretty large databases (a backup and restore would take much longer). In total 9 databases need to be moved, is this a simple procedure aslong as the location and user have required permissions? Thank you for any help.
This is a simple procedure, and you don't really need to detach the database to do it either, you can just do something along the lines of:
set db offline
alter the file location in the master db (using alter database)
physically move the files
set db online
The process is described in the following article:
Move User Databases
So long as the user moving the files has the permissions and the service account you're running SQL server as has full control of the new folder it's quite easy, and something I've done many times.
Doing it for multiple databases too is simple once you've worked out the procedure for doing the first one.
You can use this code to change the path. But you have to manually move the files to the new location. The WITH ROLLBACK IMMEDIATE speeds up the offline procedure by disconnecting any current connections.
ALTER DATABASE <db-name> SET OFFLINE WITH ROLLBACK IMMEDIATE;
ALTER DATABASE <db-name> MODIFY FILE ( NAME = <db-name>, FILENAME = <db-path\filename.mdf> );
ALTER DATABASE <db-name> SET ONLINE;
For more info check the relevant MSDN article
I want a way to write my own query to restore the database. The database to restore needs to have all the settings to delete the current user and re-map the same user. The reason for that is because when the database is restored, the user will not have the right settings to use the database and will have to re assign the user the privileges.
Check this out:-
Step 1: Retrive the Logical file name of the database from backup.
RESTORE FILELISTONLY
FROM DISK = 'D:BackUpYourBaackUpFile.bak'
GO
Step 2: Use the values in the LogicalName Column in following Step.
----Make Database to single user Mode
ALTER DATABASE YourDB
SET SINGLE_USER WITH
ROLLBACK IMMEDIATE
----Restore Database
RESTORE DATABASE YourDB
FROM DISK = 'D:BackUpYourBaackUpFile.bak'
WITH MOVE 'YourMDFLogicalName' TO 'D:DataYourMDFFile.mdf',
MOVE 'YourLDFLogicalName' TO 'D:DataYourLDFFile.ldf'
/If there is no error in statement before database will be in multiuser
mode.
If error occurs please execute following command it will convert
database in multi user./
ALTER DATABASE YourDB SET MULTI_USER
GO
The reason for that is because when the database is restored, the user will not have the right settings to use the database and will have to re assign the user the privileges.
I guess that:
You are using mixed mode authentication and the user is a SQL Server user (not a Windows user)
You are restoring the database to a different server than the one where the backup was made
Correct?
If yes, you need to consider the following:
The user must exist on the second server as well, it's not created automatically when you restore the database there
It's not enough to just create a new user with the same name on the second server - to SQL Server, this would be a different user!
I guess that the second point is the reason why your user doesn't have "the right settings" after restoring.
Some background:
Internally, all SQL Server users are represented by a SID (something unique and unreadable - similar to a GUID. SQL Server doesn't care about the actual user name internally).
The permissions that each user has on a database are saved inside the database, using the SID and not the username
When you restore the database to a different server, the permissions are restored with the database...but they only work when there's a user with the exact SID on the new server
As I said before: when you just create a new user with the same name, he gets a new SID.
So what probably happened is this:
on the old server, there's a user "Mohammed Tahir" with the SID 123456789
inside the database, there's a permission that says "SID 123456789 is allowed to read from this database"
you restored the database on the new server
you created a user "Mohammed Tahir" on the new server, but he has a different SID (let's say 987654321), so the existing permissions on 123456789 don't work for him!
So what you need is a way to "copy" the user from the old server to the new server, with the exact same SID.
There is a stored procedure from Microsoft named sp_help_revlogin, which does just that.
It generates a script with all the users from the old server. You can then run the script on the new server, and it will create the users with the same SIDs they had on the old server.
Then, you can restore the database from the old server to the new server, and all the permissions already in the database just work.
You can get sp_help_revlogin from this MSDN article:
How to transfer logins and passwords between instances of SQL Server.
Note that there is nothing special about the actual restoring process - it's the users and their SIDs that make the difference.
So you don't need any "special" commands to restore the database, just the standard ones, for example the one from Rahul Tripathi's answer.
SQL Server is not my strong point and I start to get lost when going past the basic Create Table, Select from Table etc.
I am attempting to set up a database synchronisation scenario with an Microsoft SQLCompact 3.5 database being Synced through a Proxy to and SQL 2008 R2 database. It is being synced through the Microsoft Sync Framework 2.1.
I got everything set up and working fine through the proxy when the user account is the db_owner of the database.
Of course this now needs to be locked down - so I have been trying to restrict the permissions to the bare minimum required for Synchronisation.
According to the Microsoft articles, I need to do the following...
Use the principle of least permission. Do not grant more permissions than are required to perform a specific task. For example, do not grant INSERT permissions for server database tables that are involved in download-only synchronization. Synchronization operations require the following permissions:
EXECUTE permissions on all the stored procedures that Sync Framework uses to read and write to metadata tables and base tables.
SELECT, INSERT, UPDATE, and DELETE permissions for metadata tables and any base tables that will be updated during a synchronization session.
When you provision SQL Server databases that use SqlSyncProvider, be aware of the following permissions requirements for provisioning:
CREATE TABLE permissions to enable creation of the metadata tables: scope_info and scope_config, and the tracking tables that are created for each base table.
ALTER TABLE to add triggers to the base tables.
CREATE PROCEDURE permissions to create the procedures that Sync Framework requires.
SELECT and INSERT permissions for scope_info and scope_config tables.
SELECT permissions for base tables.
I allowed the wizards in Visual Studio 2010 to create the Sync database and proxy for me.
As such - I am unable to find the scope_info and scope_config tables in SQL Server databases, and I am also unable to find the metadata tables so cannot set permissions on these tables. Also - where would I find the stored procedures that the Synchronisation framework is trying to use - I have looked but cannto find them.
Where would I find these and how would I go about setting the appropriate permissions?
I have granted datareader and datawriter, Insert, Update, Delete and Select as well as Execute permissions on the SQL Server database but the sync fails. I have also granted Create Table, Create Procedure and ALTER permissions on the database for the user as well- but still it fails.
If i enable the db_owner role for the user - it works.
The error I receive is:
Unable to initialize the client database, because the schema for table 'tblApplications, tblApplicationConfiguration, tblApplicationInstallProperties, tblApplicationPreRequisites, tblApplicationTypes, tblComputerApps, tblComputers, tblComputerTypes, tblDriveHWSerials, tblDrives, tblDriveTypes, tblFunctions, tblLocationApps, tblLocationComputers, tblLocationIPAddress, tblLocations, tblLocationUsers, tblPermissions, tblRegionLocations, tblRegions, tblRegisteredModules, tblRequestFormats, tblRequestStatus, tblRequestTypes, tblRoles, tblRoleUsers, tblSecurity, tblUsers, tblVehicle, tblVehicleLocationMap, tblVehicleMake, tblRequestProcessingStatus, tblDriveStatus, tblVideoViewTypes' could not be retrieved by the GetSchema() method of DbServerSyncProvider.
Make sure that you can establish a connection to the client database and that either the SelectIncrementalInsertsCommand property or the SelectIncrementalUpdatesCommand property of the SyncAdapter is specified correctly.
I am not able to use the db_owner role when its released.
there are two types of database providers in Sync Framework, the offline provider (SqlCeClientSyncProvider/DbServerSyncProvider) which is used by the Local Database Cache project item and the collaboration/peer-to-peer provider (SqlSyncProvider/SqlCeSyncProvider).
the offline providers dont use the scope_xxx tables as such you wont find it.
assuming you used the default SQL Server Change Tracking when you configured the sync via the wizard, try granting VIEW CHANGE TRACKING permission to the account you're using to connect to the database.
I'm not sure if it will help, but I found this:
Try to set UploadOnly on the SyncTable object instead. When you set it on the SyncAdapterBuidler, the select incremental commands are not generated by the builder. These commands are used to get the table schema from the database. Since these are missing you are getting the schema error.
Also, maybe this blog entry will help.
As JuneT Mentioned, you should turn on Change Tracking
ALTER DATABASE YourDataBaseName
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON)
I have several stored procedures in my database that are used to load data from a datamart that is housed in a separate database. These procedures are, generally, in the form:
CREATE PROCEDURE load_stuff
WITH EXECUTE AS OWNER AS
INSERT INTO my_db.dbo.report_table
(
column_a
)
SELECT
column_b
FROM data_mart.dbo.source_table
WHERE
foo = 'bar';
These run fine when I execute the query in SQL Server Management Studio. When I try to execute them using EXEC load_stuff, the procedure fails with a security warning:
The server principal "the_user" is not able to access the database "data_mart" under the current security context.
The OWNER of the sproc is dbo, which is the_user (for the sake of our example). The OWNER of both databases is also the_user and the_user is mapped to dbo (which is what SQL Server should do).
Why would I be seeing this error in SQL Server? Is this because the user in question is being aliased as dbo and I should use a different user account for my cross-database data access?
Edit
I understand that this is because SQL Server disables cross database ownership chaining by default, which is good. However, I'm not sure of the best practice in this situation. If anyone has any input on the best practice for this scenario, it would be greatly appreciated.
Edit 2
The eventual solution was to set TRUSTWORTHY ON on both of the databases. This allows for limited ownership chaining between the two databases without resorting to full database ownership chaining.
Why not remove EXECUTE AS OWNER?
Usually, my user executing the SP would have appropriate rights in both databases, and I don't have to do that at all.
There is no need to create login, you can just enable guest user in target DB.
grant connect to guest
This allows executing user to enter DB under guest context, and when "db chaining is ON access will not be checked in target DB.
Actually, DBO is a role (you can consider it as a group of users), not a user in himself. (Unless you can connect to SQL SERVER using dbo:passwordfordbo it's not a user).
Usually, in the wonderful world of SQL Server, if you grant userX right to execute storedprocY then X gets the right to perform all the task Y contains even if he doesn't have all the permission on all the objects used in Y.
That's an extremely useful feature to encapsulate business logic in a stored procedure. (Your user have NO access on the table but they do can EXECUTE one stored proc).
When we talk about "ownership chaining" it means the following (please correct me if I am wrong though)
- If ownership chaining is disabled: the right to execute procedureX will work as long as all the required objects are in the same database
- Of chaining is enabled: That "privilege" will expands towards all databases.
Hope that helps,