将Snowflake的结构体类型作为参数传递

编程语言 2026-07-09

我在尝试评估Snowflake的新 CREATE TYPE 功能。

这确实可行,但我在把结构化类型传入存储过程时遇到困难。

对下面代码运行Run All时会抛出异常:

未捕获的异常,类型为 'STATEMENT_ERROR',在第11行第4 位置:SQL编译错误:不兼容的类型:[UNKNOWN] 与 [STRUCTURED_OBJECT]

SHOW PROCEDURES 报告了正确的参数类型。但在最末端的 CALL 中,ARRAY 类型似乎正在被丢失。

CREATE OR REPLACE SCHEMA MVE;

CREATE OR REPLACE TYPE MVE_RANGE AS OBJECT (
    RANGE_START INTEGER,
    RANGE_END   INTEGER
);

CREATE OR REPLACE PROCEDURE TEST_MVE_ARRAY(A ARRAY(MVE_RANGE))
RETURNS INTEGER
LANGUAGE SQL
AS
BEGIN
    RETURN ARRAY_SIZE(:A);
END;

DECLARE
    A ARRAY(MVE_RANGE NOT NULL) DEFAULT ARRAY_CONSTRUCT()::ARRAY(MVE_RANGE);
    R INTEGER;
BEGIN
    SELECT ARRAY_APPEND(
               ARRAY_CONSTRUCT()::ARRAY(MVE_RANGE),
               {'RANGE_START':1, 'RANGE_END':2}::MVE_RANGE
           )
    INTO   :A;
    A:=A::ARRAY(MVE_RANGE);
    R := (CALL TEST_MVE_ARRAY((:A)::ARRAY(MVE_RANGE)));
    RETURN :R;
END;

解决方案

Workaround: It is possible to pass it directly without an error:

变通方法:可以直接传递它而不出错:

DECLARE
    R INTEGER;
BEGIN
    CALL MVE.TEST_MVE_ARRAY(SELECT ARRAY_APPEND(
                ARRAY_CONSTRUCT()::ARRAY(MVE.MVE_RANGE),
                {'RANGE_START':1, 'RANGE_END':2}::MVE.MVE_RANGE
            )) 
    INTO :R;

    RETURN :R;
END;

-- anonymous block
-- 1

尽管在 CALL 中使用了结构化类型的中间变量时会报错:

DECLARE
    R INTEGER;
BEGIN
    LET A := (SELECT ARRAY_APPEND(
                ARRAY_CONSTRUCT()::ARRAY(MVE.MVE_RANGE),
                {'RANGE_START':1, 'RANGE_END':2}::MVE.MVE_RANGE
            ))::ARRAY(MVE.MVE_RANGE);

    CALL MVE.TEST_MVE_ARRAY(:A::ARRAY(MVE.MVE_RANGE)) INTO :R;  -- error

    RETURN :R;
END;

不兼容的类型:[UNKNOWN] 与 [STRUCTURED_OBJECT]

直接提供一个值也能工作:

DECLARE
  R INTEGER;
BEGIN
  CALL MVE.TEST_MVE_ARRAY([{'RANGE_START':1, 'RANGE_END':2}]::ARRAY(MVE.MVE_RANGE)) 
  INTO :R;
  RETURN :R;
END;
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章