Data Organization Using Schemas

In this post, Data Education founder and trainer Adam Machanic continues his discussion of schemas and the difficulty that comes with maintaining a secure database. Here, he explains that by dividing your database into schemas, related objects and control permissions can be easily grouped without worry.

In versions of SQL Server prior to 2005, all database objects were both owned by database users and referenced by owner name. So to select from a table that was not owned by dbo, the table name would have to be prefixed with the name of the database user that owned it (unless you were logged in as that user). In addition to owner name prefixing, other difficult security scenarios were also created. For instance, there was no easy way to assign permissions to all of the tables owned by a certain user, meaning that ownership did not work as a method by which to easily logically segment tables into groups.

The situation changed with SQL Server 2005, thanks to support for ANSI standard schemas. Schemas are essentially containers into which any database object can be placed, and security rules applied en masse. By dividing your database into schemas, you can easily group related objects and control permissions, without having to worry about what objects might be added or removed over time. As new objects are added to a schema, existing permissions propagate, thereby allowing you to set up access rights for a given schema once, and not have to manipulate them again as the database changes.

To create a schema, use the CREATE SCHEMA command. The following T-SQL creates a schema called Sales:

CREATE SCHEMA Sales

Optionally, you can specify a schema owner by using the AUTHORIZATION clause. If an owner is not specified, the user that creates the schema will be automatically used by SQL Server.

Once a schema is created, you can begin creating database objects within the schema, using two-part naming, similar to creating objects by owner in previous versions of SQL Server:

CREATE TABLE Sales.SalesData
(
    SaleNumber INT,
    SaleDate DATETIME,
    ...
)

Once an object is created, it can be referenced by schema name; so to select from the SalesData table, the following SQL is used:

SELECT FROM Sales.SalesData

This same SQL is used no matter who owns the table. Remember, owner names are never used to qualify objects, as of SQL Server 2005.

The beauty of schemas becomes obvious when it is time to apply permissions to the objects in the schema. Assuming that each object is equivalent from a permissions point of view, only a single grant is necessary to give a user access to every object within a schema. For instance, after the following T-SQL is run, the Alejandro user will have access to select rows from every table in the Sales schema, even if new tables are added later:

CREATE USER Alejandro
WITHOUT LOGIN
GO 

GRANT SELECT ON SCHEMA::Sales
TO Alejandro
GO

It’s important to note that when initially created, the owner of any object in a schema will be the same as the owner of the schema itself. The individual object owners can be changed later, but in most cases I recommend that you keep everything in any given schema owned by the same user. This is especially important for ownership chaining. In addition, because two-part naming now references a schema rather than an object owner, the process for explicitly setting an object’s owner changed with SQL Server 2005. A new command, ALTER AUTHORIZATION, is used in order to set ownership on objects. The following T-SQL shows the basics of how it is used:

--Create a user
CREATE USER Javier
WITHOUT LOGIN
GO 

--Create a table
CREATE TABLE JaviersData
(
    SomeColumn INT
)
GO 

--Set Javier as the owner of the table
ALTER AUTHORIZATION ON JaviersData
TO Javier
GO

As a final note on schemas, there is also a command that can be used to move objects between them. By using ALTER SCHEMA with the TRANSFER option, you can specify that a table should be moved to another schema:

--Create a new schema
CREATE SCHEMA Purchases
GO 

--Move the SalesData table into the new schema
ALTER SCHEMA Purchases
TRANSFER Sales.SalesData
GO 

--Reference the table by its new schema name
SELECT *
FROM Purchases.SalesData
GO

Schemas are a powerful feature in SQL Server, and I recommend their use any time you’re dealing with sets of tables that are tightly related to one another. The AdventureWorks sample database that shipped with SQL Server 2005 makes great use of schemas, and I highly recommend you take a look at what Microsoft has done in that example and try to design new databases along similar lines. Legacy database applications that use multiple databases in order to create logical boundaries between objects might also benefit from schemas. The multiple databases can be consolidated to a single database that uses schemas. The benefit is that the same logical boundaries will exist, but because the objects are in the same database, they can participate in declarative referential integrity and can be backed up together.