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.