diff --git a/datafusion/core/src/catalog/information_schema.rs b/datafusion/core/src/catalog/information_schema.rs
index fd8e250feab3b..0467dffa70252 100644
--- a/datafusion/core/src/catalog/information_schema.rs
+++ b/datafusion/core/src/catalog/information_schema.rs
@@ -41,6 +41,7 @@ use super::{
 
 const INFORMATION_SCHEMA: &str = "information_schema";
 const TABLES: &str = "tables";
+const VIEWS: &str = "views";
 const COLUMNS: &str = "columns";
 
 /// Wraps another [`CatalogProvider`] and adds a "information_schema"
@@ -124,28 +125,21 @@ impl InformationSchemaProvider {
                         builder.add_table(
                             &catalog_name,
                             &schema_name,
-                            table_name,
+                            &table_name,
                             table.table_type(),
-                            table.get_table_definition(),
                         );
                     }
                 }
             }
 
             // Add a final list for the information schema tables themselves
-            builder.add_table(
-                &catalog_name,
-                INFORMATION_SCHEMA,
-                TABLES,
-                TableType::View,
-                None::<&str>,
-            );
+            builder.add_table(&catalog_name, INFORMATION_SCHEMA, TABLES, TableType::View);
+            builder.add_table(&catalog_name, INFORMATION_SCHEMA, VIEWS, TableType::View);
             builder.add_table(
                 &catalog_name,
                 INFORMATION_SCHEMA,
                 COLUMNS,
                 TableType::View,
-                None::<&str>,
             );
         }
 
@@ -154,6 +148,32 @@ impl InformationSchemaProvider {
         Arc::new(mem_table)
     }
 
+    fn make_views(&self) -> Arc<dyn TableProvider> {
+        let mut builder = InformationSchemaViewBuilder::new();
+
+        for catalog_name in self.catalog_list.catalog_names() {
+            let catalog = self.catalog_list.catalog(&catalog_name).unwrap();
+
+            for schema_name in catalog.schema_names() {
+                if schema_name != INFORMATION_SCHEMA {
+                    let schema = catalog.schema(&schema_name).unwrap();
+                    for table_name in schema.table_names() {
+                        let table = schema.table(&table_name).unwrap();
+                        builder.add_view(
+                            &catalog_name,
+                            &schema_name,
+                            &table_name,
+                            table.get_table_definition(),
+                        )
+                    }
+                }
+            }
+        }
+
+        let mem_table: MemTable = builder.into();
+        Arc::new(mem_table)
+    }
+
     /// Construct the `information_schema.columns` virtual table
     fn make_columns(&self) -> Arc<dyn TableProvider> {
         let mut builder = InformationSchemaColumnsBuilder::new();
@@ -194,7 +214,7 @@ impl SchemaProvider for InformationSchemaProvider {
     }
 
     fn table_names(&self) -> Vec<String> {
-        vec![TABLES.to_string(), COLUMNS.to_string()]
+        vec![TABLES.to_string(), VIEWS.to_string(), COLUMNS.to_string()]
     }
 
     fn table(&self, name: &str) -> Option<Arc<dyn TableProvider>> {
@@ -202,13 +222,15 @@ impl SchemaProvider for InformationSchemaProvider {
             Some(self.make_tables())
         } else if name.eq_ignore_ascii_case("columns") {
             Some(self.make_columns())
+        } else if name.eq_ignore_ascii_case("views") {
+            Some(self.make_views())
         } else {
             None
         }
     }
 
     fn table_exist(&self, name: &str) -> bool {
-        return matches!(name.to_ascii_lowercase().as_str(), TABLES | COLUMNS);
+        return matches!(name.to_ascii_lowercase().as_str(), TABLES | VIEWS | COLUMNS);
     }
 }
 
@@ -220,7 +242,6 @@ struct InformationSchemaTablesBuilder {
     schema_names: StringBuilder,
     table_names: StringBuilder,
     table_types: StringBuilder,
-    definitions: StringBuilder,
 }
 
 impl InformationSchemaTablesBuilder {
@@ -234,7 +255,6 @@ impl InformationSchemaTablesBuilder {
             schema_names: StringBuilder::new(default_capacity),
             table_names: StringBuilder::new(default_capacity),
             table_types: StringBuilder::new(default_capacity),
-            definitions: StringBuilder::new(default_capacity),
         }
     }
 
@@ -244,7 +264,6 @@ impl InformationSchemaTablesBuilder {
         schema_name: impl AsRef<str>,
         table_name: impl AsRef<str>,
         table_type: TableType,
-        definition: Option<impl AsRef<str>>,
     ) {
         // Note: append_value is actually infallable.
         self.catalog_names
@@ -261,7 +280,6 @@ impl InformationSchemaTablesBuilder {
                 TableType::Temporary => "LOCAL TEMPORARY",
             })
             .unwrap();
-        self.definitions.append_option(definition.as_ref()).unwrap();
     }
 }
 
@@ -272,7 +290,6 @@ impl From<InformationSchemaTablesBuilder> for MemTable {
             Field::new("table_schema", DataType::Utf8, false),
             Field::new("table_name", DataType::Utf8, false),
             Field::new("table_type", DataType::Utf8, false),
-            Field::new("definition", DataType::Utf8, true),
         ]);
 
         let InformationSchemaTablesBuilder {
@@ -280,7 +297,6 @@ impl From<InformationSchemaTablesBuilder> for MemTable {
             mut schema_names,
             mut table_names,
             mut table_types,
-            mut definitions,
         } = value;
 
         let schema = Arc::new(schema);
@@ -291,6 +307,80 @@ impl From<InformationSchemaTablesBuilder> for MemTable {
                 Arc::new(schema_names.finish()),
                 Arc::new(table_names.finish()),
                 Arc::new(table_types.finish()),
+            ],
+        )
+        .unwrap();
+
+        MemTable::try_new(schema, vec![vec![batch]]).unwrap()
+    }
+}
+
+/// Builds the `information_schema.VIEWS` table row by row
+///
+/// Columns are based on <https://www.postgresql.org/docs/current/infoschema-columns.html>
+struct InformationSchemaViewBuilder {
+    catalog_names: StringBuilder,
+    schema_names: StringBuilder,
+    table_names: StringBuilder,
+    definitions: StringBuilder,
+}
+
+impl InformationSchemaViewBuilder {
+    fn new() -> Self {
+        // StringBuilder requires providing an initial capacity, so
+        // pick 10 here arbitrarily as this is not performance
+        // critical code and the number of tables is unavailable here.
+        let default_capacity = 10;
+        Self {
+            catalog_names: StringBuilder::new(default_capacity),
+            schema_names: StringBuilder::new(default_capacity),
+            table_names: StringBuilder::new(default_capacity),
+            definitions: StringBuilder::new(default_capacity),
+        }
+    }
+
+    fn add_view(
+        &mut self,
+        catalog_name: impl AsRef<str>,
+        schema_name: impl AsRef<str>,
+        table_name: impl AsRef<str>,
+        definition: Option<impl AsRef<str>>,
+    ) {
+        // Note: append_value is actually infallable.
+        self.catalog_names
+            .append_value(catalog_name.as_ref())
+            .unwrap();
+        self.schema_names
+            .append_value(schema_name.as_ref())
+            .unwrap();
+        self.table_names.append_value(table_name.as_ref()).unwrap();
+        self.definitions.append_option(definition.as_ref()).unwrap();
+    }
+}
+
+impl From<InformationSchemaViewBuilder> for MemTable {
+    fn from(value: InformationSchemaViewBuilder) -> Self {
+        let schema = Schema::new(vec![
+            Field::new("table_catalog", DataType::Utf8, false),
+            Field::new("table_schema", DataType::Utf8, false),
+            Field::new("table_name", DataType::Utf8, false),
+            Field::new("definition", DataType::Utf8, true),
+        ]);
+
+        let InformationSchemaViewBuilder {
+            mut catalog_names,
+            mut schema_names,
+            mut table_names,
+            mut definitions,
+        } = value;
+
+        let schema = Arc::new(schema);
+        let batch = RecordBatch::try_new(
+            schema.clone(),
+            vec![
+                Arc::new(catalog_names.finish()),
+                Arc::new(schema_names.finish()),
+                Arc::new(table_names.finish()),
                 Arc::new(definitions.finish()),
             ],
         )
diff --git a/datafusion/core/tests/sql/information_schema.rs b/datafusion/core/tests/sql/information_schema.rs
index f528c3c3c56de..5a4aa297f8085 100644
--- a/datafusion/core/tests/sql/information_schema.rs
+++ b/datafusion/core/tests/sql/information_schema.rs
@@ -52,12 +52,13 @@ async fn information_schema_tables_no_tables() {
         .unwrap();
 
     let expected = vec![
-        "+---------------+--------------------+------------+------------+------------+",
-        "| table_catalog | table_schema       | table_name | table_type | definition |",
-        "+---------------+--------------------+------------+------------+------------+",
-        "| datafusion    | information_schema | columns    | VIEW       |            |",
-        "| datafusion    | information_schema | tables     | VIEW       |            |",
-        "+---------------+--------------------+------------+------------+------------+",
+        "+---------------+--------------------+------------+------------+",
+        "| table_catalog | table_schema       | table_name | table_type |",
+        "+---------------+--------------------+------------+------------+",
+        "| datafusion    | information_schema | columns    | VIEW       |",
+        "| datafusion    | information_schema | tables     | VIEW       |",
+        "| datafusion    | information_schema | views      | VIEW       |",
+        "+---------------+--------------------+------------+------------+",
     ];
     assert_batches_sorted_eq!(expected, &result);
 }
@@ -76,13 +77,14 @@ async fn information_schema_tables_tables_default_catalog() {
         .unwrap();
 
     let expected = vec![
-        "+---------------+--------------------+------------+------------+------------+",
-        "| table_catalog | table_schema       | table_name | table_type | definition |",
-        "+---------------+--------------------+------------+------------+------------+",
-        "| datafusion    | information_schema | columns    | VIEW       |            |",
-        "| datafusion    | information_schema | tables     | VIEW       |            |",
-        "| datafusion    | public             | t          | BASE TABLE |            |",
-        "+---------------+--------------------+------------+------------+------------+",
+        "+---------------+--------------------+------------+------------+",
+        "| table_catalog | table_schema       | table_name | table_type |",
+        "+---------------+--------------------+------------+------------+",
+        "| datafusion    | information_schema | columns    | VIEW       |",
+        "| datafusion    | information_schema | tables     | VIEW       |",
+        "| datafusion    | information_schema | views      | VIEW       |",
+        "| datafusion    | public             | t          | BASE TABLE |",
+        "+---------------+--------------------+------------+------------+",
     ];
     assert_batches_sorted_eq!(expected, &result);
 
@@ -95,14 +97,15 @@ async fn information_schema_tables_tables_default_catalog() {
         .unwrap();
 
     let expected = vec![
-        "+---------------+--------------------+------------+------------+------------+",
-        "| table_catalog | table_schema       | table_name | table_type | definition |",
-        "+---------------+--------------------+------------+------------+------------+",
-        "| datafusion    | information_schema | columns    | VIEW       |            |",
-        "| datafusion    | information_schema | tables     | VIEW       |            |",
-        "| datafusion    | public             | t          | BASE TABLE |            |",
-        "| datafusion    | public             | t2         | BASE TABLE |            |",
-        "+---------------+--------------------+------------+------------+------------+",
+        "+---------------+--------------------+------------+------------+",
+        "| table_catalog | table_schema       | table_name | table_type |",
+        "+---------------+--------------------+------------+------------+",
+        "| datafusion    | information_schema | columns    | VIEW       |",
+        "| datafusion    | information_schema | tables     | VIEW       |",
+        "| datafusion    | information_schema | views      | VIEW       |",
+        "| datafusion    | public             | t          | BASE TABLE |",
+        "| datafusion    | public             | t2         | BASE TABLE |",
+        "+---------------+--------------------+------------+------------+",
     ];
     assert_batches_sorted_eq!(expected, &result);
 }
@@ -139,19 +142,22 @@ async fn information_schema_tables_tables_with_multiple_catalogs() {
         .unwrap();
 
     let expected = vec![
-        "+------------------+--------------------+------------+------------+------------+",
-        "| table_catalog    | table_schema       | table_name | table_type | definition |",
-        "+------------------+--------------------+------------+------------+------------+",
-        "| datafusion       | information_schema | columns    | VIEW       |            |",
-        "| datafusion       | information_schema | tables     | VIEW       |            |",
-        "| my_catalog       | information_schema | columns    | VIEW       |            |",
-        "| my_catalog       | information_schema | tables     | VIEW       |            |",
-        "| my_catalog       | my_schema          | t1         | BASE TABLE |            |",
-        "| my_catalog       | my_schema          | t2         | BASE TABLE |            |",
-        "| my_other_catalog | information_schema | columns    | VIEW       |            |",
-        "| my_other_catalog | information_schema | tables     | VIEW       |            |",
-        "| my_other_catalog | my_other_schema    | t3         | BASE TABLE |            |",
-        "+------------------+--------------------+------------+------------+------------+",
+        "+------------------+--------------------+------------+------------+",
+        "| table_catalog    | table_schema       | table_name | table_type |",
+        "+------------------+--------------------+------------+------------+",
+        "| datafusion       | information_schema | columns    | VIEW       |",
+        "| datafusion       | information_schema | tables     | VIEW       |",
+        "| datafusion       | information_schema | views      | VIEW       |",
+        "| my_catalog       | information_schema | columns    | VIEW       |",
+        "| my_catalog       | information_schema | tables     | VIEW       |",
+        "| my_catalog       | information_schema | views      | VIEW       |",
+        "| my_catalog       | my_schema          | t1         | BASE TABLE |",
+        "| my_catalog       | my_schema          | t2         | BASE TABLE |",
+        "| my_other_catalog | information_schema | columns    | VIEW       |",
+        "| my_other_catalog | information_schema | tables     | VIEW       |",
+        "| my_other_catalog | information_schema | views      | VIEW       |",
+        "| my_other_catalog | my_other_schema    | t3         | BASE TABLE |",
+        "+------------------+--------------------+------------+------------+",
     ];
     assert_batches_sorted_eq!(expected, &result);
 }
@@ -200,15 +206,16 @@ async fn information_schema_tables_table_types() {
         .unwrap();
 
     let expected = vec![
-        "+---------------+--------------------+------------+-----------------+------------+",
-        "| table_catalog | table_schema       | table_name | table_type      | definition |",
-        "+---------------+--------------------+------------+-----------------+------------+",
-        "| datafusion    | information_schema | columns    | VIEW            |            |",
-        "| datafusion    | information_schema | tables     | VIEW            |            |",
-        "| datafusion    | public             | physical   | BASE TABLE      |            |",
-        "| datafusion    | public             | query      | VIEW            |            |",
-        "| datafusion    | public             | temp       | LOCAL TEMPORARY |            |",
-        "+---------------+--------------------+------------+-----------------+------------+",
+        "+---------------+--------------------+------------+-----------------+",
+        "| table_catalog | table_schema       | table_name | table_type      |",
+        "+---------------+--------------------+------------+-----------------+",
+        "| datafusion    | information_schema | columns    | VIEW            |",
+        "| datafusion    | information_schema | tables     | VIEW            |",
+        "| datafusion    | information_schema | views      | VIEW            |",
+        "| datafusion    | public             | physical   | BASE TABLE      |",
+        "| datafusion    | public             | query      | VIEW            |",
+        "| datafusion    | public             | temp       | LOCAL TEMPORARY |",
+        "+---------------+--------------------+------------+-----------------+",
     ];
     assert_batches_sorted_eq!(expected, &result);
 }
@@ -273,13 +280,14 @@ async fn information_schema_show_tables() {
     let result = plan_and_collect(&ctx, "SHOW TABLES").await.unwrap();
 
     let expected = vec![
-        "+---------------+--------------------+------------+------------+------------+",
-        "| table_catalog | table_schema       | table_name | table_type | definition |",
-        "+---------------+--------------------+------------+------------+------------+",
-        "| datafusion    | information_schema | columns    | VIEW       |            |",
-        "| datafusion    | information_schema | tables     | VIEW       |            |",
-        "| datafusion    | public             | t          | BASE TABLE |            |",
-        "+---------------+--------------------+------------+------------+------------+",
+        "+---------------+--------------------+------------+------------+",
+        "| table_catalog | table_schema       | table_name | table_type |",
+        "+---------------+--------------------+------------+------------+",
+        "| datafusion    | information_schema | columns    | VIEW       |",
+        "| datafusion    | information_schema | tables     | VIEW       |",
+        "| datafusion    | information_schema | views      | VIEW       |",
+        "| datafusion    | public             | t          | BASE TABLE |",
+        "+---------------+--------------------+------------+------------+",
     ];
     assert_batches_sorted_eq!(expected, &result);
 
@@ -542,11 +550,11 @@ async fn show_create_view() {
     assert_eq!(results[0].num_rows(), 1);
 
     let expected = vec![
-        "+------+--------------------------------------+",
-        "| name | definition                           |",
-        "+------+--------------------------------------+",
-        "| xyz  | CREATE VIEW xyz AS SELECT * FROM abc |",
-        "+------+--------------------------------------+",
+        "+---------------+--------------+------------+--------------------------------------+",
+        "| table_catalog | table_schema | table_name | definition                           |",
+        "+---------------+--------------+------------+--------------------------------------+",
+        "| datafusion    | public       | xyz        | CREATE VIEW xyz AS SELECT * FROM abc |",
+        "+---------------+--------------+------------+--------------------------------------+",
     ];
     assert_batches_eq!(expected, &results);
 }
@@ -567,11 +575,11 @@ async fn show_create_view_in_catalog() {
     assert_eq!(results[0].num_rows(), 1);
 
     let expected = vec![
-        "+----------+-------------------------------------------+",
-        "| name     | definition                                |",
-        "+----------+-------------------------------------------+",
-        "| test.xyz | CREATE VIEW test.xyz AS SELECT * FROM abc |",
-        "+----------+-------------------------------------------+",
+        "+---------------+--------------+------------+-------------------------------------------+",
+        "| table_catalog | table_schema | table_name | definition                                |",
+        "+---------------+--------------+------------+-------------------------------------------+",
+        "| datafusion    | test         | xyz        | CREATE VIEW test.xyz AS SELECT * FROM abc |",
+        "+---------------+--------------+------------+-------------------------------------------+",
     ];
     assert_batches_eq!(expected, &results);
 }
@@ -587,11 +595,11 @@ async fn show_create_table() {
     let results = plan_and_collect(&ctx, result_sql).await.unwrap();
 
     let expected = vec![
-        "+------+------------+",
-        "| name | definition |",
-        "+------+------------+",
-        "| abc  |            |",
-        "+------+------------+",
+        "+---------------+--------------+------------+------------+",
+        "| table_catalog | table_schema | table_name | definition |",
+        "+---------------+--------------+------------+------------+",
+        "| datafusion    | public       | abc        |            |",
+        "+---------------+--------------+------------+------------+",
     ];
 
     assert_batches_eq!(expected, &results);
diff --git a/datafusion/sql/src/planner.rs b/datafusion/sql/src/planner.rs
index edabbf8f2b112..6a5f7135f0cbf 100644
--- a/datafusion/sql/src/planner.rs
+++ b/datafusion/sql/src/planner.rs
@@ -2455,8 +2455,8 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
             .join(" AND ");
 
         let query = format!(
-            "SELECT '{}' as name, definition FROM information_schema.tables WHERE {}",
-            table_name, where_clause
+            "SELECT table_catalog, table_schema, table_name, definition FROM information_schema.views WHERE {}",
+            where_clause
         );
 
         let mut rewrite = DFParser::parse_sql(&query)?;
