diff --git INSTALL.pgsql.txt INSTALL.pgsql.txt
index f5f276e..57178bb 100644
--- INSTALL.pgsql.txt
+++ INSTALL.pgsql.txt
@@ -26,3 +26,19 @@ Note that the database must be created with UTF-8 (Unicode) encoding.
      createdb --encoding=UTF8 --owner=username databasename
 
    If there are no errors then the command was successful
+
+3. CREATE A SCHEMA OR SCHEMAS (Optional Advanced)
+
+  Drupal will run across different schemas within your database if you so wish.
+  By default, Drupal runs inside the 'public' schema but you can use $db_prefix
+  inside settings.php to define a schema for drupal to inside of or specify tables
+  that are shared inside of a separate schema. Drupal will not create schemas for 
+  you, infact the user that drupal runs as should not be allowed to. You'll need
+  execute the SQL below as a superuser (such as a postgres user) and replace
+  'drupaluser' with the username that drupal uses to connect to PostgreSQL with
+  and replace schema_name with a schema name you wish to use such as 'shared':
+
+    CREATE SCHEMA schema_name AUTHORIZATION drupaluser;
+
+  Do this for as many schemas as you need. See default.settings.php for how to 
+  set which tables use which schemas.
diff --git includes/database/database.inc includes/database/database.inc
index 946a495..6937adc 100644
--- includes/database/database.inc
+++ includes/database/database.inc
@@ -426,6 +426,25 @@ abstract class DatabaseConnection extends PDO {
   }
 
   /**
+   * Find the prefix for a table
+   *
+   * This is not used in prefixTables due to performance reasons.
+   */
+  public function tablePrefix($table = 'default') {
+    global $db_prefix;
+    if (is_array($db_prefix)) {
+      if (isset($db_prefix[$table])) {
+        return $db_prefix[$table];
+      }
+      elseif (isset($db_prefix['default'])) {
+        return isset($db_prefix['default']);
+      }
+      return '';
+    }
+    return $db_prefix;
+  }
+
+  /**
    * Prepare a query string and return the prepared statement.
    *
    * This method caches prepared statements, reusing them when
diff --git includes/database/mysql/schema.inc includes/database/mysql/schema.inc
index 16f3fd5..4121ce2 100644
--- includes/database/mysql/schema.inc
+++ includes/database/mysql/schema.inc
@@ -25,6 +25,27 @@ class DatabaseSchema_mysql extends DatabaseSchema {
   const COMMENT_MAX_COLUMN = 255;
 
   /**
+   * Get information about the table and database name from the db_prefix.
+   *
+   * @return
+   *   A keyed array with information about the database, table name and prefix.
+   */
+  protected function getPrefixInfo($table = 'default', $key = null) {
+    $info = array(
+              'database' => '',
+              'prefix' => $this->connection->tablePrefix($table),
+            );
+    if (($pos = strpos($info['prefix'], '.')) !== FALSE) {
+      $info['database'] = substr($info['prefix'], 0, $pos);
+      $info['table'] = substr($info['prefix'], ++$pos) . $table;
+    }
+    else {
+      $info['table'] = $info['prefix'] . $table;
+    }
+    return $key ? $info[$key] : $info;
+  }
+
+  /**
    * Build a condition to match a table name against a standard information_schema.
    *
    * MySQL uses databases like schemas rather than catalogs so when we build
@@ -265,7 +286,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
   }
 
   public function renameTable(&$ret, $table, $new_name) {
-    $ret[] = update_sql('ALTER TABLE {' . $table . '} RENAME TO {' . $new_name . '}');
+    $ret[] = update_sql('ALTER TABLE {' . $table . '} RENAME TO `' . $this->getPrefixInfo($new_name, 'table') . '`');
   }
 
   public function dropTable(&$ret, $table) {
diff --git includes/database/pgsql/schema.inc includes/database/pgsql/schema.inc
index 61080c0..b4614ed 100644
--- includes/database/pgsql/schema.inc
+++ includes/database/pgsql/schema.inc
@@ -68,7 +68,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
     }
     return $this->tableInformation[$key];
   }
-
+  
   /**
    * Generate SQL to create a new table from a Drupal schema definition.
    *
@@ -91,7 +91,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
     }
     if (isset($table['unique keys']) && is_array($table['unique keys'])) {
       foreach ($table['unique keys'] as $key_name => $key) {
-        $sql_keys[] = 'CONSTRAINT {' . $name . '}_' . $key_name . '_key UNIQUE (' . implode(', ', $key) . ')';
+        $sql_keys[] = 'CONSTRAINT ' . $this->_prefixNonTable($name, $key_name, 'key') . ' UNIQUE (' . implode(', ', $key) . ')';
       }
     }
 
@@ -277,7 +277,12 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
    *   The new name for the table.
    */
   function renameTable(&$ret, $table, $new_name) {
-    $ret[] = update_sql('ALTER TABLE {' . $table . '} RENAME TO {' . $new_name . '}');
+    // The new name of a table doesn't need to be referenced by schema.
+    // In the situation where the db_prefix is something like schema.prefix,
+    // the query will fail. So we must figure this out here instead of wrapping
+    // the new column in curly braces.
+    $prefixInfo = $this->getPrefixInfo($new_name);
+    $ret[] = update_sql('ALTER TABLE {' . $table . '} RENAME TO "' . $prefixInfo['table'] . '"');
   }
 
   /**
@@ -418,7 +423,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
    *   The table to be altered.
    */
   public function dropPrimaryKey(&$ret, $table) {
-    $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP CONSTRAINT {' . $table . '}_pkey');
+    $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $this->_prefixNonTable($table, 'pkey'));
   }
 
   /**
@@ -434,8 +439,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
    *   An array of field names.
    */
   function addUniqueKey(&$ret, $table, $name, $fields) {
-    $name = '{' . $table . '}_' . $name . '_key';
-    $ret[] = update_sql('ALTER TABLE {' . $table . '} ADD CONSTRAINT "' . $name . '" UNIQUE (' . implode(',', $fields) . ')');
+   $ret[] = update_sql('ALTER TABLE {' . $table . '} ADD CONSTRAINT "' . $this->_prefixNonTable($table, $name, 'key') . '" UNIQUE (' . implode(',', $fields) . ')'); 
   }
 
   /**
@@ -449,8 +453,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
    *   The name of the key.
    */
   public function dropUniqueKey(&$ret, $table, $name) {
-    $name = '{' . $table . '}_' . $name . '_key';
-    $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP CONSTRAINT "' . $name . '"');
+    $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP CONSTRAINT "' . $this->_prefixNonTable($table, $name, 'key') . '"');
   }
 
   /**
@@ -480,8 +483,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
    *   The name of the index.
    */
   public function dropIndex(&$ret, $table, $name) {
-    $name = '{' . $table . '}_' . $name . '_idx';
-    $ret[] = update_sql('DROP INDEX ' . $name);
+    $ret[] = update_sql('DROP INDEX ' . $this->_prefixNonTable($table, $name, 'idx'));
   }
 
   /**
@@ -578,7 +580,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
   }
 
   protected function _createIndexSql($table, $name, $fields) {
-    $query = 'CREATE INDEX "{' . $table . '}_' . $name . '_idx" ON {' . $table . '} (';
+    $query = 'CREATE INDEX "' . $this->_prefixNonTable($table, $name, 'idx') . '" ON {' . $table . '} (';
     $query .= $this->_createKeySql($fields) . ')';
     return $query;
   }
@@ -600,10 +602,19 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
   }
 
   /**
+   * Create names for Indexes, Primary Keys and Contstraints
+   */
+  function _prefixNonTable($table) {
+    $args = func_get_args();
+    $args[0] = $this->getPrefixInfo($table, 'table');
+    return implode('_', $args);
+  }
+
+  /**
    * Retrieve a table or column comment.
    */
   public function getComment($table, $column = NULL) {
-    $table = $this->connection->prefixTables('{' . $table . '}');
+    $table = $this->getPrefixInfo($table, 'table');
     // Don't use {} around pg_class, pg_attribute tables.
     if (isset($column)) {
       return db_query('SELECT col_description(oid, attnum) FROM pg_class, pg_attribute WHERE attrelid = oid AND relname = ? AND attname = ?', array($table, $column))->fetchField();
diff --git includes/database/schema.inc includes/database/schema.inc
index 442fedd..6531d47 100644
--- includes/database/schema.inc
+++ includes/database/schema.inc
@@ -150,11 +150,54 @@ abstract class DatabaseSchema {
 
   protected $connection;
 
+  /**
+   * Definition of prefixInfo array structure.
+   *
+   * Rather than redefining DatabaseSchema::getPrefixInfo() for each driver,
+   * by defining the defaultSchema variable only MySQL has to re-write the
+   * method.
+   *
+   * @see DatabaseSchema::getPrefixInfo()
+   */ 
+  protected $defaultSchema = 'public';
+
   public function __construct($connection) {
     $this->connection = $connection;
   }
 
   /**
+   * Get information about the table name and schema from the db_prefix.
+   *
+   * @return
+   *   A keyed array with information about the schema, table name and prefix.
+   */
+  protected function getPrefixInfo($table = 'default', $key = NULL) {
+    $info = array(
+              'schema' => $this->defaultSchema,
+              'prefix' => $this->connection->tablePrefix($table),
+            );
+    if (($pos = strpos($info['prefix'], '.')) !== FALSE) {
+      $info['schema'] = substr($info['prefix'], 0, $pos);
+      $info['table'] = substr($info['prefix'], ++$pos) . $table;
+    }
+    else {
+      $info['table'] = $info['prefix'] . $table;
+    }
+    return $key ? $info[$key] : $info;
+  }
+
+  /**
+   * Create names for Indexes, Primary Keys and Contstraints.
+   *
+   * This prevents using {} around non-table names like indexes and keys.
+   */
+  function _prefixNonTable($table) {
+    $args = func_get_args();
+    $args[0] = $this->getPrefixInfo($table, 'table');
+    return implode('_', $args);
+  }
+
+  /**
    * Build a condition to match a table name against a standard information_schema.
    *
    * The information_schema is a SQL standard that provides information about the
diff --git includes/database/sqlite/schema.inc includes/database/sqlite/schema.inc
index d32ef98..5b78940 100644
--- includes/database/sqlite/schema.inc
+++ includes/database/sqlite/schema.inc
@@ -14,6 +14,11 @@
 
 class DatabaseSchema_sqlite extends DatabaseSchema {
 
+  /**
+   * Override DatabaseSchema::$defaultSchema
+   */
+  protected $defaultSchema = 'main';
+
   public function tableExists($table) {
     // Don't use {} around sqlite_master table.
     return (bool) $this->connection->query("SELECT name FROM sqlite_master WHERE type = 'table' AND name LIKE '{" . $table . "}'", array(), array())->fetchField();
@@ -47,12 +52,12 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
     $sql = array();
     if (!empty($schema['unique keys'])) {
       foreach ($schema['unique keys'] as $key => $fields) {
-        $sql[] = 'CREATE UNIQUE INDEX "{' . $tablename . '}_' . $key . '" ON {' . $tablename . '} (' . $this->createKeySql($fields) . "); \n";
+        $sql[] = 'CREATE UNIQUE INDEX "' . $this->_prefixNonTable($tablename, $key) . '" ON {' . $tablename . '} (' . $this->createKeySql($fields) . "); \n";
       }
     }
     if (!empty($schema['indexes'])) {
       foreach ($schema['indexes'] as $index => $fields) {
-        $sql[] = 'CREATE INDEX "{' . $tablename . '}_' . $index . '" ON {' . $tablename . '} (' . $this->createKeySql($fields) . "); \n";
+        $sql[] = 'CREATE INDEX "' . $this->_prefixNonTable($tablename, $key) . '" ON {' . $tablename . '} (' . $this->createKeySql($fields) . "); \n";
       }
     }
     return $sql;
@@ -218,7 +223,11 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
   *   The new name for the table.
   */
   public function renameTable(&$ret, $table, $new_name) {
-    $ret[] = update_sql('ALTER TABLE {' . $table . '} RENAME TO {' . $new_name . '}');
+    // The new name of a table doesn't need to be referenced by schema.
+    // In the situation where the db_prefix is something like schema.prefix,
+    // the query will fail. So we must figure this out here instead of wrapping
+    // the new column in curly braces.
+    $ret[] = update_sql('ALTER TABLE {' . $table . '} RENAME TO ' . $this->getPrefixInfo($new_name, 'table'));
   }
 
   /**
@@ -447,7 +456,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
    *   The name of the index.
    */
   public function dropIndex(&$ret, $table, $name) {
-    $ret[] = update_sql('DROP INDEX ' . '{' . $table . '}_' . $name);
+    $ret[] = update_sql('DROP INDEX ' . $this->_prefixNonTable($table, $name));
   }
 
   /**
@@ -481,7 +490,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
    *   The name of the key.
    */
   public function dropUniqueKey(&$ret, $table, $name) {
-    $ret[] = update_sql('DROP INDEX ' . '{' . $table . '}_' . $name);
+    $ret[] = update_sql('DROP INDEX ' . $this->_prefixNonTable($table, $name));
   }
 
   /**
diff --git sites/default/default.settings.php sites/default/default.settings.php
index 7e3ded1..6dc2c25 100644
--- sites/default/default.settings.php
+++ sites/default/default.settings.php
@@ -130,6 +130,17 @@
  *     'authmap'   => 'shared_',
  *   );
  *
+ * For PostgreSQL, you can also specify a schema as a part of the
+ * prefix if the schema's already exist, for example:
+ *
+ *  $db_prefix = array(
+ *    'default' => 'main.',
+ *     'users'      => 'shared.',
+ *     'sessions'  => 'shared.',
+ *     'role'      => 'shared.',
+ *     'authmap'   => 'shared.',
+ *  );
+ *
  * Database configuration format:
  *   $databases['default']['default'] = array(
  *     'driver' => 'mysql',
