跳转到主要内容
用户自定义函数 (UDF) 允许用户将 ClickHouse 的功能扩展到其内置的一千多种函数之外。 在 ClickHouse Cloud 中,创建用户自定义函数有两种方式:
  1. 使用 SQL
  2. 使用 UI 和你自己的代码 (Public Beta)

SQL 用户自定义函数

可以使用 CREATE FUNCTION 语句,基于 lambda 表达式创建 SQL UDF。 在此示例中,我们将创建一个简单的可执行用户自定义函数 isBusinessHours。 该函数会检查某个时间戳是否处于正常营业时间内;如果是则返回 true,否则返回 false。
  1. 登录 Cloud Console 并打开 SQL 控制台
  2. 编写以下 SQL 查询以创建 isBusinessHours 函数:
CREATE FUNCTION isBusinessHours AS (ts) ->
toDayOfWeek(ts) BETWEEN 1 AND 5
AND toHour(ts) BETWEEN 9 AND 17;
  1. 运行以下内容,测试你刚创建的 UDF:
SELECT isBusinessHours('2026-03-20 10:00:00'::DateTime), isBusinessHours('2026-03-20 23:00:00'::DateTime);
你应该会看到如下结果:
1   0
  1. 您可以使用 DROP FUNCTION 命令删除刚刚创建的 UDF:
DROP FUNCTION isBusinessHours
重要ClickHouse Cloud 中的 UDFs 不会继承用户级设置,而是按默认系统设置执行。
这意味着:
  • 会话级设置 (通过 SET 语句设置) 不会传递到 UDF 的执行上下文中
  • 用户 profile 中的设置不会被 UDFs 继承
  • 查询级设置在 UDF 执行期间不生效

通过 UI 创建的用户自定义函数

ClickHouse Cloud 提供了可通过 UI 创建用户自定义函数的配置界面。 在本示例中,我们将创建与前文相同的简单可执行用户自定义函数 isBusinessHours,用于检查某个时间戳是否落在正常工作时间内。 此前我们是通过 SQL 创建它的,这次则改用 Python 创建,并通过 UI 进行配置。
1

创建 Python 文件

在本地新建一个 main.py 文件:
cat > main.py << 'EOF'
import sys
from datetime import datetime

for line in sys.stdin:
    ts = datetime.fromisoformat(line.strip())
    result = 1 if (0 <= ts.weekday() <= 4 and 9 <= ts.hour <= 17) else 0
    print(result)
    sys.stdout.flush()
EOF
如果你的 Python 脚本导入了第三方包,就必须创建一个 requirements.txt 文件,并在其中列出这些依赖项。例如:
requests>=2.28.0
numpy>=1.23.0
ClickHouse Cloud 会在你下一步通过 UI 上传的 zip 文件中查找 main.py。 如果将该文件命名为其他名称,就会报错。
2

打包依赖项和本地文件

要包含依赖包以及其他本地文件 (例如 wheel 文件、配置文件或数据文件) ,请将它们放在与您的 main.pyrequirements.txt 相同的目录中。创建 ZIP 归档时,请包含所有文件:
zip is_business_hours.zip main.py requirements.txt
你可以在 Python 代码中使用 os.path.dirname(os.path.abspath(__file__)) 引用本地打包路径的基目录。它会返回 ZIP 归档中 main.py 所在目录的绝对路径,以便你访问其他一并打包的文件:
import os

# 获取打包文件的根目录
base_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(base_dir, 'config.json')
在你需要执行以下操作时,这会很有用:
  • 访问随 UDF 一起打包的配置文件
  • 为自定义依赖加载 wheel 包
  • 引用其他脚本或数据文件
现在将该文件压缩为 ZIP 压缩包:
zip is_business_hours.zip main.py
不允许使用符号链接ClickHouse Cloud 会拒绝包含符号链接的 UDF 归档文件。请确保 ZIP 压缩包中只包含普通文件和目录——包含符号链接的上传内容将无法通过验证。
3

通过 UI 创建 UDF

  1. 在 Cloud 控制台主页上,点击左下角菜单中的组织名称。
  2. 从菜单中选择用户自定义函数
  3. 在用户自定义函数页面中,点击设置 UDF。屏幕右侧会打开一个配置面板。
  4. 输入函数名称。本示例使用 isBusinessHours
  5. 选择函数类型,可选 Executable poolExecutable
    • Executable pool:系统会维护一个持久进程池,并从池中取出进程来处理读取请求。
    • Executable:脚本会在每次查询时运行。
  6. 本示例使用默认设置。有关完整的配置参数列表,请参见可执行用户自定义函数
  7. 点击浏览文件,上传在本教程开头创建的 .zip 文件。
  8. 添加一个新参数。本示例中,添加一个类型为 DateTime 的参数 timestamp
  9. 选择返回类型。本示例中,选择 Bool
  10. 点击创建 UDF。此时会显示一个对话框,展示当前构建状态。
    • 如果出现任何问题,状态将变为错误
    • 否则,状态会从构建中变为预配中。你的服务必须处于唤醒状态才能完成预配。如果服务处于空闲状态,请在服务名称旁的 UDF 详细信息 面板中点击唤醒服务
    • 完成后,状态将变为已部署
4

测试你的 UDF

  1. 点击页面左上角的 Settings - 返回到服务视图,返回 SQL 控制台主页
  2. 点击左侧菜单中的 SQL 控制台
  3. 输入以下查询:
SELECT isBusinessHours('2026-03-20 10:00:00'::DateTime), isBusinessHours('2026-03-20 23:00:00'::DateTime);
你应该会看到如下结果:
true    false
5

创建新版本

  1. 在 Cloud Console 首页,点击左下角菜单中的组织名称。
  2. 在菜单中选择 用户自定义函数
  3. isBusinessHours UDF 的 操作 一栏中点击三点图标,然后点击 创建新版本
  4. 上传包含修改后代码的 ZIP 压缩包,或修改设置,然后点击 创建新版本
你已成功通过 UI 添加了第一个用户自定义函数,确认其可正常运行,并了解了在需要时如何创建新版本。
最后修改于 2026年6月10日