You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含JS代码的Snowflake SQL脚本无法通过Liquibase执行求助

问题描述

使用Snowflake管理数据库,尝试将现有含JavaScript代码的SQL脚本适配Liquibase执行。以下是创建函数的SQL代码:

create or replace function GetTimeSeries (businessDate text)
returns varchar
language javascript
as
$$
    var bDate = new Date(BUSINESSDATE);
    if(BUSINESSDATE == '' || bDate > new Date('2059-09-18')) {
        return 32767;
    }
    return Math.ceil(parseFloat((bDate-(new Date('01/01/1970')))/(24*3600*1000)));
    
$$;

该代码在Snowflake工作表中手动执行正常,但通过Liquibase CLI执行以下命令时:

liquibase update --defaults-file=dev.liquibase.properties --default-schema-name=DEV "-Dschema=DEV"

出现报错:

Unexpected error running Liquibase: Migration failed for changeset ../changelogs/dev/..
     Reason: liquibase.exception.DatabaseException: SQL compilation error:
parse error line 6 at position 39 near '<EOF>'.
syntax error line 5 at position 1 unexpected '$'. [Failed SQL: (1003) create or replace procedure GetTimeSeries (businessDate text)
returns text
language javascript
as
$$
    var bDate = new Date(BUSINESSDATE);

已对SQL文件做适配修改:

--liquibase formatted sql

-- changeset Bhushan:1
create or replace function ${schema}.GetTimeSeries (businessDate text)
returns varchar
language javascript
as
$$
    var bDate = new Date(BUSINESSDATE);
    if(BUSINESSDATE == '' || bDate > new Date('2059-09-18')) {
        return 32767;
    }
    return Math.ceil(parseFloat((bDate-(new Date('01/01/1970')))/(24*3600*1000)));

$$;

需要无需手动转换大量JS代码的解决方案。

解决方案

方法1:在Changeset中禁用语句拆分

Liquibase默认会按分号拆分SQL语句,且会错误解析Snowflake JS函数中的$$分界符,导致提前终止语句解析。只需在changeset中添加splitStatements=false配置,让Liquibase将整个函数定义作为单条完整SQL发送给Snowflake处理:

--liquibase formatted sql

-- changeset Bhushan:1 splitStatements=false
create or replace function ${schema}.GetTimeSeries (businessDate text)
returns varchar
language javascript
as
$$
    var bDate = new Date(BUSINESSDATE);
    if(BUSINESSDATE == '' || bDate > new Date('2059-09-18')) {
        return 32767;
    }
    return Math.ceil(parseFloat((bDate-(new Date('01/01/1970')))/(24*3600*1000)));

$$;

这种方式无需修改JS代码本身,适配所有含$$分界符的Snowflake JS函数/存储过程。

方法2:命令行全局禁用语句拆分

如果多个changeset都需要处理类似的JS代码,可以在执行Liquibase命令时添加--splitStatements=false参数:

liquibase update --defaults-file=dev.liquibase.properties --default-schema-name=DEV "-Dschema=DEV" --splitStatements=false

注意:该参数会对所有changeset生效,若存在需要拆分的普通SQL语句,建议优先使用方法1的局部配置。

方法3:使用XML格式Changelog(可选)

若切换到XML格式的changelog,可通过<sql>标签的splitStatements="false"属性实现同样效果:

<changeSet id="1" author="Bhushan">
    <sql splitStatements="false">
        create or replace function ${schema}.GetTimeSeries (businessDate text)
        returns varchar
        language javascript
        as
        $$
            var bDate = new Date(BUSINESSDATE);
            if(BUSINESSDATE == '' || bDate > new Date('2059-09-18')) {
                return 32767;
            }
            return Math.ceil(parseFloat((bDate-(new Date('01/01/1970')))/(24*3600*1000)));
        $$;
    </sql>
</changeSet>

内容的提问来源于stack exchange,提问作者Bhushan Goel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 12:59:13