diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c
index 9fec6fa0d..4a9ae3286 100644
--- a/lib/db-ctl-base.c
+++ b/lib/db-ctl-base.c
@@ -2170,6 +2170,20 @@ ctl_get_db_cmd_usage(void)
 Potentially unsafe database commands require --force option.\n";
 }
 
+const char *
+ctl_list_db_tables_usage(struct ds *tables, const struct ovsdb_idl_table_class *class,
+               int n_tables)
+{
+    if (!tables->length) {
+        ds_put_cstr(tables, "Valid tables for this database are:\n");
+        for (int i = 0; i < n_tables; i++) {
+            ds_put_format(tables, "  %s\n", class[i].name);
+        }
+    }
+
+    return ds_cstr(tables);
+}
+
 /* Initializes 'ctx' from 'command'. */
 void
 ctl_context_init_command(struct ctl_context *ctx,
diff --git a/lib/db-ctl-base.h b/lib/db-ctl-base.h
index 81f0d0b27..71fb123c5 100644
--- a/lib/db-ctl-base.h
+++ b/lib/db-ctl-base.h
@@ -159,6 +159,9 @@ struct ctl_command {
 
 bool ctl_might_write_to_db(char **argv);
 const char *ctl_get_db_cmd_usage(void);
+
+const char *ctl_list_db_tables_usage(struct ds *tables,
+    const struct ovsdb_idl_table_class *class, int n_tables);
 void ctl_print_commands(void);
 void ctl_print_options(const struct option *);
 void ctl_add_cmd_options(struct option **, size_t *n_options_p,
diff --git a/ovn/lib/ovn-util.h b/ovn/lib/ovn-util.h
index 9b456426d..e7e84b98e 100644
--- a/ovn/lib/ovn-util.h
+++ b/ovn/lib/ovn-util.h
@@ -67,6 +67,11 @@ char *alloc_nat_zone_key(const struct uuid *key, const char *type);
 const char *default_nb_db(void);
 const char *default_sb_db(void);
 
+struct ovsdb_idl_table_class;
+const char *db_table_usage(struct ds *tables,
+                           const struct ovsdb_idl_table_class *class,
+                           int n_tables);
+
 bool ovn_is_known_nb_lsp_type(const char *type);
 
 #endif
diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml
index 4d0aea963..7f4b3aba8 100644
--- a/ovn/utilities/ovn-nbctl.8.xml
+++ b/ovn/utilities/ovn-nbctl.8.xml
@@ -820,64 +820,11 @@
     additional ways to identify records.  Some commands also take
     <var>column</var> parameters that identify a particular field within the
     records in a table.</p>
-    <p>The following tables are currently defined:</p>
-    <dl>
-      <dt><code>Logical_Switch</code></dt>
-      <dd>
-        An L2 logical switch.  Records may be identified by name.
-      </dd>
-
-      <dt><code>Logical_Switch_Port</code></dt>
-      <dd>
-        A port within an L2 logical switch.  Records may be identified by name.
-      </dd>
-
-      <dt><code>ACL</code></dt>
-      <dd>
-        An ACL rule for a logical switch that points to it through its <var>acls</var> column.
-      </dd>
-
-      <dt><code>Logical_Router</code></dt>
-      <dd>
-        An L3 logical router.  Records may be identified by name.
-      </dd>
-
-      <dt><code>Logical_Router_Port</code></dt>
-      <dd>
-        A port within an L3 logical router.  Records may be identified by name.
-      </dd>
-
-      <dt><code>Logical_Router_Static_Route</code></dt>
-      <dd>
-        A static route belonging to an L3 logical router.
-      </dd>
 
-      <dt><code>Address_Set</code></dt>
-      <dd>
-        An address set that can be used in ACLs.
-      </dd>
-
-      <dt><code>Load_Balancer</code></dt>
-      <dd>
-        A load balancer for a logical switch that points to it through its <var>load_balancer</var> column.
-      </dd>
-
-      <dt><code>NAT</code></dt>
-      <dd>
-        A NAT rule for a Gateway router.
-      </dd>
-
-      <dt><code>DHCP_Options</code></dt>
-      <dd>
-        DHCP options.
-      </dd>
-
-      <dt><code>NB_Global</code></dt>
-      <dd>
-        North bound global configurations.
-      </dd>
-
-    </dl>
+    <p>
+      For a list of tables and their columns, see <code>ovn-nb</code>(5) or
+      see the table listing from the <code>--help</code> option.
+    </p>
 
     <p>
       Record names must be specified in full and with correct capitalization,
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c
index b3f60bdb7..1152ee075 100644
--- a/ovn/utilities/ovn-nbctl.c
+++ b/ovn/utilities/ovn-nbctl.c
@@ -314,6 +314,14 @@ parse_options(int argc, char *argv[], struct shash *local_options)
     free(options);
 }
 
+static const char *db_table_list(void)
+{
+    static struct ds tables = DS_EMPTY_INITIALIZER;
+
+    return ctl_list_db_tables_usage(&tables, nbrec_table_classes,
+                                    NBREC_N_TABLES);
+}
+
 static void
 usage(void)
 {
@@ -455,6 +463,7 @@ SSL commands:\n\
 set the SSL configuration\n\
 \n\
 %s\
+%s\
 \n\
 Synchronization command (use with --wait=sb|hv):\n\
   sync                     wait even for earlier changes to take effect\n\
@@ -469,6 +478,7 @@ Options:\n\
   --dry-run                   do not commit changes to database\n\
   --oneline                   print exactly one line of output per command\n",
            program_name, program_name, ctl_get_db_cmd_usage(),
+           db_table_list(),
            default_nb_db());
     table_usage();
     vlog_usage();
diff --git a/ovn/utilities/ovn-sbctl.8.in b/ovn/utilities/ovn-sbctl.8.in
index cd43cf3be..c59a9f542 100644
--- a/ovn/utilities/ovn-sbctl.8.in
+++ b/ovn/utilities/ovn-sbctl.8.in
@@ -278,8 +278,9 @@ parameter may be the UUID for a record, and many tables offer
 additional ways to identify records.  Some commands also take
 \fIcolumn\fR parameters that identify a particular field within the
 records in a table.
-.\" It would be kind to list all the tables and their supported identifiers
-.\" here.
+.PP
+For a list of tables and their columns, see \fBovn\-sb\fR(5) or
+see the table listing from the \fB--help\fR option.
 .PP
 Record names must be specified in full and with correct
 capitalization, except that UUIDs may be abbreviated to their first 4
diff --git a/ovn/utilities/ovn-sbctl.c b/ovn/utilities/ovn-sbctl.c
index 5764ee336..0d1d36235 100644
--- a/ovn/utilities/ovn-sbctl.c
+++ b/ovn/utilities/ovn-sbctl.c
@@ -288,6 +288,14 @@ parse_options(int argc, char *argv[], struct shash *local_options)
     free(options);
 }
 
+static const char *db_table_list(void)
+{
+    static struct ds tables = DS_EMPTY_INITIALIZER;
+
+    return ctl_list_db_tables_usage(&tables, sbrec_table_classes,
+                                    SBREC_N_TABLES);
+}
+
 static void
 usage(void)
 {
@@ -326,6 +334,7 @@ SSL commands:\n\
 set the SSL configuration\n\
 \n\
 %s\
+%s\
 \n\
 Options:\n\
   --db=DATABASE               connect to DATABASE\n\
@@ -334,6 +343,7 @@ Options:\n\
   --dry-run                   do not commit changes to database\n\
   --oneline                   print exactly one line of output per command\n",
            program_name, program_name, ctl_get_db_cmd_usage(),
+           db_table_list(),
            default_sb_db());
     table_usage();
     vlog_usage();
diff --git a/utilities/ovs-vsctl.8.in b/utilities/ovs-vsctl.8.in
index 34f41e4e8..b18782c31 100644
--- a/utilities/ovs-vsctl.8.in
+++ b/utilities/ovs-vsctl.8.in
@@ -530,55 +530,8 @@ additional ways to identify records.  Some commands also take
 \fIcolumn\fR parameters that identify a particular field within the
 records in a table.
 .PP
-The following tables are currently defined:
-.IP "\fBOpen_vSwitch\fR"
-Global configuration for an \fBovs\-vswitchd\fR.  This table contains
-exactly one record, identified by specifying \fB.\fR as the record
-name.
-.IP "\fBBridge\fR"
-Configuration for a bridge within an Open vSwitch.  Records may be
-identified by bridge name.
-.IP "\fBPort\fR"
-A bridge port.  Records may be identified by port name.
-.IP "\fBInterface\fR"
-A network device attached to a port.  Records may be identified by
-name.
-.IP "\fBFlow_Table\fR"
-Configuration for a particular OpenFlow flow table.  Records may be
-identified by name.
-.IP "\fBQoS\fR"
-Quality-of-service configuration for a \fBPort\fR.  Records may be
-identified by port name.
-.IP "\fBQueue\fR"
-Configuration for one queue within a \fBQoS\fR configuration.  Records
-may only be identified by UUID.
-.IP "\fBMirror\fR"
-A port mirroring configuration attached to a bridge.  Records may be
-identified by mirror name.
-.IP "\fBController\fR"
-Configuration for an OpenFlow controller.  A controller attached to a
-particular bridge may be identified by the bridge's name.
-.IP "\fBManager\fR"
-Configuration for an OVSDB connection.  Records may be identified
-by target (e.g. \fBtcp:1.2.3.4\fR).
-.IP "\fBNetFlow\fR"
-A NetFlow configuration attached to a bridge.  Records may be
-identified by bridge name.
-.IP "\fBSSL\fR"
-The global SSL configuration for \fBovs\-vswitchd\fR.  The record
-attached to the \fBOpen_vSwitch\fR table may be identified by
-specifying \fB.\fR as the record name.
-.IP "\fBsFlow\fR"
-An sFlow exporter configuration attached to a bridge.  Records may be
-identified by bridge name.
-.IP "\fBIPFIX\fR"
-An IPFIX exporter configuration attached to a bridge.  Records may be
-identified by bridge name.
-.IP "\fBFlow_Sample_Collector_Set\fR"
-An IPFIX exporter configuration attached to a bridge for sampling
-packets on a per-flow basis using OpenFlow \fBsample\fR actions.
-.IP "\fBAutoAttach\fR"
-Configuration for Auto Attach within a bridge.
+For a list of tables and their columns, see \fBovs-vswitchd.conf.db\fR(5) or
+see the table listing from the \fB--help\fR option.
 .PP
 Record names must be specified in full and with correct
 capitalization, except that UUIDs may be abbreviated to their first 4
diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index e22baeb28..38c202365 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -353,6 +353,14 @@ parse_options(int argc, char *argv[], struct shash *local_options)
     free(options);
 }
 
+static const char *db_table_list(void)
+{
+    static struct ds tables = DS_EMPTY_INITIALIZER;
+
+    return ctl_list_db_tables_usage(&tables, ovsrec_table_classes,
+                                    OVSREC_N_TABLES);
+}
+
 static void
 usage(void)
 {
@@ -416,6 +424,7 @@ Switch commands:\n\
   emer-reset                  reset switch to known good state\n\
 \n\
 %s\
+%s\
 \n\
 Options:\n\
   --db=DATABASE               connect to DATABASE\n\
@@ -425,7 +434,8 @@ Options:\n\
   -t, --timeout=SECS          wait at most SECS seconds for ovs-vswitchd\n\
   --dry-run                   do not commit changes to database\n\
   --oneline                   print exactly one line of output per command\n",
-           program_name, program_name, ctl_get_db_cmd_usage(), ctl_default_db());
+           program_name, program_name, ctl_get_db_cmd_usage(), db_table_list(),
+           ctl_default_db());
     table_usage();
     vlog_usage();
     printf("\
