> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-trino-dialect.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> ROW POLICY 文档

# CREATE ROW POLICY

创建[行策略](/zh/concepts/features/security/access-rights#row-policy-management)，即一种用于确定用户可从表中读取哪些行的过滤器。

<Tip>
  行策略仅适用于具有只读访问权限的用户。如果用户可以修改表，或在表之间复制分区，就会绕过行策略的限制。
</Tip>

语法：

```sql theme={null}
-- Multiple names on one table target
CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name [, ...]
    [ON CLUSTER cluster_name]
    ON { [db.]table | db.* }
    [IN access_storage_type]
    [FOR SELECT] USING condition
    [AS {PERMISSIVE | RESTRICTIVE}]
    [TO {role1 [, role2 ...] | ALL | ALL EXCEPT role1 [, role2 ...]}]

-- One name on multiple table targets
CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name
    [ON CLUSTER cluster_name]
    ON { [db.]table | db.* } [, ...]
    [IN access_storage_type]
    [FOR SELECT] USING condition
    [AS {PERMISSIVE | RESTRICTIVE}]
    [TO {role1 [, role2 ...] | ALL | ALL EXCEPT role1 [, role2 ...]}]

-- Mixed packing: each name paired with its own table target
CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE]
    policy_name ON { [db.]table | db.* } [, policy_name ON { [db.]table | db.* } ...]
    [ON CLUSTER cluster_name]
    [IN access_storage_type]
    [FOR SELECT] USING condition
    [AS {PERMISSIVE | RESTRICTIVE}]
    [TO {role1 [, role2 ...] | ALL | ALL EXCEPT role1 [, role2 ...]}]
```

`ParserRowPolicyNames` 支持**三种**打包形式 (并非完整的笛卡尔积) ：

1. **多个名称，一个目标** — `pol1, pol2 ON table1` 会在该表 (或 `db.*`) 上创建列出的每个名称。
2. **一个名称，多个目标** — `pol1 ON table1, table2` 会在每个列出的目标上创建相同的短名称。
3. **混合配对** — `p1 ON t1, p2 ON t2` 仅在各自配对的目标上创建对应的名称。

多名称列表**不能**与多表 `ON` 列表组合在同一组中：`p1, p2 ON t1, t2` 会被拒绝。多名称组之后，也不能在同一语句中追加另一个以逗号分隔的 `name ON target` 组。

可选的 `ON CLUSTER` 适用于整个语句 (仅指定一个集群名称) 。ClickHouse **不**接受在单个创建语句中为每个策略名称指定不同的 `ON CLUSTER` — 若必须在不同集群上创建策略，请分别执行 `CREATE ROW POLICY` 语句。

<div id="multiple-names-and-tables">
  ## 多个名称和表
</div>

有效：

```sql theme={null}
-- Several policy names, one table
CREATE ROW POLICY pol1, pol2, pol3 ON table1
    FOR SELECT USING id = 1
    TO accountant;

-- One policy name, several tables
CREATE ROW POLICY IF NOT EXISTS pol1 ON table1, table2, table3
    FOR SELECT USING id = 1
    TO accountant;

-- Mixed packing: different name per table
CREATE ROW POLICY p4 ON db.table, p5 ON db2.table2
    USING a = b;

-- Same policy on several tables, on a cluster
CREATE ROW POLICY IF NOT EXISTS pol1 ON CLUSTER replicated_cluster ON table1, table2
    FOR SELECT USING id = 1
    TO accountant;
```

无效：

```sql theme={null}
-- Multi-name × multi-table in one ON-group (not a Cartesian product)
CREATE ROW POLICY p1, p2 ON t1, t2
    FOR SELECT USING id = 1
    TO accountant;

-- Different clusters per name in one statement
CREATE ROW POLICY pol1 ON CLUSTER cluster1 ON table1, pol2 ON CLUSTER cluster2 ON table2
```

<div id="using-clause">
  ## USING 子句
</div>

允许指定用于过滤行的条件。若某一行上的该条件计算结果非零，用户就能看到该行。

<div id="to-clause">
  ## TO 子句
</div>

在 `TO` 部分中，您可以指定此策略适用的用户和 roles 列表。例如，`CREATE ROW POLICY ... TO accountant, john@localhost`。

关键字 `ALL` 表示所有 ClickHouse 用户，包括当前用户。关键字 `ALL EXCEPT` 允许从所有用户列表中排除某些用户，例如 `CREATE ROW POLICY ... TO ALL EXCEPT accountant, john@localhost`

<div id="as-clause">
  ## AS 子句
</div>

允许同一用户在同一张表上同时启用多个策略。因此，我们需要一种方式来组合多个策略中的条件。

默认情况下，策略通过布尔 `OR` 运算符进行组合。例如，以下策略：

```sql theme={null}
CREATE ROW POLICY pol1 ON mydb.table1 USING b=1 TO mira, peter
CREATE ROW POLICY pol2 ON mydb.table1 USING c=2 TO peter, antonio
```

允许用户 `peter` 查看满足 `b=1` 或 `c=2` 的行。

`AS` 子句指定策略应如何与其他策略组合。策略可以是宽松型或限制型。默认情况下，策略为宽松型，这意味着它们会通过布尔 `OR` 运算符组合。

或者，也可以将策略定义为限制型。限制型策略会通过布尔 `AND` 运算符组合。

以下是通用公式：

```text theme={null}
row_is_visible = (one or more of the permissive policies' conditions are non-zero) AND
                 (all of the restrictive policies's conditions are non-zero)
```

例如，以下策略：

```sql theme={null}
CREATE ROW POLICY pol1 ON mydb.table1 USING b=1 TO mira, peter
CREATE ROW POLICY pol2 ON mydb.table1 USING c=2 AS RESTRICTIVE TO peter, antonio
```

仅当 `b=1` 且 `c=2` 两个条件同时满足时，才允许用户 `peter` 查看这些行。

数据库策略会与表策略组合生效。

例如，以下策略：

```sql theme={null}
CREATE ROW POLICY pol1 ON mydb.* USING b=1 TO mira, peter
CREATE ROW POLICY pol2 ON mydb.table1 USING c=2 AS RESTRICTIVE TO peter, antonio
```

使用户 `peter` 只有在同时满足 `b=1` 且 `c=2` 时才能看到 table1 的行，尽管
mydb 中的任何其他表对该用户都只会应用 `b=1` 策略。

<div id="distributed-and-remote-backed-tables">
  ## Distributed 和由远程服务器支持的表
</div>

行策略会在实际读取表数据的位置过滤行。将读取操作委托给远程服务器的表，例如 [Distributed](/zh/reference/engines/table-engines/special/distributed) 表或其封装 (例如，目标为 `Distributed` 的 materialized view) ，只会将查询文本发送到远程服务器，无法对远程读取应用策略过滤器。为避免过滤器被悄然忽略，策略适用用户对这类表发起的查询会因 `ILLEGAL_PREWHERE` 错误而被拒绝。

请改为在每台远程服务器的底层本地表上定义策略；当发送的查询读取这些表时，策略会在该处生效：

```sql theme={null}
-- Filters reads of local_table on this server, including reads shipped by a Distributed table over it.
CREATE ROW POLICY filter ON mydb.local_table USING a < 1000 TO john;
```

<Warning>
  此机制仅在查询以文本形式发送时生效，默认即为此方式。使用 [`serialize_query_plan = 1`](/zh/reference/settings/session-settings/serialize#serialize_query_plan) 时，发起节点会改为发送已构建的读取计划；执行该计划的远程服务器不会应用其自身的行策略。因此，通过 `local_table` 读取 `Distributed` 表会返回未过滤的行。对于必须强制执行行策略的用户，请保持 `serialize_query_plan = 0`。参见 [issue #112891](https://github.com/ClickHouse/ClickHouse/issues/112891)。
</Warning>

<div id="on-cluster-clause">
  ## ON CLUSTER 子句
</div>

允许在集群中创建行策略，参见 [Distributed DDL](/zh/reference/statements/distributed-ddl)。这也是在集群中每台服务器的本地表上创建策略的便捷方式。

<div id="examples">
  ## 示例
</div>

`CREATE ROW POLICY filter1 ON mydb.mytable USING a<1000 TO accountant, john@localhost`

`CREATE ROW POLICY filter2 ON mydb.mytable USING a<1000 AND b=5 TO ALL EXCEPT mira`

`CREATE ROW POLICY filter3 ON mydb.mytable USING 1 TO admin`

`CREATE ROW POLICY filter4 ON mydb.* USING 1 TO admin`
