7. Contained Databases
Consider the case where you perform a database
backup and restore it on a different server. Upon restoration, you may
still need some additional objects in order for your application that
is using the database to work properly. These objects may include SQL
Server Agent jobs, SQL logins, linked server definitions, database mail
configuration, replication setup, and a few others. Database
administrators may have to create these objects before the database is
useable. A contained database is a step toward alleviating this pain
point. A contained database is the same as a traditional
database with the exception that in addition to traditional database
users you can create database users that are not mapped to any SQL
login. This allows your database application to connect directly to the
database without authenticating a login at the server level. Upon a
failover, all you need is the database itself on the disaster recovery
site, because the database contains the security information needed for
the user. SQL Server 2012 introduces a partially contained database. A partially contained database
is the same as a user-defined database except it also includes security
information needed for authentication. In the scenario where you move a
contained database, if your database leverages objects that exist
outside the database such as agent jobs or linked servers, these
objects would have to be created on the new server first before the
database could be used on the new server.
Database movement is not the only use case for
contained databases. Benefits for this feature revolve around
separating the application development and management from the
underlying database instance infrastructure needed to support it. A
contained database makes administering applications easier, because
there is no real dependency on the host instance.
To create a contained database you must first enable the “contained database authentication” system option as follows:
Sp_configure 'show advanced options', 1
RECONFIGURE
GO
Sp_configure 'contained database authentication', 1
RECONFIGURE WITH OVERRIDE
GO
Next, let’s create a sample database and set the containment of this database to partial.
CREATE DATABASE Customers
GO
ALTER DATABASE Customers SET CONTAINMENT=PARTIAL;
Now that our database is partially contained,
we can create database users without associated SQL logins. These users
can be created with a password or they can be Windows principals. If
you use Windows principal users, they do not need any existing access
to SQL Server. For this example, assume we have created a local Windows
user named, "Bob"
on the server, "ROB-DENALI-1"
. To create both a user with a password and a user from a Windows principal, we issue the following commands:
USE Customers
GO
CREATE USER [SalesRep1] WITH PASSWORD='pass@word1';
GO
CREATE USER [ROB-DENALI-1\Bob];
GO
To test our containment, assume we logged into
a Windows client under Bob’s credentials. Alternatively, you as a
Windows administrator, can issue the RUNAS
command and open a new command window under Bob’s context. To do this, you can type the following in a command prompt:
C:\>RUNAS /USER:Bob "CMD.EXE"
Bob can now try to connect to SQL Server. Figure 1
shows a command shell window running under Bob’s security context
depicting Bob’s attempt at connecting to SQL Server. Bob is using
SQLCMD, which is the command line tool for connecting to SQL Server. In
case you are not familiar with the command line switches, -E
means connect via Windows Authentication, meaning connect as Bob in this case. -S .
means the server name, and the period is an abbreviation for the local
server. In the first attempt, notice that SQL Server failed to
authenticate Bob.
Figure 1. Using SQLCMD to connect to a contained database
This failure
occurred, because we didn’t specify an initial database to connect to,
so it was implied that we were trying to connect to the master
database. Since Bob doesn’t exist as a SQL login in the master
database, SQL Server rejected the connection request. In the second
attempt at the sqlcmd
command Bob explicitly states that he wishes to connect to the Customers
database via the -d
parameter in SQLCMD. Since Bob’s account is provisioned in the database, the connection succeeds. You can see SQLCMD gives us 1>
,
which is the SQLCMD command prompt with a successful connection. This
example used SQLCMD, but you can use whatever application or method you
normally use to connect to SQL Server. There are no specific connection
requirements or restrictions for accessing a contained database.