创建和管理视图

本页介绍了如何创建和管理 Spanner 视图。如需详细了解 Spanner 视图,请参阅视图简介

权限

如需创建、授予和撤消对视图的访问权限,您必须拥有 spanner.database.updateDdl 权限。

创建视图

如需创建视图,请使用 DDL 语句 CREATE VIEW 命名视图,并提供定义该视图的查询。此语句有两种形式:

  • CREATE VIEW 用于定义当前数据库中的新视图。如果名为 view_name 的视图已存在,则 CREATE VIEW 语句将失败。

  • CREATE OR REPLACE VIEW 用于定义当前数据库中的新视图。如果已经存在名为 view_name 的视图,则其定义会被替换。

CREATE VIEW 语句的语法如下:

{CREATE | CREATE OR REPLACE } VIEW  view_name
SQL SECURITY { INVOKER | DEFINER }
AS query

由于视图是虚拟表,因此您指定的 query 必须为该虚拟表中的所有列提供名称。

此外,Spanner 还会检查您使用严格名称解析指定的 query,这意味着查询中使用的所有架构对象名称都必须是限定的,这样才能明确标识单个架构对象。例如,Singers 表的 SingerId 列后面的示例必须限定为 Singers.SingerId

您必须在 CREATE VIEWCREATE OR REPLACE VIEW 语句中将 SQL SECURITY 指定为 INVOKERDEFINER。如需详细了解这两种安全类型之间的区别,请参阅视图简介

例如,假设 Singers 表的定义如下:

GoogleSQL

CREATE TABLE Singers (
  SingerId   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX)
) PRIMARY KEY (SingerId);

PostgreSQL

CREATE TABLE Singers (
  SingerId   BIGINT PRIMARY KEY,
  FirstName  VARCHAR(1024),
  LastName   VARCHAR(1024),
  SingerInfo BYTEA
);

您可以使用调用方的权限定义 SingerNames 视图,如下所示:

CREATE VIEW SingerNames
SQL SECURITY INVOKER
AS SELECT
   Singers.SingerId AS SingerId,
   Singers.FirstName || ' ' || Singers.LastName AS Name
FROM Singers;

在查询中使用 SingerNames 视图时创建的虚拟表包含 SingerIdName 列。

虽然此 SingerNames 视图的定义有效,但没有遵循数据类型转换的最佳做法,该最佳做法旨在确保架构更改的稳定性,如下一部分所述。

创建视图时的最佳做法

要尽量减少更新视图定义的需求,请在定义视图的查询中显式类型转换所有表列的数据类型。执行此操作后,视图的定义在列类型架构更改时可保持有效。

例如,由于在 Singers 表中更改了列的数据类型,以下 SingerNames 视图定义可能会失效。

CREATE VIEW SingerNames
SQL SECURITY INVOKER
AS SELECT
   Singers.SingerId AS SingerId,
   Singers.FirstName || ' ' || Singers.LastName AS Name
FROM Singers;

您可以通过将列明确转换为所需的数据类型来避免视图无效,如下所示:

GoogleSQL

CREATE OR REPLACE VIEW SingerNames
SQL SECURITY INVOKER
AS SELECT
 CAST(Singers.SingerId AS INT64) AS SingerId,
 CAST(Singers.FirstName AS STRING) || " " || CAST(Singers.LastName AS STRING) AS Name
FROM Singers;

PostgreSQL

CREATE OR REPLACE VIEW SingerNames
SQL SECURITY INVOKER
AS SELECT
 CAST(Singers.SingerId AS bigint) AS SingerId,
 CAST(Singers.FirstName AS varchar) || ' ' || CAST(Singers.LastName AS varchar) AS Name
FROM Singers;

授予和撤消对视图的访问权限

作为精细访问权限控制用户,您必须对视图拥有 SELECT 权限。如需向数据库角色授予对视图的 SELECT 特权,请执行以下操作:

GoogleSQL

GRANT SELECT ON VIEW SingerNames TO ROLE Analyst;

PostgreSQL

GRANT SELECT ON TABLE SingerNames TO Analyst;

如需从数据库角色撤消对视图的 SELECT 权限,请执行以下操作:

GoogleSQL

REVOKE SELECT ON VIEW SingerNames FROM ROLE Analyst;

PostgreSQL

REVOKE SELECT ON TABLE SingerNames FROM Analyst;

查询视图

查询调用方权限视图或定义方权限视图的方式相同。不过,根据视图的安全类型,Spanner 可能需要或不需要根据调用查询的正文的数据库角色检查视图中引用的架构对象。

查询调用方的权限视图

如果视图具有调用方的权限,用户必须对视图的所有底层架构对象拥有权限,才能对其进行查询。

例如,如果数据库角色有权访问 SingerNames 视图引用的所有对象,则可以查询 SingerNames 视图:

SELECT COUNT(SingerID) as SingerCount 
FROM SingerNames;

查询定义者的权限视图

如果视图具有定义者权限,只要您向所需角色授予对视图的 SELECT 权限,用户便无需对底层对象拥有权限即可查询该视图。

在以下示例中,具有“分析师”数据库角色的用户想要查询 SingerNames 视图。不过,系统会拒绝用户访问,因为 SingerNames 是调用方的权限视图,而“分析师”角色无权访问所有底层对象。在这种情况下,如果您决定向“分析师”角色授予对视图的访问权限,但不想向其授予对 Singers 表的访问权限,则可以替换视图的安全类型,以便为“定义者”角色授予相应权限。替换视图的安全类型后,请向“分析师”角色授予对该视图的访问权限。用户现在可以查询 SingerNames 视图,即使他们无权访问 Singers 表也是如此。

SELECT COUNT(SingerID) as SingerCount 
FROM SingerNames;

替换视图

您可以使用 CREATE OR REPLACE VIEW 语句更改视图定义或视图的安全类型,从而替换视图。

替换视图类似于删除并重新创建视图。替换视图后,必须重新向初始视图授予所有访问权限。

如需将调用方的权限视图替换为定义方的权限视图,请执行以下操作:

CREATE OR REPLACE VIEW SingerNames
SQL SECURITY DEFINER
AS SELECT
   Singers.SingerId AS SingerId,
   Singers.FirstName || ' ' || Singers.LastName AS Name
FROM Singers;

删除视图

视图被删除后,对其拥有权限的数据库角色将无法再访问该视图。如需删除视图,请使用 DROP VIEW 语句。

DROP VIEW SingerNames;

获取视图的相关信息

您可以通过查询 INFORMATION_SCHEMA 架构中的表来获取数据库中的视图的相关信息。

  • INFORMATION_SCHEMA.TABLES 表提供所有已定义视图的名称。

  • INFORMATION_SCHEMA.VIEWS 表提供所有已定义视图的名称、视图定义、安全类型和查询文本。对视图拥有 SELECT 权限的 FGAC 用户可以从 INFORMATION_SCHEMA.VIEWS 表中获取视图的相关信息。如果其他 FGAC 用户没有相应视图的 SELECT 权限,则需要拥有 spanner_info_reader 角色。

如需检查名为 ProductSoldLastWeek 的视图的视图定义和安全类型,请执行以下操作:

  SELECT *
  FROM INFORMATION_SCHEMA.VIEWS
  WHERE TABLE_NAME = 'ProductSoldLastWeek';