Skip to main content
创建由 SQL 定义的自定义 HTTP 处理程序,无需编辑服务器配置文件。SQL 定义的处理程序可替代基于配置的 HTTP 接口处理程序

语法

使用指定的 name 创建处理程序。该名称用于通过 SQL 查询管理处理程序、生成诊断消息以及确定处理程序的顺序。

子句

  • PROTOCOL — 可选。如果指定了协议名称,处理程序仅对指定的可组合协议生效。否则,处理程序会在所有 HTTP 端点上生效:内置的 http/https 端口,以及每个 HTTP 类型的可组合协议侦听器。PROTOCOL ANY 显式指定后一种默认行为;在 ALTER HANDLER 中,它会移除此前设置的协议限制。名称恰为 any 的协议可使用反引号引用:PROTOCOL `any`
  • URL — 必填。可以是精确 URL、URL PREFIXURL REGEXP。对于精确 URL 和前缀,会在创建或修改时检查是否存在歧义;如有歧义,则抛出异常。对于 regexp,无法检查歧义。匹配 URL 时会忽略 ? 查询字符串和 # 片段标识符。URL PREFIX 会作为基路径在路径段边界处匹配——其语义与通过配置定义的处理程序中的 url_prefix 规则相同:URL PREFIX '/api/v1' 匹配 /api/v1/api/v1//api/v1/write,但不匹配 /api/v1beta。前缀末尾的 / 会被忽略,因此 '/api/v1/''/api/v1' 的行为相同。
  • METHODS — 可选。允许的 HTTP 方法列表。默认为仅允许 GET。支持的方法包括 GETPOSTPUTDELETE。会修改数据的方法 POSTPUTDELETE 可执行修改数据的查询;GETHEAD 等安全方法始终以 readonly 模式执行。因此,执行修改数据查询 (例如 INSERT 或 DDL) 的处理程序必须允许至少一种修改方法——若仅使用只读方法 (例如默认的 GET) 创建此类处理程序,将抛出异常。副作用可在 readonly 模式下保留的查询属于特殊情况:BACKUPRESTORE 具有持久性副作用;使用 session_id 时,修改会话的语句 SETSET ROLEUSEBEGIN TRANSACTIONCOMMITROLLBACKSET TRANSACTION SNAPSHOT 会更改跨请求持续保留的会话或事务状态;CREATE TEMPORARY TABLE / CREATE TEMPORARY VIEW 会创建仅存在于会话中的对象——但安全方法的 readonly 模式不会阻止其中任何一种。readonly 模式同样不会阻止对现有临时表的修改,因此可能以临时表为目标的查询也按相同方式处理:目标表未使用数据库限定的 INSERT (未限定名称可能解析为会话临时表) 、DROP TEMPORARY TABLE、对未使用数据库限定的表执行的 DROP TABLE / TRUNCATE TABLE,以及对未使用数据库限定的表执行的 ALTER (ALTER TEMPORARY TABLE 是相同的语句) 。使用数据库限定的目标不可能是临时表,因此此类查询不受此规则约束。HTTP 要求安全方法不得产生副作用 (声明为 GET 的处理程序也会处理 HEAD 请求,此时响应正文会被抑制,副作用将不可见) 。因此,执行此类查询的处理程序必须列出修改方法——创建或修改该处理程序时如包含安全方法,将抛出异常。会深入检查复合语句:对于 statement1 PARALLEL WITH statement2 ...EXECUTE AS <user> <statement>,上述规则适用于其包装的语句,因为实际执行的是这些语句 (每个语句都在处理程序上下文的副本中运行,该副本会保留 readonly 模式) 。不带语句的 EXECUTE AS <user> 会使整个会话以另一用户身份运行,因此它本身会修改会话。此外,任何 EXECUTE AS 处理程序——无论是不带语句还是包装语句——都必须允许至少一种修改方法:身份模拟需要 IMPERSONATE 权限,而安全方法的 readonly 模式会拒绝该权限。
  • TYPE — 可选。目前唯一支持的类型是 query
  • AS — 此处理程序将调用的 SQL 查询。该查询可以参数化。在创建或修改处理程序时,会对查询进行语法解析以检查其正确性,但不会进行语义分析——例如,创建处理程序时,查询所引用的表可能尚不存在。FORMAT 及类似子句属于查询本身,而不属于整个 CREATE/ALTER 语句。为消除歧义,可将查询置于括号中。INSERT 查询的 VALUESFORMAT 子句后不得包含内联数据——创建或修改此类处理程序会引发异常,因为内联载荷无法保留在处理程序定义中;数据应通过 HTTP 请求正文提供 (或由 INSERT ... SELECT 计算) 。对于处理程序查询会读取请求正文的请求——即从正文获取数据的 INSERT,或使用 _request_body 参数的查询——必须声明正文长度:不含 Content-Length 请求头的非分块请求将收到 411 Length Required 响应,因为否则正文会一直读取到 stream 结束,连接中断也会被视为完整请求。此类处理程序的每种方法也必须是可携带请求正文的方法 (POSTPUTDELETE) ——如果在 METHODS 子句中使用安全方法创建处理程序 (例如默认的 GET) ,将引发异常,因为安全方法绝不会提供请求正文,查询会在不知不觉中读取空正文;声明 GET 后也会为 HEAD 提供服务,因此混用安全方法和可携带请求正文的方法会使这些调用仍然可达。INSERT ... SELECT 不读取请求正文 (其数据来自 SELECT) ,因此不受这些要求约束——除非其 SELECT 从由请求正文提供数据的 input 表函数读取。读取请求正文的 INSERT 必须是处理程序自身的查询:EXECUTE ASPARALLEL WITH 在运行其封装的语句时不会使用请求正文,因此在创建时将此类查询封装在其中会被拒绝,以避免悄然丢弃每次上传的数据。读取请求正文的查询也不得使用 _request_body 参数:请求正文只有一个,绑定 _request_body 会在查询读取输入数据前将其消耗,因此此类处理程序会在创建时被拒绝,以避免悄然丢失每次上传的数据——请使用查询自身的正文输入或 _request_body,不要同时使用两者。不读取请求正文的处理程序没有此类要求;对此类处理程序的请求正文会被忽略,绝不会追加到处理程序的查询中。每次重新加载或调用处理程序时,服务器都会以无限制的解析器深度和回溯次数重新解析存储的查询文本,因此,在提高 max_parser_depth / max_parser_backtracks 的会话中创建的处理程序,在普通会话限制下仍可加载和调用。

优先级

服务器配置中定义的处理程序优先于通过 SQL 定义的处理程序。通过 SQL 定义的处理程序会按名称的词典序进行匹配。

参数

与配置定义的 处理程序 一样,参数化查询的查询参数可通过以下方式提供:
  • 查询字符串中的 HTTP URL 参数,使用 param_<name> 命名约定 (例如,?param_id=42 绑定 {id:Type}) ;
  • URL REGEXP 中的命名捕获组 (例如,URL REGEXP '/users/(?P<id>\d+)' 绑定 {id:Type}) ;
  • 对于查询中声明了参数的 处理程序,请求正文中的表单字段:在携带正文的 POSTPUTDELETE 方法中,application/x-www-form-urlencoded 正文 (例如,curl -d 'param_id=42') 和 multipart/form-data 正文中的字段均会像 URL 参数一样绑定 {name:Type} 参数。若某个参数同时出现在 URL 和正文中,则以 URL 中的值为准。被解析为表单的正文会由 处理程序 层消费,不会作为 INSERT 数据传递给查询。如果 处理程序 对正文的唯一用途是 _request_body,则会获得原始正文,而不会进行表单解析;如果 处理程序 除了其他参数外还声明了 _request_body,则两者都会获得——在将正文解析为表单前,原始未解析正文的副本会保存在 _request_body 中 (受 http_max_request_param_data_size 限制) 。
调用 处理程序 时,标准 ClickHouse HTTP 请求头 (如 X-ClickHouse-DatabaseX-ClickHouse-UserX-ClickHouse-Key) 仍会照常生效。 函数 currentHandlercurrentRequestURL 可用于根据调用的 处理程序 和请求 URL 自定义查询行为。

访问控制

CREATE HANDLERDROP HANDLERALTER HANDLER 分别需要 CREATE HANDLERDROP HANDLERALTER HANDLER 授权。 读取 system.handlers 表需要 SHOW HANDLERS 授权。处理程序查询中可能嵌入的 secret 会在该表中被掩码,除非用户还获准查看 secret (请参阅 system.handlers) 。 调用处理程序无需额外授权,但在执行查询时仍会照常检查授权,并按常规进行身份验证。若要封装对特定查询的访问,请创建一个使用 SQL SECURITY DEFINERVIEW,并定义一个从该视图中查询的处理程序。

存储

处理程序保存在存储中。与命名集合类似,存储可以是本地存储或 Keeper 存储,并在配置文件的 query_rules_storage 部分中进行配置:
使用 Keeper 存储时,处理程序 会自动在所有副本之间保持同步,因此显式指定 ON CLUSTER 子句不仅多余,还会导致每个副本都尝试创建同一个 处理程序。启用 ignore_on_cluster_for_replicated_handler_queries 设置后,当存储已启用复制时,CREATEALTERDROP HANDLER 会忽略 ON CLUSTER,其行为与 ignore_on_cluster_for_replicated_named_collections_queries 一致。

ALTER HANDLER

将 处理程序 替换为新的 处理程序。ALTER 查询只能包含部分子句;例如,可仅更改 URL 或查询。未指定的子句将保留原有值。PROTOCOL ANY 会移除现有的协议限制,使 处理程序 再次在所有 HTTP 端点上生效。

DROP HANDLER

删除指定名称的处理程序。

内部信息

system.handlers 表列出所有通过 SQL 定义的处理程序。system.query_log 表在 http_handler_namehttp_request_url 列中记录每个查询对应的处理程序名称及 HTTP 请求路径 (不含查询字符串) 。

示例

带有 Regexp URL 的参数化处理程序:
CREATE HANDLERCREATE 语句家族的一部分,与 ALTERDROP 相关。
最后修改于 2026年8月27日