在 Unity Catalog 中创建表

本文介绍 Unity Catalog 中的托管表和外部表的概念,并介绍如何在 Unity Catalog 中创建表。

注意

创建表时,请务必引用由 Unity Catalog 管理的目录,或将默认目录设置为由 Unity Catalog 管理的目录。 请参阅管理默认目录

目录 hive_metastore 显示在目录资源管理器中,但不被视为由 Unity Catalog 管理。 它由 Azure Databricks 工作区的 Hive 元存储管理。 列出的所有其他目录都由 Unity Catalog 管理。

可以使用 Unity Catalog 表升级界面将 Hive 元存储中注册的现有表升级到 Unity Catalog。 请参阅将 Hive 表和视图升级到 Unity Catalog

托管表

托管表是在 Unity Catalog 中创建表的默认方式。 Unity Catalog 管理这些表的生命周期和文件布局。 不应使用 Azure Databricks 以外的工具直接操作这些表中的文件。

托管表存储在元存储、目录或架构级别的托管存储中,具体取决于架构和目录的配置方式。 请参阅在 Unity Catalog 中指定托管存储位置

托管表始终使用 Delta 表格式。

删除托管表时,将于 30 天内从云租户中删除其基础数据。

外部表

外部表是其数据存储在为元存储、目录或架构指定的托管存储位置外部的表。 仅当需要直接访问 Azure Databricks 群集或 Databricks SQL 仓库外部的数据时,才使用外部表。

在外部表上运行 DROP TABLE 时,Unity Catalog 不会删除基础数据。 若要删除某个表,你必须是其所有者。 你可以管理外部表的权限,并以与托管表相同的方式在查询中使用它们。 要使用 SQL 创建外部表,请在 CREATE TABLE 语句中指定 LOCATION 路径。 外部表可以使用以下文件格式:

  • DELTA
  • CSV
  • JSON
  • AVRO
  • PARQUET
  • ORC
  • TEXT

要管理对外部表的底层云存储的访问,必须设置存储凭据和外部位置

若要了解详细信息,请参阅创建外部表

要求

必须对要在其中创建表的架构拥有 CREATE TABLE 特权,以及对架构拥有 USE SCHEMA 特权,并对父目录拥有 USE CATALOG 特权。

如果要创建外部表,请参阅创建外部表了解其他要求。

创建托管表

若要创建托管表,请运行以下 SQL 命令。 括号中的项是可选的。 替换占位符值替:

  • <catalog-name>:将包含表的目录的名称。

    这不能是为与你的 Azure Databricks 工作区关联的 Hive 元存储自动创建的 hive_metastore 目录。 如果要在工作区默认目录中创建表,则可以删除目录名称。

  • <schema-name>:将包含表的架构的名称。

  • <table-name>:表的名称。

  • <column-specification>:每列的名称和数据类型。

SQL

CREATE TABLE <catalog-name>.<schema-name>.<table-name>
(
  <column-specification>
);

Python

spark.sql("CREATE TABLE <catalog-name>.<schema-name>.<table-name> "
  "("
  "  <column-specification>"
  ")")

R

library(SparkR)

sql(paste("CREATE TABLE <catalog-name>.<schema-name>.<table-name> ",
  "(",
  "  <column-specification>",
  ")",
  sep = ""))

Scala

spark.sql("CREATE TABLE <catalog-name>.<schema-name>.<table-name> " +
  "(" +
  "  <column-specification>" +
  ")")

还可使用 Databricks Terraform 提供程序databricks_table 创建托管表。 可以使用 databricks_tables 检索表全名列表。

例如,要创建表 main.default.department 并在其中插入五行,请执行以下操作:

SQL

CREATE TABLE main.default.department
(
  deptcode  INT,
  deptname  STRING,
  location  STRING
);

INSERT INTO main.default.department VALUES
  (10, 'FINANCE', 'EDINBURGH'),
  (20, 'SOFTWARE', 'PADDINGTON'),
  (30, 'SALES', 'MAIDSTONE'),
  (40, 'MARKETING', 'DARLINGTON'),
  (50, 'ADMIN', 'BIRMINGHAM');

Python

spark.sql("CREATE TABLE main.default.department "
  "("
  "  deptcode  INT,"
  "  deptname  STRING,"
  "  location  STRING"
  ")"
  "INSERT INTO main.default.department VALUES "
  "  (10, 'FINANCE', 'EDINBURGH'),"
  "  (20, 'SOFTWARE', 'PADDINGTON'),"
  "  (30, 'SALES', 'MAIDSTONE'),"
  "  (40, 'MARKETING', 'DARLINGTON'),"
  "  (50, 'ADMIN', 'BIRMINGHAM')")

R

library(SparkR)

sql(paste("CREATE TABLE main.default.department ",
  "(",
  "  deptcode  INT,",
  "  deptname  STRING,",
  "  location  STRING",
  ")",
  "INSERT INTO main.default.department VALUES ",
  "  (10, 'FINANCE', 'EDINBURGH'),",
  "  (20, 'SOFTWARE', 'PADDINGTON'),",
  "  (30, 'SALES', 'MAIDSTONE'),",
  "  (40, 'MARKETING', 'DARLINGTON'),",
  "  (50, 'ADMIN', 'BIRMINGHAM')",
  sep = ""))

Scala

spark.sql("CREATE TABLE main.default.department " +
  "(" +
  "  deptcode  INT," +
  "  deptname  STRING," +
  "  location  STRING" +
  ")" +
  "INSERT INTO main.default.department VALUES " +
  "  (10, 'FINANCE', 'EDINBURGH')," +
  "  (20, 'SOFTWARE', 'PADDINGTON')," +
  "  (30, 'SALES', 'MAIDSTONE')," +
  "  (40, 'MARKETING', 'DARLINGTON')," +
  "  (50, 'ADMIN', 'BIRMINGHAM')")

删除托管表

你必须是表的所有者才能删除表。 若要删除托管表,请运行以下 SQL 命令:

DROP TABLE IF EXISTS catalog_name.schema_name.table_name;

删除托管表时,将于 30 天内从云租户中删除其基础数据。

创建外部表

外部表中的数据存储在云租户上的路径中。 为了使用外部表,Unity Catalog 引入了两个对象来访问和使用外部云存储:

  • 存储凭据包含用于访问云存储位置的身份验证方法。 存储凭据不包含到其授予访问权限的路径的映射。 存储凭据受访问控制,以确定哪些用户可以使用该凭据。
  • 外部位置将存储凭据与它授予访问权限的云存储路径映射在一起。 外部位置仅授予对该云存储路径及其内容的访问权限。 外部位置受访问控制,以确定哪些用户可以使用这些外部位置。 当 SQL 命令包含 LOCATION 子句时,将自动使用外部位置。

要求

要创建外部表,你必须具有:

  • 对外部位置的 CREATE EXTERNAL TABLE 权限,授予对外部表所访问的 LOCATION 的访问权限。
  • 对表的父架构的 USE SCHEMA 权限。
  • 对表的父目录的 USE CATALOG 权限。
  • 对表的父架构的 CREATE TABLE 权限。

外部位置和存储凭据存储在元存储级别,而不是存储在目录中。 若要创建存储凭据,你必须是帐户管理员或拥有 CREATE STORAGE CREDENTIAL 权限。 若要创建外部位置,必须是元存储管理员或具有 CREATE EXTERNAL LOCATION 权限。 请参阅使用 Unity Catalog 连接到云对象存储

创建表

在笔记本或 SQL 查询编辑器中使用以下命令示例之一来创建外部表。

还可以使用示例笔记本创建存储凭据、外部位置和外部表,并为其管理权限。

在以下示例中,替换占位符值:

  • <catalog>:将包含表的目录的名称。

    这不能是为与你的 Azure Databricks 工作区关联的 Hive 元存储自动创建的 hive_metastore 目录。 如果要在工作区默认目录中创建表,则可以删除目录名称。

  • <schema>:将包含该表的架构的名称。

  • <table-name>:表的名称。

  • <column-specification>:每列的名称和数据类型。

  • <bucket-path>:要在其中创建表的云存储存储桶的路径。

  • <table-directory>:将在其中创建表的目录。 为每个表使用唯一目录。

重要

在路径中创建表后,用户将无法再直接从 Azure Databricks 访问该路径中的文件,即使他们已被授予对外部位置或存储凭据的权限。 这是为了确保用户无法通过直接从你的云租户读取文件来规避应用于表的访问控制。

SQL

CREATE TABLE <catalog>.<schema>.<table-name>
(
  <column-specification>
)
LOCATION 'abfss://<bucket-path>/<table-directory>';

Python

spark.sql("CREATE TABLE <catalog>.<schema>.<table-name> "
  "("
  "  <column-specification>"
  ") "
  "LOCATION 'abfss://<bucket-path>/<table-directory>'")

R

library(SparkR)

sql(paste("CREATE TABLE <catalog>.<schema>.<table-name> ",
  "(",
  "  <column-specification>",
  ") ",
  "LOCATION 'abfss://<bucket-path>/<table-directory>'",
  sep = ""))

Scala

spark.sql("CREATE TABLE <catalog>.<schema>.<table-name> " +
  "(" +
  "  <column-specification>" +
  ") " +
  "LOCATION 'abfss://<bucket-path>/<table-directory>'")

Unity Catalog 会检查你是否具有以下权限:

  • 引用你指定的云存储路径的外部位置上的 CREATE EXTERNAL TABLE
  • 父架构上的 CREATE TABLE
  • 父架构上的 USE SCHEMA
  • 父目录上的 USE CATALOG

如果这样做,则会创建外部表。 否则,将发生错误,并且不会创建外部表。

注意

你可以改为将 Hive 元存储中的现有外部表迁移到 Unity Catalog,而无需复制其数据。 请参阅使用升级向导将单个 Hive 表升级为 Unity Catalog 外部表

还可使用 Databricks Terraform 提供程序databricks_table 创建外部表。 可以使用 databricks_tables 检索表全名列表。

示例笔记本:创建外部表

可以使用以下示例笔记本创建目录、架构和外部表,并管理对它们的权限。

在 Unity Catalog 笔记本中创建和管理外部表

获取笔记本

从存储在云租户中的文件创建表

可以使用存储在云租户中的文件中的记录填充托管表或外部表。 Unity Catalog 读取该位置的文件,并将其内容插入到表中。 在 Unity 目录中,这称为基于路径的访问

可以按照本部分中的示例操作,也可以使用添加数据 UI

浏览文件的内容

若要在从外部位置存储的数据创建表之前浏览这些数据,可以使用目录资源管理器或以下命令。

所需的权限:必须对与云存储路径关联的外部位置拥有 READ FILES 权限,以返回该位置中的数据文件列表。

SQL

  1. 列出云存储路径中的文件:

    LIST 'abfss://<path-to-files>';
    
  2. 查询给定路径中文件中的数据:

    SELECT * FROM <format>.`abfss://<path-to-files>`;
    

Python

  1. 列出云存储路径中的文件:

    display(spark.sql("LIST 'abfss://<path-to-files>'"))
    
  2. 查询给定路径中文件中的数据:

    display(spark.read.load("abfss://<path-to-files>"))
    

R

  1. 列出云存储路径中的文件:

    library(SparkR)
    
    display(sql("LIST 'abfss://<path-to-files>'"))
    
  2. 查询给定路径中文件中的数据:

    library(SparkR)
    
    display(loadDF("abfss://<path-to-files>"))
    

Scala

  1. 列出云存储路径中的文件:

    display(spark.sql("LIST 'abfss://<path-to-files>'"))
    
  2. 查询给定路径中文件中的数据:

    display(spark.read.load("abfss://<path-to-files>"))
    

从文件创建一个表

按照本部分中的示例创建一个新表,并在其中填充云租户上的数据文件。

注意

你可以改为将 Hive 元存储中的现有外部表迁移到 Unity Catalog,而无需复制其数据。 请参阅使用升级向导将单个 Hive 表升级为 Unity Catalog 外部表

重要

  • 使用此方法创建表时,存储路径只读取一次,以防止记录重复。 如果要重新读取目录的内容,则必须删除并重新创建表。 对于现有表,可以从存储路径插入记录
  • 你创建表的存储桶路径也不能用于读取或写入数据文件。
  • 只读取确切目录中的文件;读取不是递归的。
  • 你必须具有以下权限:
    • 对父目录的 USE CATALOG 权限,以及对架构的 USE SCHEMA 权限。
    • 父架构上的 CREATE TABLE
    • READ FILES,在与文件所在的存储桶路径关联的外部位置中,或者直接在存储凭据中(如果你未使用外部位置)。
    • 如果你要创建外部表,则需要将创建该表的存储桶路径上的 CREATE EXTERNAL TABLE

若要创建新的托管表并使用云存储空间中的数据填充该表,请使用以下示例。

SQL

CREATE TABLE <catalog>.<schema>.<table-name>
(
  <column-specification>
)
SELECT * from <format>.`abfss://<path-to-files>`;

Python

spark.sql("CREATE TABLE <catalog>.<schema>.<table-name> "
  "( "
  "  <column-specification> "
  ") "
  "SELECT * from <format>.`abfss://<path-to-files>`")

R

library(SparkR)

sql(paste("CREATE TABLE <catalog>.<schema>.<table-name> ",
  "( ",
  "  <column-specification> ",
  ") ",
  "SELECT * from <format>.`abfss://<path-to-files>`",
  sep = ""))

Scala

spark.sql("CREATE TABLE <catalog>.<schema>.<table-name> " +
  "( " +
  "  <column-specification> " +
  ") " +
  "SELECT * from <format>.`abfss://<path-to-files>`")

若要创建外部表并使用云存储空间中的数据填充该表,请添加 LOCATION 子句:

SQL

CREATE TABLE <catalog>.<schema>.<table-name>
(
    <column-specification>
)
USING <format>
LOCATION 'abfss://<table-location>'
SELECT * from <format>.`abfss://<path-to-files>`;

Python

spark.sql("CREATE TABLE <catalog>.<schema>.<table-name> "
  "( "
  "  <column-specification> "
  ") "
  "USING <format> "
  "LOCATION 'abfss://<table-location>' "
  "SELECT * from <format>.`abfss://<path-to-files>`")

R

library(SparkR)

sql(paste("CREATE TABLE <catalog>.<schema>.<table-name> ",
  "( ",
  "  <column-specification> ",
  ") ",
  "USING <format> ",
  "LOCATION 'abfss://<table-location>' ",
  "SELECT * from <format>.`abfss://<path-to-files>`",
  sep = ""))

Scala

spark.sql("CREATE TABLE <catalog>.<schema>.<table-name> " +
  "( " +
  "  <column-specification> " +
  ") " +
  "USING <format> " +
  "LOCATION 'abfss://<table-location>' " +
  "SELECT * from <format>.`abfss://<path-to-files>`")

将路径中的记录插入到现有表中

要将存储桶路径中的记录插入到现有表中,请使用 COPY INTO 命令。 在以下示例中,替换占位符值:

  • <catalog>:表的父目录的名称。
  • <schema>:表的父架构的名称。
  • <path-to-files>:包含数据文件的存储桶路径。
  • <format>:文件格式,例如 delta
  • <table-location>:将在其中创建表的存储桶路径。

重要

  • 使用此方法将记录插入到表中时,你提供的存储桶路径只读取一次,以防止记录重复。
  • 你创建表的存储桶路径也不能用于读取或写入数据文件。
  • 只读取确切目录中的文件;读取不是递归的。
  • 你必须具有以下权限:
    • 对父目录的 USE CATALOG 权限,以及对架构的 USE SCHEMA 权限。
    • 对表具有 MODIFY 权限。
    • READ FILES,在与文件所在的存储桶路径关联的外部位置中,或者直接在存储凭据中(如果你未使用外部位置)。
    • 要将记录插入到外部表中,你需要表所在的存储桶路径上的 CREATE EXTERNAL TABLE

要将存储桶路径中文件中的记录插入到托管表中,请使用外部位置从存储桶路径读取:

SQL

COPY INTO <catalog>.<schema>.<table>
FROM (
  SELECT *
  FROM 'abfss://<path-to-files>'
)
FILEFORMAT = <format>;

Python

spark.sql("COPY INTO <catalog>.<schema>.<table> "
  "FROM ( "
  "  SELECT * "
  "  FROM 'abfss://<path-to-files>' "
  ") "
  "FILEFORMAT = <format>")

R

library(SparkR)

sql(paste("COPY INTO <catalog>.<schema>.<table> ",
  "FROM ( ",
  "  SELECT * ",
  "  FROM 'abfss://<path-to-files>' ",
  ") ",
  "FILEFORMAT = <format>",
  sep = ""))

Scala

spark.sql("COPY INTO <catalog>.<schema>.<table> " +
  "FROM ( " +
  "  SELECT * " +
  "  FROM 'abfss://<path-to-files>' " +
  ") " +
  "FILEFORMAT = <format>")

要插入到外部表中,请添加一个 LOCATION 子句:

SQL

COPY INTO <catalog>.<schema>.<table>
LOCATION 'abfss://<table-location>'
FROM (
  SELECT *
  FROM 'abfss://<path-to-files>'
)
FILEFORMAT = <format>;

Python

spark.sql("COPY INTO <catalog>.<schema>.<table> "
  "LOCATION 'abfss://<table-location>' "
  "FROM ( "
  "  SELECT * "
  "  FROM 'abfss://<path-to-files>' "
  ") "
  "FILEFORMAT = <format>")

R

library(SparkR)

sql(paste("COPY INTO <catalog>.<schema>.<table> ",
  "LOCATION 'abfss://<table-location>' ",
  "FROM ( ",
  "  SELECT * ",
  "  FROM 'abfss://<path-to-files>' ",
  ") ",
  "FILEFORMAT = <format>",
  sep = ""))

Scala

spark.sql("COPY INTO <catalog>.<schema>.<table> " +
  "LOCATION 'abfss://<table-location>' " +
  "FROM ( " +
  "  SELECT * " +
  "  FROM 'abfss://<path-to-files>' " +
  ") " +
  "FILEFORMAT = <format>")

向表添加注释

作为表所有者或对表具有 MODIFY 权限的用户,你可向表及其列添加注释。 可使用以下功能添加注释:

后续步骤