Click here to Skip to main content
Click here to Skip to main content

Database Design and Naming Conventions

By , 2 Aug 2011
 

Introduction

I have looked around a lot and decided that the majority of "standards" for databases don't make sense, so I thought I would document mine.

Background

Looking around at the standards on the internet, I see that there are suggestions like, use the prefix tbl for a table name, and col for column names, use the table name for the primary column name, and they are silly. It gets worse when people start prefixing column names. The worst one I saw was cusCustomerNotes for a string in their customer table. So I am going to put forward my philosophy and explain each one.

Natural joins are evil

I start here, because my next point will be argued to no end if I don't. One of the most nonsensical arguments I hear is that columns should be uniquely named, that way your tool "knows" the proper join without you having to do an explicit join. Thus the tool, like Enterprise Manager, or in the case of Oracle, the SQL Execution Engine, will explicitly or implicitly create the join for you.

If you don't know what a natural join is, the simple description is "you can be lazy and not write your join because the database knows what you mean". So SQL like the following actually works (doesn't even complain in Oracle).

SELECT person.*,card.* from person, card

The obvious problem here is that you have no idea what is being joined on social security number, person, who knows... Furthermore, you have no idea if it is supposed to be an inner join (as a natural join is), or if it is a cross join. A cross join joins all the rows from both tables.

A secondary problem is that different database systems will treat the statement differently, some treat it as a cross join, others treat it as a natural join.

It is my experience that all joins should be explicit and laid out as joins. The following clearly indicates what is intended:

SELECT person.*, card.* 
FROM person 
INNER JOIN card 
    ON card.person_id = person.person_id

If I had designed the tables, it would look like the following instead. (Note the id column in the Person table is now just id rather than person_id), so a natural join won't work. However, tools like Enterprise Manager will recognize the foreign key relationship. This is assuming that one exists, and it absolutely needs to if you want to make sure of your data integrity.

SELECT person.*, card.* 
FROM person 
INNER JOIN card 
    ON card.person_id = person.id

I dislike implicit joins in the where clause for one very simple reason, you then miss joins, thus you end up with natural and cross joins. On complex queries like the following, you could very easily make a mistake.

select country.countryname, state.statename, county.countyname, city.cityname
FROM country, state, county, city
WHERE state.country=country.country and city.county=county.county

At a very minimum, in this example, state and county are a natural join or cross join depending on whether or not there is a matching column name, but we don't know, so who knows what data this will return.

In my opinion, it is better to be specific so that the compiler knows what you want rather than making it guess.

Reuse column names

Why would I ever want to make unique names for every table; for simple things, if a column is the unique row ID, then it should probably called ID; if it is for a description it should probably be called Description. This way when accessing the table or using it for something like a dropdown list, it will always be the same SQL. Consistency is the name of the game; if you always name the column representing the name "Name", it will be much easier to deal with than colcustblCustomerNameString. If we stop and think about it, we already know the table name, so why include it in the name of the column? Furthermore, databases aren't there only to hold data, some program is out there using it, so more modern program might even be able to use mapping tools called Object Relational Mappers, and naming consistency helps everything.

Every table gets a row identifier

There is nothing worse than trying to enforce database constraints when the tables are joined against multiple columns for a single entity when the parent row has a compound key. Here is our state, county, and city example when things get crazy..

SELECT Country.CountryName, State.StateName, County.CountyName
    FROM Country
    INNER JOIN State 
        ON State.CountryName = Country.CountryName
    INNER JOIN County 
        ON County.StateName = State.StateName 
        AND County.CountryName = State.CountryName
        AND County.CountryName = Country.CountryName

As you can see, that gets carried away in a big hurry, and admittedly, this is bad example for a Select statement, since all the information is in the county table. However, many databases don't support multiple column foreign key constraints, so imagine what happens when someone types the wrong county name when entering a county. By each and every table having a unique row identifier, it allows you to reference that row for integrity with foreign keys and simplifies those joins in your SQL.

SELECT Country.Name as Country, State.Name as State, County.Name  as County
    FROM Country
    INNER JOIN State 
        ON State.Country_ID = Country.ID
    INNER JOIN County 
        ON County.State_ID = State.ID

As you can see, it simplifies the SQL as well. Before I leave this subject, I'd like to touch on GUIDs vs. other keys.

Unique Identifiers and Primary Keys

There is a lot of arguments about whether or not GUIDs make useful primary keys. I think the point is being missed, GUIDs are supposed to be unique identifiers, this is not to say that they should be used for the primary key, because then clustering (organization of the rows in the actual file system) would be meaningless, and thus performance will degrade horribly. These GUIDs should be used as a unique row identifier, and in some cases, they are required for synchronization technologies.

A very common complaint about GUIDs is that they are hard to remember. Yes that is true, which is why they should never be used as the primary key; the thing that makes the row unique should be the primary key. Ideally, human meaningful data so humans can look at it. But when enforcing constraints at the database level, especially in relationships, it is nice to know that you can not put the wrong data into a column. Take a look at the following entity relationship diagram:

Untitled.png

Looking at this, we see that foreign key relationships have been put on the tables, so as far as the database can tell, a row will be valid as long as a row with the correct number exists in the parent tables. But if we realize that they are just integers, a bug in a program, a cut and paste error, or typo in a Stored Procedure could flip that data around. inserting the numbers from the person table into the "car_id" column and the numbers from the car table into the "person_id" column. Depending on the number of rows in each table, it may be a very long time before the error is caught, and then all the data has to be re-entered. Thus, just because you have a foreign key, that alone doesn't guarantee valid data. However, if the ID columns are indeed GUIDs, the chances of such mistakes are minimized to the point of virtual non-existence.

In other words, this SQL is much more likely to be wrong and not caught:

INSERT INTO Car_Owner (person_id, car_id) VALUES (3, 5)

Than this one is:

INSERT INTO Car_Owner (person_id, car_id) 

VALUES ('{E1D56D43-4FCA-44B1-8D16-BF7F106D0A6D}',

'{BCFB7934-6FB2-4AC1-96BC-1D8D46C7067D}')

Primary Keys should be on the unique data for the row

Two part thought here, first, GUIDs aren't meaningful to humans, you should not need to know the GUID for day to day use of your data. They are for data integrity, not for use by people. Second, when looking for data, the database needs to be able to find that data easily. So you should never make a person table's unique key, the GUID, you would make it something unique about them, perhaps their social security number, with a secondary non-unique index on their last, middle, and first names. The problem with using the name as the primary key is names like John Smith aren't unique, however that will likely be a common search item, hence the non-unique index.

Columns that reference other tables

When a table needs to reference an existing row in another table, it should follow a few rules:

  • Such columns should only reference the row ID column
  • The reference should be enforced with a foreign key constraint
  • It should include the table name

Touching on each point individually, I will start with the first one. A table should contain unique data, that is the reason for its existence. There are two rows in the table with the exact same data, you have a problem, however the row might be associating two other tables, like my Car_Owner table above. If I have a table that now needs to reference that table, I don't want to keep that relationship in another place, and I want to make sure that the relationship exists. So rather than keeping two columns in my new table, I would simply keep the ID column from Car_Owner, or as another example, I wouldn't want to keep the County, State, and Country, columns in my City table, when I can keep the single column of County_ID in the City table.

For the second point, it's fairly simple, we tell the database to ensure that the data we are referencing actually exists.

Lastly, including the table name ensures consistency. I know that if I have a column named Person_ID that it is going to be the ID column from the Person table.

Relationship tables should only join two tables

All too often, people will try to force multiple relationships into a single table. For example, look at the following image:

Untitled2.png

From this relationship, you can't tell how this relationship is supposed to be, or that the other relationships, like a user belonging to one or multiple groups actually exist. If the relationship where defined two at a time, you could tell if this table where associating medias to groups of users, or groups of media to users, or what. The associations would also be guaranteed to exist before making the next association. For example, in a car lease contract for a corporation, you would want to make sure the contract and corporation exist, before you start assigning cars to it.

Use schema/namespaces to separate like named objects

In the old days, or when using weak databases, you would have to resort to naming your object differently to be able to tell apart a State (a plot of land) from a State (where in a workflow your process is). So you would end up naming one WorkFlowState and the other State, which is fine, but modern databases can partition the two objects into separate blocks. Some databases call these blocks "schemas", some call them "namespaces", while MySQL seems to think they are separate databases. For the most part, the partitioning of these objects into namespaces is conceptually no different than making objects in your program use different namespaces. Your query will have to be specific, but it doesn't prevent the object from being used.

Fear of keywords

As you can tell, I am not afraid of using words for column and table names that might be keywords. Most modern databases give you some way to handle escaping keywords so you can use them as things like column names. SQL92, which should have been adhered to by all database now, specifies the double quote ( " ) character to do this. Microsoft SQL Server uses square brackets ( [] ) to do it, and if QUOTED_IDENTIFIER ON is specified, it allows double quotes. MySQL uses, of all things, the accent grave (`).

For all you .NET coders, the DataProviders give you the characters if you know where to look.

Make full use of your database

Strongly type your data

Just like in programming, there are different types to do different things, use the proper type for the job. In other words, strongly type your data.

  • Use a boolean or bit to hold true/false values
  • Don't use character fields to hold numbers
  • Make sure number fields have constraints for valid values
  • Only use char/nchar fields when the data is truly fixed length

Just like in programming, these types not only help you keep the data available efficiently, but they help enforce the integrity of the data. Using fixed length character fields to hold variable length data is a personal peeve of mine. Because if the data isn't as long as the field, the database pads it, requiring the programming to trim the padding everywhere.

Use Cascades, Triggers, and Constraints

Cascades make sure that when you delete or update a row, rows that depend on it are deleted or changed as well.

Triggers can help make sure that calculations get run when data is updated.

Constraints on fields can make sure of things like "this field must be a positive number". The thing to be aware of though is use of this to enforce "magic values", i.e., "this field must be a 'P', 'Q' or 'Z'": that is a sure sign that it really should be a foreign key to a table, so you can display it to the user.

Avoid overloading fields

Don't use a field to indicate one thing, say price, in one circumstance, and another thing, say discount percentage, in another. It makes writing both SQL and code against the database nightmarish.

Bringing it all together

As you can tell, when I make a table that represents relationships between multiple tables, my best thought is to name the table the table names that it is joining, separated by an underscore. Even in databases (or database settings) that support differentiating by case only, I don't want confusion between multi-word table names and relationship table names; for example, I don't want User_Groups to be confused with UserGroups.

These guidelines mean you can normalize your data in a meaningful way, ensuring data integrity.

At this point, someone is going to whine about the performance of normalized databases versus non-normalized databases, and someone else will join in about how GUIDs are big and slow. Think about this though, the data in your database is likely of paramount importance, are you willing to sacrifice a small amount of speed to be guaranteed the integrity of your data, or are you willing to go down the route of super high performance and possibly have your data trashed? If you really stop and think about it, normalization can enhance performance by allowing updates to every user in a group by simply changing the group record, rather than having to change every user row as you would in a non-normalized database.

Using consistent naming means I can save time in writing SQL, because I know what things will be named, and joins will be easy and consistently fast. Furthermore, if a well written Object Relational Mapper is used, I might be able to take advantage of inheritance in the programming model.

So as a final example, here is a normalized database example using Country, State, County, and City, and relationship tables. It may be over-normalized, but it means there will only be one record per name, things like populations, zip codes etc. could be added to the relationship records where they are meaningful. However, this is a nice academic example but it isn't worthwhile for a business example; because of Consolidated City Counties, cities like St. Louis Missouri, which does not exist within any county, and because of Washington D.C. which doesn't exist within any state. However, it does account for a city named Springfield in every state, with no data duplication.

Untitled3.png

SELECT   
        Country.Name as Country, State.Name AS State, County.Name AS County, City.Name AS City
    FROM   Country
    INNER JOIN Country_State 
        ON Country.ID = Country_State.Country_ID 
    INNER JOIN State 
        ON Country_State.State_ID = State.ID 
    INNER JOIN  State_County 
        ON Country_State.ID = State_County.Country_State_ID 
    INNER JOIN  County 
        ON State_County.County_ID = County.ID 
    INNER JOIN County_City 
        ON State_County.ID = County_City.State_County_ID 
    INNER JOIN City 
        ON County_City.City_ID = City.ID

Gotchas

Like any other ideas on designing databases, there are things that could cause problems. People depending on natural joins is a big one, and I addressed that issue above. The only real problem I have run into is trying to use Entity Framework with this design. While I haven't tried version 4 with this design, version 3.5 has a very serious problem even when using SQL Server. EntityFramework doesn't seem to pick up the relationships for foreign keys unless they are against the primary key; this bug forced me to create a clustered unique constraint on a Name column and make my ID column a primary key.

Things for next time

I haven't touched on several items, like naming Views or Stored Procedures. Nor did I touch on writing SQL too much, I tried to keep it to just the SQL necessary to explain the choices I have made. Remember to let me know what you think of my articles by voting.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Alaric Dailey
Software Developer (Senior) Pengdows
United States United States
Member
Currently looking for new contracts in Omaha NE or telecommute opportunities.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionnaming conventions for database design: for beginnersprofessionalRavi.Kumar02119 May '13 - 21:38 
Its really nice. Thanks!
 
I have found another article especially for beginners visit http://www.etechpulse.com/2013/05/naming-convention-for-database-design.html[^]
 

Regards,
Ravi Kumar
QuestionSome good points but also some very wrong things...memberthe.Kris2 Aug '11 - 1:20 
Where did you get "most databases don't support a multiple column foriegn key" ?
I've worked with MS SQL, MySQL, Oracle, PostgreSQL, SQLite, ... Just to name a few, and they ALL support multi-column foreign keys.
 
Reading the article I got the impression you were on the right track. (right = trying to be consistent and sensible about your choices and thinking them through), but arriving at your final example dropped that impression to the bottom of the ocean...
 
First, the names are wrong. You are in fact de-duping the names of the cities, countries... instead of normalizing entity information. The table names would be more correct if they were country_name, state_name, city_name. To apply an example: city "Antwerp" exists in different countries and although they have the same name, they really are different entities.
It is very important to have the correct table name for the type of entity it contains, to prevent confusion. Your Country_State actually defines a unique State entity, so should be called State, while your State table should be named StateName or something like it.
 
Next to that your over-normalizing (read as: de-duping) actually increases data and index storage, increases query length and complexity. It would be good to normalize a name like that if there were many cities (entities) for each name, e.g. if there were a thousand or maybe a million cities named "ThisIsTheCityWithTheWayTooLongName", then the city table would take up less space.
 
However, this is a nice academic example but it isn't worthwhile for a business example
I would state: this is a nice example of how not to do this. I will agree with the fact that there are situations where the given way-of-work is the right solution, just not with countries, states, counties and cities.
 
My conclusion, you do get points for thinking about this stuff and sharing it with others. There will never be a single perfect solution, but only many good solutions.
AnswerRe: Some good points but also some very wrong things...memberAlaric Dailey2 Aug '11 - 2:13 
Even if I am wrong about "most" not being able to handle it, which I am happy to admit, there are still DBs that don't. Even if you aren't designing with the idea of being able to upgrade from one DB to another in the future, multiple column foreign keys are a PITA.
 
I did say the example was over-normalized, and didn't account for all the data in the real world. There a multiple problems with the example, like not every country has entities that match up to counties and states. It doesn't account for groups of countries (like the UK) or groups of groups of countries (like the EU including the UK).
 
"Antwerp" in different countries would have a different County_City, record, thus each would have a Unique County_City.ID that represents its unique existence. This example makes the name exist once, not the entity.
 
I would say that users of the system would never see the guids that represent the entity, they would simply see, the names.
 
All that aside. I agree with "There will never be a single perfect solution, but only many good solutions.
Questiondidnt read it all but i dont agree already..memberHaBiX1 Aug '11 - 21:31 
i'd take Person.PersonID over Person.ID naming conventions any time..
 
i dont support the fact that querys get "auto-built" (they even get built with different field names, having foreign keys setup, having db schema, etc..) - stuff will get auto-hooked in any way
 

but i'd rather have longer clearer field names than 10 fields named "id"
AnswerRe: didnt read it all but i dont agree already..memberAlaric Dailey2 Aug '11 - 1:32 
Everyone disagrees about something with someone.
 
there are 3 reasons why I think that names that are used for the same thing like a row ID should always be named the same.
 
1. consistency - If I am making a dropdown list against a table I designed, I know that I can use the follow SQL and just swap out the tablename
SELECT ID, Name, Description FROM  schema.tableName
I also know that if I want to join another table, how it neeeds to look. Furthermore, because I am not using the table name in the ID column I can do heirarchies by joining back the parent with the tablename_id
 
 
/****** Object:  Table [dbo].[Node]    Script Date: 08/02/2011 06:25:59 ******/
SET ANSI_NULLS ON
GO
 
SET QUOTED_IDENTIFIER ON
GO
 
CREATE TABLE [dbo].[Node](
	[ID] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
	[Name] [nvarchar](50) NOT NULL,
	[Description] [nvarchar](500) NOT NULL,
	[Node_ID] [uniqueidentifier] NULL,
 CONSTRAINT [IX_Node] UNIQUE NONCLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
 CONSTRAINT [IX_Node_1] UNIQUE NONCLUSTERED 
(
	[Name] ASC,
	[Node_ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
 
GO
 
ALTER TABLE [dbo].[Node]  WITH CHECK ADD  CONSTRAINT [FK_Node_Node] FOREIGN KEY([Node_ID])
REFERENCES [dbo].[Node] ([ID])
GO
 
ALTER TABLE [dbo].[Node] CHECK CONSTRAINT [FK_Node_Node]
GO
 
ALTER TABLE [dbo].[Node] ADD  CONSTRAINT [DF_Node_ID]  DEFAULT (newid()) FOR [ID]
GO
 
2. As my OR/M articles progress I intend to show how to do inheritance of tables as objects, if you don't name things the same way, polymorphism won't work right.
 
3. One of the big reasons people do the prefixing is to avoid key words. My code[^] Allows me not to give a darn, about keywords.
GeneralRe: didnt read it all but i dont agree already..memberHaBiX2 Aug '11 - 20:40 
For me your join querys from article seems inconsitent:
INNER JOIN City
    ON County_City.City_ID = City.ID
 
City_ID -> City.ID
 
For your nodes table, i'd use (did use) NodeID, ParentNodeID naming anytime. I would also call table "Nodes".
 
You're saying you're not using "table id" for column names, but your "ParentNodeID" in sample is named "Node_ID". Not only its not consistent again (one field is ID, other is table name + id), a developer opening your project wouldnt know what those fields mean just by names.
A true generic way of hiearchy would be "ID" & "ParentID" in table name "xy".
 

All n-tier apps have DAO and BI confiured before developing (they know all the tables, etc). I dont see a problem making BI working with combobox in a genetic way - DAO knows all the PK names.
 

For prefixing: to avoid keywords i prefix with real words based on context of field and never with "tbl", "col", "view", "str", etc..
eg: [From] => [FromDestination], [TimeStamp] => [Stamp],...
GeneralRe: didnt read it all but i dont agree already..memberAlaric Dailey3 Aug '11 - 2:22 
I don't see where
INNER JOIN City
    ON County_City.City_ID = City.ID
is in consistent, it is explicit, and does exactly what I said, the table referencing a foreign table, names that table.
 
Exactly the same with Node_ID, in a node table, points to the table. easy and consistent.
 
At this point, your opinion obviously won't be changed, and you are only looking for an argument, as is shown by your original statement of "Didn't read it all, but I don't agree already", and by arguing with others that responded as well.
GeneralRe: didnt read it all but i dont agree already..memberHaBiX3 Aug '11 - 3:25 
You're right - i probably wont change my opinion on naming as in my time of development i switched from your variation to mine Smile | :)
 
But no, i'm not looking for argument. I think the most important thing is keeping it consistant over whole solution to your personal/company standard.
QuestionGood post with a few comments..memberweberrich29 Jul '11 - 12:14 
Good article, and I agree with many of the suggestions. There are a few comments.
 
• Guids as Primary keys?? Im not even talking about space or performance. Yes I can consider it, but how about and identity column?? And if you hit max, then you have not "typed" the column correctly.
 
• Additionally, I personally like to have the “tbl” and “idx” along with “ssp” prefix. Agreed “col” prefix is overdoing it. The prefix should be help identify what is this name. Now should there be an additional underscore??
 
• In your Unique Identifiers and Primary Keys section.. Spaces in the field Names? I know it's an example but, I would not like to create any column that requires escape characters '[]', ', or whatever.
 
• So in your Relationship Tables Should Only Join 2 Tables, I can see the issue, but how would this be designed. The question is at the id fields nullable? Then the issue is what is the usage.
 
• Keywords should be avoided. Making it easier for development on both sides, software and database. Avoiding creating rules is the best way to make development easier.
 
• Cascades deletes is a way to get yourself in trouble. I use FK constraints to enforce various rules. Just have to look for orphans records. or a stored procedure to perform the delete manually.
 
Just as a small teaser, I like to establish basic rules: OMG | :OMG:
 
• Segregate keys on all tables. All Table identity columns as 'ID', so all tables have an ID column. Maybe even modified date and modified by based on a trigger.
 
• If a column can have more than one value, and the number of values can be predicted (zip-codes, state, city, country, etc...) There must be a look-up table with a foreign key.
 
So, do we create a tbl_YesNo. Correct an look-up table dedicated to two values yes and no. Consider this, you can have yes/no, true/false, active/closed, pass/fail then in a query you can display easier names to users. For you developers, think enumeration (-1, 0, 1)
AnswerRe: Good post with a few comments..memberAlaric Dailey29 Jul '11 - 13:20 
To each their own, I will agree to disagree on some points.
 
Guids as primary keys - no, as ID fields, the primary key should be meaningful to those using the data, whatever it is that makes the row unique.
 
Prefixes - ick, agree to disagree. But additional underscores, For the most part when creating indexes I let the DB choose the name (as most of the time I am using SQL Server) if I am choosing the names I use casing to separate words. At that point things get complicated and it becomes easier to just create the DB as I want it in Enterprise Manager and let it create my names for indexes and the like.
 
Spaces in Column Names and Keywords should be avoided - If you look at some of my other articles, specifically this one[^], you will see that I account for using anything I like in my table and column names, keywords, special characters, and spaces. While I often use keywords like "Name", "Default" and "Group", I never use spaces or special characters when I design a database, not because my code can't handle it, but because some databases, and certain tools can't handle it. It's humorous that the enterprise manager like tool built into visual studio removes the wrapping brackets and then fails to be able to execute the following
SELECT [ID], [Default], [Name] FROM [dbo].[Group] 
It's always better to be able to handle names with special garbage in them, so my code reflects that. One time I ran into a column that was obviously due to a script with a typo in it, it named
Name varchar(20) NOT NULL,
	Description
Yes it did even have the Carriage Return in the name, my code was the only thing that could pull that data out.
 

Relationships joining 2 tables - One thing I didn't cover and probably should have is that ID fields should NEVER be null, and in fact Null fields should be kept to a minimum. There are uses, I would never argue that as some DBA's I know do, but I would say that uses are somewhat rare if the DB is well done.
 
Cascades can get you into trouble, my choice is to simply turn them off if I shouldn't be deleting that data.
 
So, do we create a tbl_YesNo. - Only in Oracle or other DBs that have the shortsightedness to NOT include a boolean type.
 
In the case of Enumerations, a small table with a few values and descriptions is so much better than not having it. Then reports can be done with SQL joins rather than having to get complex and write joins or stored procs or the like just to translate 'O' into 'Open' and 'V' into 'Void'.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 2 Aug 2011
Article Copyright 2011 by Alaric Dailey
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid