SQL Server 2005 introduces a world of new features and in my first article for Windows
IT Pro News UK I gave a very high-level overview about some of them. In my previous
article I wrote about SQL Server Service broker, the new messaging infrastructure in SQL
Server 2005. In this article, I will take a look at a new feature in the SQL Server called
schemas.
The fully qualified name of a database object in SQL Server 2000 (and earlier versions)
was like the following:
server-name.database-name.owner-name.object-name.
So, for example, if the user Bob in the database db1 in the server serv1 created a
table called tab1, the fully qualified name would be:
serv1.db1.Bob.tab1.
In other words, the creator was tightly coupled to the object itself. Subsequently, if
we for some reason wanted to delete Bob from the database (DROP USER BOB), we could not do
that without first dropping the objects owned by Bob or change the owner of the objects.
Neither of these options is really appealing as we probably have code referencing the
objects and we would then need to change our code.
We can see a schema as a collection of database entities, sharing the same schema name.
If you are familiar with the Common Language Runtime, you can draw a parallel between
schemas and namespaces.
You may now say that in SQL Server 2000 we had the ability to create a schema with the
CREATE SCHEMA statement. However, in SQL Server 2000 this does not create a schema
independent of the user that creates it. It implicitly connects the user with the schema,
and if you try to drop the user you run into the same problems as mentioned before.
Therefore, in SQL Server 2005, Microsoft has given us the ability to create schemas
independent of the user, and by this we achieve separation of schemas and users. This
gives us some considerable advantages:
- Dropping database users is greatly simplified.
- Dropping a database user does not require the renaming of objects contained by that
user's schema. Thus it is no longer necessary to revise and test applications that refer
explicitly to schema-contained objects after dropping the user that created them.
- Multiple users can share a single default schema for uniform name resolution.
- Shared default schemas allow developers to store shared objects in a schema created
specifically for a specific application, rather than in the DBO schema.
- Permissions on schemas and schema-contained objects can be managed with a higher
degree of granularity than in earlier releases.
The syntax to create a schema is like so:
CREATE SCHEMA schema_name
[AUTHORIZATION user]
where the AUTHORIZATION clause is optional. In addition to the syntax above you can
also create tables, views and GRANT and DENY permissions for the particular schema when it
is being created. For example, the following statement:
CREATE SCHEMA Marketing
AUTHORIZATION Bob
CREATE TABLE Mailshots (id int primary key, description varchar(max))
GRANT SELECT TO Alice
DENY SELECT TO Kent;
GO
will create the Marketing schema with Bob being the owner. Furthermore, it creates a
table called Mailshots with Marketing being the schema qualifier and it allows Alice to
run SELECT statements against tables in the schema but denies Kent.
Schemas and users
In the CREATE SCHEMA statement above we explicitly granted and denied permissions to
two users (Alice and Kent), which will be part of this schema. In SQL Server 2005 every
user will have a default schema and if no default schema has been assigned to a user, she
will be part of the DBO schema.
Being part of the DBO schema may initially sound a bit dangerous -- does that imply
that the user then has the permissions as the dbo? No, absolutely not! Every user has to
be given explicit permissions for that particular schema (or have to be be part of a role
which has rights in that schema) in order to be able to do anything. The user also has to
have general permissions, ie GRANT CREATE TABLE TO user-name.
The following code snippet shows an example:
--create a user called niels
CREATE USER niels FROM LOGIN niels
--by default niels is part of the DBO schema
--grant the user general table creation rights
GRANT CREATE TABLE TO niels
--change to niels and try to create a table
SETUSER `niels'
--this will fail
CREATE TABLE n(id int)
--change back to admin and grant niels table creation rights in the Marketing
schema created previously
setuser
GRANT ALTER ON SCHEMA::Marketing to niels
--go back to niels
SETUSER `niels'
--try to create a table in the Marketing schema
--this will succeed
CREATE TABLE Marketing.n(id int)
Notice how the user had to schema-qualify the table name, as the user created the table
in her non-default schema. To make Marketing the default schema for niels we could run
following code:
ALTER USER niels
WITH DEFAULT_SCHEMA = niels
It is also worth noticing that even though niels has rights to create tables in that
particular schema, he has no rights to SELECT from those tables. For that to happen we
need to grant niels SELECT permissions:
GRANT SELECT ON SCHEMA::Marketing to niels
This may sound like a lot of work, and to a degree it is. In real life you'll probably
find that you assign permissions to roles (as before) and then add users to the roles.
Summary
Schemas gives us the ability to separate users from objects, which will make our
database objects easier to administer. In addition, the introduction of schemas will also
make it easier to implement a more granular security model within a database.
End of Article