SnowConvert AI - Oracle - COLLECTIONS AND RECORDS

Oracle COLLECTIONS 및 RECORDS 문을 Snowflake Scripting으로 변환하기 위한 변환 참조

경고

이 섹션은 진행 중인 작업으로 향후 정보가 변경될 수 있습니다.

일반 설명

PL/SQL 에서 컬렉션과 레코드가라는 두 가지 복합 데이터 타입을 정의할 수 있으며, 여기서 복합은 내부 구성 요소를 가진 값을 저장하는 데이터 타입입니다.

컬렉션에서 내부 구성 요소는 항상 동일한 데이터 타입을 가지며 이를 요소라고 합니다.

레코드에서 내부 구성 요소는 서로 다른 데이터 타입을 가질 수 있으며 이를 필드라고 합니다. (Oracle PL/SQL Language Reference COLLECTIONS AND RECORDS)

참고

일부 해결 방법은 중복될 수 있고 두 시나리오 모두에서 작동할 수 있으므로 CREATE TYPE 문 변환 참조를 참조하세요.

제한 사항

온라인 설명서 지원되지 않는 데이터 타입 에 따르면 Snowflake는 PL 컬렉션 및 레코드를 포함한 사용자 정의 데이터 타입은 지원하지 않지만, 레코드의 계층 구조와 컬렉션 사용자 정의 타입의 요소 구조를 모두 모방하는 데 사용할 수 있는 반정형 데이터 타입 을 지원합니다. 이러한 이유로 해결 방법이 없는 여러 유형의 기능이 있습니다.

다음은 NO 해결 방법이 제안된 기능입니다.

변수 크기는 16MB 를 초과할 수 없습니다

Snowflake는 VARIANT, OBJECT, ARRAY 의 최대 크기를 16MBs 로 설정합니다. 즉, 레코드, 컬렉션 또는 둘 중 어느 한 요소가 이 크기를 초과하면 런타임 오류가 발생합니다.

Varray 용량은 제한할 수 없습니다

Oracle의 varray는 그 안에 있는 요소의 수를 제한할 수 있는 용량을 제공합니다. 이 기능은 Snowflake에서 지원되지 않습니다.

제안된 해결 방법

레코드 유형 정의 정보

제안된 해결 방법은 “OBJECT”반정형 데이터 타입을 사용하여 Oracle의 데이터 타입을 모방하는 것입니다.

컬렉션 유형 정의 정보

마이그레이션할 컬렉션 유형에 따라 두 가지 해결 방법이 있습니다.

  • 연관 배열을 “OBJECT” 반정형 데이터 타입으로 변경할 것을 제안합니다.

  • 배열과 중첩된 테이블 배열은 “ARRAY” 반정형 데이터 타입으로 변경될 예정입니다.

현재 SnowConvert AI 지원

다음 테이블은 SnowConvert AI 도구에서 제공하는 현재 지원에 대한 요약을 보여줍니다. 변환이 아직 최종 버전이 아닐 수 있으며 더 많은 작업이 필요할 수 있습니다.

하위 기능

현재 인식 상태

현재 변환 상태

알려진 해결 방법이 있음

레코드 유형 정의

인식됨.

변환되지 않음.

예.

연관 배열 유형 정의

인식되지 않음.

변환되지 않음.

예.

배열 유형 정의

인식됨.

변환되지 않음.

예.

중첩 테이블 배열 유형 정의

인식됨.

변환되지 않음.

예.

Known Issues

1. Associate Arrays are considered a Nested Table

현재, SnowConvert AI는 연관 배열과 중첩 테이블을 구분하지 않습니다. 즉, 동일한 평가 횟수에서 혼합되어 있습니다.

연관 배열 유형 정의

이는 Oracle 연관 배열 선언을 Snowflake로 변환하기 위한 변환 참조입니다.

경고

이 섹션은 진행 중인 작업으로 향후 정보가 변경될 수 있습니다.

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

설명

연관 배열(이전에는 PL/SQL 테이블 또는 인덱스별 테이블이라고 함)은 키-값 페어의 집합입니다. 각 키는 고유한 인덱스이며, variable_name(index) 구문으로 연관된 값을 찾는 데 사용됩니다.

인덱스 의 데이터 타입은 문자열 타입(VARCHAR2, VARCHAR, STRING, LONG) 또는 PLS_INTEGER 일 수 있습니다. 인덱스는 생성 순서가 아닌 정렬 순서로 저장됩니다. 문자열 유형의 경우 정렬 순서는 초기화 매개 변수 NLS_SORTNLS_COMP 에 의해 결정됩니다.

(Oracle PL/SQL Language Reference ASSOCIATIVE ARRAYS)

경고

PL/SQL NESTED TABLE 유형 정의와 혼동하지 마십시오.

변환의 경우, 유형 정의가 OBJECT 반정형 데이터 타입 으로 대체된 후 모든 작업에서 그 용도가 그에 따라 변경됩니다.

연관 배열 유형을 정의하는 구문은 다음과 같습니다.

type_definition := TYPE IS TABLE OF datatype INDEX BY indexing_datatype;

indexing_datatype := { PLS_INTEGER
                     | BINARY_INTEGER
                     | string_datatype
                     }
Copy

이 유형의 변수를 선언하려면:

variable_name collection_type;

Copy

샘플 소스 패턴

varchar 인덱싱된 연관 배열

Oracle
CREATE OR REPLACE PROCEDURE associative_array
IS
    TYPE associate_array_typ IS TABLE OF INTEGER
        INDEX BY VARCHAR2(50);
        
    associate_array associate_array_typ := associate_array_typ();
    associate_index VARCHAR2(50);
BEGIN
    associate_array('abc') := 1;
    associate_array('bca') := 2;
    associate_array('def') := 3;
    
    DBMS_OUTPUT.PUT_LINE(associate_array('abc'));
    associate_array('abc') := 4;
    --THROWS 'NO DATA FOUND'
    --DBMS_OUTPUT.PUT_LINE(associate_array('no exists'));
    
    DBMS_OUTPUT.PUT_LINE(associate_array.COUNT);
    
    associate_index := associate_array.FIRST;
    WHILE associate_index IS NOT NULL
    LOOP
        DBMS_OUTPUT.PUT_LINE(associate_array(associate_index));
        associate_index := associate_array.NEXT(associate_index);
    END LOOP;
END;

CALL associative_array();
Copy
결과

DBMS OUTPUT

1

3

4

2

3

Snowflake

OBJECT_INSERT 에서 ‘true’ 매개 변수에 유의하십시오. 이는 요소가 배열에 이미 있는 경우 업데이트하기 위한 것입니다.

CREATE OR REPLACE PROCEDURE PUBLIC.associative_array ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
   DECLARE
      associate_array OBJECT := OBJECT_CONSTRUCT();
      associate_index VARCHAR(50);
   BEGIN
      associate_array := OBJECT_INSERT(associate_array, 'abc', 1, true);
      associate_array := OBJECT_INSERT(associate_array, 'bca', 2, true);
      associate_array := OBJECT_INSERT(associate_array, 'def', 3, true);

      CALL DBMS_OUTPUT.PUT_LINE(:associate_array['abc']);
      CALL DBMS_OUTPUT.PUT_LINE(:associate_array['not found']);
      
      associate_array := OBJECT_INSERT(:associate_array, 'abc', 4, true);
    
      CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(OBJECT_KEYS(:associate_array)));
      
      FOR i IN 1 TO ARRAY_SIZE(OBJECT_KEYS(:associate_array))
      LOOP
         associate_index := OBJECT_KEYS(:associate_array)[:i-1];
         CALL DBMS_OUTPUT.PUT_LINE(:associate_array[:associate_index]);
      END LOOP;
   END;
$$;

CALL PUBLIC.associative_array();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
결과

DBMS OUTPUT

1

3

4

2

3

숫자 인덱스 연관 배열

Oracle
CREATE OR REPLACE PROCEDURE numeric_associative_array
IS
    TYPE numeric_associative_array_typ IS TABLE OF INTEGER
        INDEX BY PLS_INTEGER;
        
    associate_array numeric_associativ
    e_array_typ := numeric_associative_array_typ();
    associate_index PLS_INTEGER;
BEGIN
    associate_array(1) := -1;
    associate_array(2) := -2;
    associate_array(3) := -3;
    
    DBMS_OUTPUT.PUT_LINE(associate_array(1));
    associate_array(1) := -4;
    
    DBMS_OUTPUT.PUT_LINE(associate_array.COUNT);
    
    associate_index := associate_array.FIRST;
    WHILE associate_index IS NOT NULL
    LOOP
        DBMS_OUTPUT.PUT_LINE(associate_array(associate_index));
        associate_index := associate_array.NEXT(associate_index);
    END LOOP;
END;

CALL numeric_associative_array();
Copy
결과

DBMS OUTPUT

-1

3

-4

-2

-3

Snowflake

숫자 값은 작업에서 필요할 때 적절하게 varchar로 변환됩니다. 또한 OBJECT_INSERT 에서 ‘true’ 매개 변수에 유의하십시오. 이는 요소가 배열에 이미 있는 경우 업데이트하기 위한 것입니다.

CREATE OR REPLACE PROCEDURE PUBLIC.numeric_associative_array ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
   DECLARE
      associate_array OBJECT := OBJECT_CONSTRUCT();
      associate_index NUMBER;
   BEGIN
      associate_array := OBJECT_INSERT(associate_array, '1', -1, true);
      associate_array := OBJECT_INSERT(associate_array, '2', -2, true);
      associate_array := OBJECT_INSERT(associate_array, '3', -3, true);

      CALL DBMS_OUTPUT.PUT_LINE(:associate_array['1']);
      
      associate_array := OBJECT_INSERT(:associate_array, '1', -4, true);
    
      CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(OBJECT_KEYS(:associate_array)));
      
      FOR i IN 1 TO ARRAY_SIZE(OBJECT_KEYS(:associate_array))
      LOOP
         associate_index := OBJECT_KEYS(:associate_array)[:i-1];
         CALL DBMS_OUTPUT.PUT_LINE(:associate_array[:associate_index::VARCHAR]);
      END LOOP;
   END;
$$;

CALL PUBLIC.numeric_associative_array();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
결과

DBMS OUTPUT

-1

3

-4

-2

-3

레코드 요소 숫자 인덱스 연관 배열

이 경우 연관 배열은 레코드 구조로 구성되며, 이 구조는 보존되어야 합니다. 이를 위해 삽입에 대한 추가 작업이 추가되었습니다.

Oracle
CREATE OR REPLACE PROCEDURE record_associative_array
IS
    TYPE record_typ IS RECORD(col1 INTEGER);
    TYPE record_associative_array_typ IS TABLE OF record_typ
        INDEX BY PLS_INTEGER;
        
    associate_array record_associati ve_array_typ := record_associative_array_typ();
    associate_index PLS_INTEGER;
BEGIN
    associate_array(1).col1 := -1;
    associate_array(2).col1 := -2;
    associate_array(3).col1 := -3;
    
    DBMS_OUTPUT.PUT_LINE(associate_array(1).col1);
    associate_array(4).col1 := -4;
    
    DBMS_OUTPUT.PUT_LINE(associate_array.COUNT);
    
    associate_index := associate_array.FIRST;
    WHILE associate_index IS NOT NULL
    LOOP
        DBMS_OUTPUT.PUT_LINE(associate_array(associate_index).col1);
        associate_index := associate_array.NEXT(associate_index);
    END LOOP;
END;
/

CALL record_associative_array();
Copy
결과

DBMS OUTPUT

-1

3

-4

-2

-3

Snowflake

이 시나리오에서 삽입/업데이트는 연관 배열 내에서 레코드가 자동으로 생성되는 것으로 가정하므로 새 레코드를 생성할 때 이를 고려해야 합니다.

CREATE OR REPLACE PROCEDURE PUBLIC.record_associative_array ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
   DECLARE
      associate_array OBJECT := OBJECT_CONSTRUCT();
      associate_index NUMBER;
   BEGIN
      associate_array := OBJECT_INSERT(associate_array, '1', OBJECT_INSERT(NVL(associate_array['1'], OBJECT_CONSTRUCT()), 'col1', -1, true), true);
      associate_array := OBJECT_INSERT(associate_array, '2', OBJECT_INSERT(NVL(associate_array['2'], OBJECT_CONSTRUCT()), 'col1', -2, true), true);
      associate_array := OBJECT_INSERT(associate_array, '3', OBJECT_INSERT(NVL(associate_array['3'], OBJECT_CONSTRUCT()), 'col1', -3, true), true);

      CALL DBMS_OUTPUT.PUT_LINE(:associate_array['1']:col1);
      
      associate_array := OBJECT_INSERT(associate_array, '1', OBJECT_INSERT(NVL(associate_array['1'], OBJECT_CONSTRUCT()), 'col1', -4, true), true);
    
      CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(OBJECT_KEYS(:associate_array)));
      
      FOR i IN 1 TO ARRAY_SIZE(OBJECT_KEYS(:associate_array))
      LOOP
         associate_index := OBJECT_KEYS(:associate_array)[:i-1];
         CALL DBMS_OUTPUT.PUT_LINE(:associate_array[:associate_index::VARCHAR]:col1);
      END LOOP;
   END;
$$;

CALL PUBLIC.record_associative_array();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
결과

DBMS OUTPUT

-1

3

-4

-2

-3

Known Issues

1. They are currently not being recognized

SnowConvert AI는 이러한 컬렉션을 중첩 테이블 배열로 처리합니다. 이 문제를 해결하기 위한 작업 항목이 있습니다.

관련 EWIs

관련 EWIs 없음.

수집 방법

Oracle 컬렉션 메서드를 Snowflake Scripting으로 변환하기 위한 변환 참조

경고

이 섹션은 진행 중인 작업이며 향후 정보가 변경될 수 있습니다

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

설명

컬렉션 메서드는 PL/SQL 하위 프로그램으로, 컬렉션에 대한 정보를 반환하는 함수 또는 컬렉션에서 작업하는 프로시저입니다. 수집 방법을 사용하면 컬렉션을 더 쉽게 사용할 수 있고 애플리케이션을 더 쉽게 유지 관리할 수 있습니다.

(Oracle PL/SQL Language Reference COLLECTION METHODS)

이러한 메서드 중 일부는 네이티브 Snowflake 반정형 작업에 매핑할 수 있습니다. 할 수 없거나 차이가 있는 항목은 UDF 구현에 매핑됩니다.

현재 SnowConvert AI 지원

다음 테이블은 SnowConvert AI 도구에서 제공하는 현재 지원에 대한 요약을 보여줍니다. 변환이 아직 최종 버전이 아닐 수 있으며 더 많은 작업이 필요할 수 있습니다.

메서드

현재 인식 상태

현재 변환 상태

매핑 대상

DELETE

인식되지 않음.

변환되지 않음.

UDF

TRIM

인식되지 않음.

변환되지 않음.

UDF(정의 예정)

EXTEND

인식되지 않음.

변환되지 않음.

UDF

EXISTS

인식되지 않음.

변환되지 않음.

ARRAY_CONTAINS

FIRST

인식되지 않음.

변환되지 않음.

UDF

LAST

인식되지 않음.

변환되지 않음.

UDF

COUNT

인식되지 않음.

변환되지 않음.

ARRAY_SIZE

LIMIT

인식되지 않음.

변환되지 않음.

지원되지 않음.

PRIOR

인식되지 않음.

변환되지 않음.

UDF(정의 예정)

NEXT

인식되지 않음.

변환되지 않음.

UDF(정의 예정)

샘플 소스 패턴

COUNT

이 메서드는 컬렉션 내에서 “정의되지 않은”(null과 혼동하지 말 것) 요소의 수를 반환합니다(중첩된 테이블은 이러한 요소를 사이에 두고 희박해질 수 있음). 연관 배열에서는 배열의 키 수를 반환합니다.

Oracle
CREATE OR REPLACE PROCEDURE collection_count
IS
    TYPE varray_typ IS VARRAY(5) OF INTEGER;
    TYPE nt_typ IS TABLE OF INTEGER;
    TYPE aa_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(20);
    
    associative_array aa_typ := aa_typ('abc'=>1, 'bca'=>1);
    varray_variable varray_typ := varray_typ(1, 2, 3);
    nt_variable nt_typ := nt_typ(1, 2, 3, 4);
BEGIN
    DBMS_OUTPUT.PUT_LINE(associative_array.COUNT);
    DBMS_OUTPUT.PUT_LINE(varray_variable.COUNT);
    DBMS_OUTPUT.PUT_LINE(nt_variable.COUNT);
END;

CALL collection_count();
Copy
결과

DBMS OUTPUT

2

3

4

Snowflake

이에 상응하는 Snowflake 메서드는 ARRAY_SIZE 메서드입니다.

CREATE OR REPLACE PROCEDURE PUBLIC.collection_count()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    associative_array OBJECT := OBJECT_CONSTRUCT('abc', 1, 'bca', 1);
    varray_variable ARRAY := ARRAY_CONSTRUCT(1, 2, 3);
    nt_variable ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
BEGIN
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(OBJECT_KEYS(:associative_array)));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(:varray_variable));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(:nt_variable));
END;
$$;

CALL PUBLIC.collection_count();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
결과

DBMS OUTPUT

2

3

4

EXISTS

이 메서드는 지정된 요소가 컬렉션에 포함되어 있으면 true를 반환합니다. 연관 배열에서는 키가 포함되어 있는지 테스트합니다.

Oracle
CREATE OR REPLACE PROCEDURE collection_exists
IS
    TYPE nt_typ IS TABLE OF INTEGER;
    TYPE aa_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(20);
    
    associative_array aa_typ := aa_typ('abc'=>1, 'bca'=>1);
    nt_variable nt_typ := nt_typ(1, 2, 3, 4);
BEGIN
    IF associative_array.EXISTS('abc')
    THEN DBMS_OUTPUT.PUT_LINE('Found');
    END IF;
    
    IF NOT associative_array.EXISTS('not found')
    THEN DBMS_OUTPUT.PUT_LINE('Not found');
    END IF;
    
    IF nt_variable.EXISTS(1)
    THEN DBMS_OUTPUT.PUT_LINE('Found');
    END IF;
    
    IF NOT nt_variable.EXISTS(5)
    THEN DBMS_OUTPUT.PUT_LINE('Not found');
    END IF;
END;
/

CALL collection_exists();
Copy
결과

DBMS OUTPUT

2

3

4

Snowflake

이에 상응하는 Snowflake 메서드는 ARRAY_CONTAINS 메서드입니다. varchar 요소를 사용할 때는 베리언트로 형 변환해야 한다는 점에 유의하십시오.

CREATE OR REPLACE PROCEDURE PUBLIC.collection_exists()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    associative_array OBJECT := OBJECT_CONSTRUCT('abc', 1, 'bca', 1);
    nt_variable ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
BEGIN
    IF (ARRAY_CONTAINS('abc'::VARIANT, OBJECT_KEYS(associative_array)))
    THEN CALL DBMS_OUTPUT.PUT_LINE('Found');
    END IF;
    
    IF (NOT ARRAY_CONTAINS('not found'::VARIANT, OBJECT_KEYS(associative_array)))
    THEN CALL DBMS_OUTPUT.PUT_LINE('Not found');
    END IF;
    
    IF (ARRAY_CONTAINS(1, nt_variable))
    THEN CALL DBMS_OUTPUT.PUT_LINE('Found');
    END IF;
    
    IF (NOT ARRAY_CONTAINS(5, nt_variable))
    THEN CALL DBMS_OUTPUT.PUT_LINE('Not found');
    END IF;
END;
$$;

CALL PUBLIC.collection_exists();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
결과

DBMS OUTPUT

2

3

4

FIRST/LAST

이 두 메서드는 각각 컬렉션의 첫 번째/마지막 요소를 반환합니다. 컬렉션이 비어 있으면 null을 반환합니다. 이 작업은 UDF 에 매핑되며, 이는 향후 개정에 추가될 예정입니다.

Oracle
CREATE OR REPLACE PROCEDURE collection_first_last
IS
    TYPE nt_typ IS TABLE OF INTEGER;
    TYPE aa_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(20);
    
    associative_array aa_typ := aa_typ('abc'=>1, 'bca'=>1);
    nt_variable nt_typ := nt_typ();
BEGIN
    DBMS_OUTPUT.PUT_LINE(associative_array.FIRST);
    DBMS_OUTPUT.PUT_LINE(associative_array.LAST);
    
    DBMS_OUTPUT.PUT_LINE(nt_variable.FIRST);
    DBMS_OUTPUT.PUT_LINE(nt_variable.LAST);
    nt_variable := nt_typ(1, 2, 3, 4);
    DBMS_OUTPUT.PUT_LINE(nt_variable.FIRST);
    DBMS_OUTPUT.PUT_LINE(nt_variable.LAST);
END;
/

CALL collection_first_last();
Copy
결과

DBMS OUTPUT

abc

bca

–null로 평가되기 때문에 이러한 빈 공간이 발생함

1

4

Snowflake
CREATE OR REPLACE PROCEDURE PUBLIC.collection_first_last()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    associative_array OBJECT := OBJECT_CONSTRUCT('abc', 1, 'bca', 1);
    nt_variable ARRAY := ARRAY_CONSTRUCT();
BEGIN
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_FIRST(:associative_array));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_LAST(:associative_array));
    
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_FIRST(:nt_variable));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_LAST(:nt_variable));
    nt_variable := ARRAY_CONSTRUCT(1, 2, 3, 4);
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_FIRST(:nt_variable));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_LAST(:nt_variable));
END;
$$;

CALL PUBLIC.collection_first_last();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
UDFs
CREATE OR REPLACE FUNCTION ARRAY_FIRST(array_variable VARIANT)
RETURNS VARIANT
LANGUAGE SQL
AS
$$
    IFF (IS_OBJECT(array_variable),
        ARRAY_FIRST(OBJECT_KEYS(array_variable)),
        IFF (ARRAY_SIZE(array_variable) = 0, null, array_variable[0]))
$$;

CREATE OR REPLACE FUNCTION ARRAY_LAST(array_variable VARIANT)
RETURNS VARIANT
LANGUAGE SQL
AS
$$
    IFF (IS_OBJECT(array_variable),
        ARRAY_LAST(OBJECT_KEYS(array_variable)),
        IFF (ARRAY_SIZE(array_variable) = 0, null, array_variable[ARRAY_SIZE(array_variable)-1]))
$$;
Copy
결과

DBMS OUTPUT

abc

bca

–null로 평가되기 때문에 이러한 빈 공간이 발생함

1

4

DELETE

이 메서드는 컬렉션에서 요소를 제거하는 데 사용됩니다. 세 가지 베리언트가 있습니다.

  • .DELETE 는 모든 요소를 제거합니다.

  • .DELETE(n)은 인덱스가 ‘n’과 일치하는 요소를 제거합니다.

  • .DELETE(n, m)은 인덱스에서 ‘n’부터 ‘m’까지 제거합니다.

참고

Oracle에서 중첩된 테이블에 이 작업을 사용하면 테이블이 희소하기 때문에 그 안에 “정의되지 않은” 요소가 생깁니다.

경고

두 번째 및 세 번째 버전은 Varray에는 적용되지 않습니다.

Oracle

이 샘플은 단순화를 위해 요소 수만 확인하지만 각 컬렉션의 내용을 표시하도록 수정할 수 있습니다.

CREATE OR REPLACE PROCEDURE collection_delete
IS
    TYPE varray_typ IS VARRAY(5) OF INTEGER;
    TYPE nt_typ IS TABLE OF INTEGER;
    TYPE aa_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(20);
    
    associative_array1 aa_typ := aa_typ('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    associative_array2 aa_typ := aa_typ('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    associative_array3 aa_typ := aa_typ('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    
    varray_variable1 varray_typ := varray_typ(1, 2, 3, 4);
    
    nt_variable1 nt_typ := nt_typ(1, 2, 3, 4);
    nt_variable2 nt_typ := nt_typ(1, 2, 3, 4);
    nt_variable3 nt_typ := nt_typ(1, 2, 3, 4);
BEGIN
    varray_variable1.DELETE;--delete everything
    
    nt_variable1.DELETE;--delete everything
    nt_variable2.DELETE(2);--delete second position
    nt_variable3.DELETE(2, 3);--delete range
    
    associative_array1.DELETE;--delete everything
    associative_array2.DELETE('def');--delete second position
    associative_array3.DELETE('def', 'jkl');--delete range
    
    DBMS_OUTPUT.PUT_LINE(varray_variable1.COUNT);
    DBMS_OUTPUT.PUT_LINE(nt_variable1.COUNT);
    DBMS_OUTPUT.PUT_LINE(nt_variable2.COUNT);
    DBMS_OUTPUT.PUT_LINE(nt_variable3.COUNT);
    
    DBMS_OUTPUT.PUT_LINE(associative_array1.COUNT);
    DBMS_OUTPUT.PUT_LINE(associative_array2.COUNT);
    DBMS_OUTPUT.PUT_LINE(associative_array3.COUNT);
END;
/

CALL collection_delete();
Copy
결과

DBMS OUTPUT

0

0

3

2

0

3

1

Snowflake

Snowflake는 기존 ARRAY 에서 삭제를 지원하지 않으므로 제공되는 유일한 해결 방법은 DELETE 의 원래 매개 변수에 따라 새 ARRAY 를 다시 작성하는 것입니다.

참고

요소 업데이트 기능을 구현하기 위해 UDF 가 추가되었습니다.

이 UDF 는 추후 개정에 추가될 예정입니다.

CREATE OR REPLACE PROCEDURE PUBLIC.collection_delete()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    associative_array1 OBJECT := OBJECT_CONSTRUCT('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    associative_array2 OBJECT := OBJECT_CONSTRUCT('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    associative_array3 OBJECT := OBJECT_CONSTRUCT('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    
    varray_variable1 ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
    
    nt_variable1 ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
    nt_variable2 ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
    nt_variable3 ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
BEGIN
    varray_variable1 := ARRAY_CONSTRUCT();--delete everything
    
    nt_variable1 := ARRAY_CONSTRUCT();--delete everything
    nt_variable2 := ARRAY_DELETE_UDF(nt_variable2, 2);--delete second position
    nt_variable3 := ARRAY_DELETE_UDF(nt_variable3, 2, 3);--delete range
    
    associative_array1 := OBJECT_CONSTRUCT();--delete everything
    associative_array2 := ASSOCIATIVE_ARRAY_DELETE_UDF('def');--delete second position
    associative_array3 := ASSOCIATIVE_ARRAY_DELETE_UDF('def', 'jkl');--delete range
    
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(varray_variable1));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(nt_variable1);
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(nt_variable2);
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(nt_variable3);
    
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(associative_array1));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(associative_array2));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(associative_array3));
END;
$$;

CALL PUBLIC.collection_first_last();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
결과

DBMS OUTPUT

0

0

3

2

0

3

1

EXTEND

이 메서드는 중첩된 테이블 또는 배열에 새 요소를 추가하는 데 사용됩니다. 세 가지 베리언트가 있습니다.

  • .EXTEND 는 null 요소를 삽입합니다.

  • .EXTEND(n)은 ‘n’개의 null 요소를 삽입합니다.

  • .EXTEND(n, i)는 ‘i’에 요소의 복사본 ‘n’개를 삽입합니다.

Oracle
CREATE OR REPLACE PROCEDURE collection_extend
IS 
    TYPE varray_typ IS VARRAY(5) OF INTEGER;
    TYPE nt_typ IS TABLE OF INTEGER;
    
    nt_variable1 nt_typ := nt_typ(1, 2, 3, 4);
    varray_variable1 varray_typ := varray_typ(1, 2, 3);
    varray_variable2 varray_typ := varray_typ(1, 2, 3);
BEGIN
    nt_variable1.EXTEND;
    varray_variable1.EXTEND(2);
    varray_variable2.EXTEND(2, 1);
    
    DBMS_OUTPUT.PUT_LINE(nt_variable1.COUNT);
    DBMS_OUTPUT.PUT_LINE(varray_variable1.COUNT);
    DBMS_OUTPUT.PUT_LINE(varray_variable2.COUNT);
END;
/

CALL collection_extend();
Copy
결과

DBMS OUTPUT

5

5

5

Snowflake

참고

요소 업데이트 기능을 구현하기 위해 UDF 가 추가되었습니다.

이 UDF 는 추후 개정에 추가될 예정입니다.

CREATE OR REPLACE PROCEDURE PUBLIC.collection_first_last()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    nt_variable1 ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
    varray_variable1 ARRAY := ARRAY_CONSTRUCT(1, 2, 3);
    varray_variable2 ARRAY := ARRAY_CONSTRUCT(1, 2, 3);
BEGIN
    nt_variable1 := ARRAY_EXTEND_UDF(nt_variable);
    varray_variable1 := ARRAY_EXTEND_UDF(varray_variable1, 2);
    varray_variable2 := ARRAY_EXTEND_UDF(varray_variable2, 2, 1);
    
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(nt_variable1);
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(varray_variable1));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(varray_variable2));
END;
$$;

CALL PUBLIC.collection_first_last();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
결과

DBMS OUTPUT

5

5

5

TRIM

이 메서드는 중첩된 테이블 또는 배열에서 마지막 요소를 제거하는 데 사용됩니다. 두 가지 베리언트가 있습니다.

  • .TRIM 은 마지막 요소를 제거합니다.

  • .TRIM(n)은 마지막 ‘n’ 요소를 제거합니다.

참고

이 기능은 ARRAY_SLICE 를 사용하여 구현할 수 있습니다.

Oracle
CREATE OR REPLACE PROCEDURE collection_trim
IS 
    TYPE varray_typ IS VARRAY(5) OF INTEGER;
    TYPE nt_typ IS TABLE OF INTEGER;
    
    varray_variable1 varray_typ := varray_typ(1, 2, 3);
    nt_variable1 nt_typ := nt_typ(1, 2, 3, 4);
BEGIN
    varray_variable1.TRIM;
    nt_variable1.TRIM(2);
    
    DBMS_OUTPUT.PUT_LINE(nt_variable1.COUNT);
    DBMS_OUTPUT.PUT_LINE(varray_variable1.COUNT);
END;
/

CALL collection_trim();
Copy
결과
DBMS OUTPUT
-----------
2
2

Copy

LIMIT

이 메서드는 Varray의 최대 제한을 반환합니다.

위험

이 방법은 Snowflake에서 지원되지 않습니다.

Oracle
CREATE OR REPLACE PROCEDURE collection_limit
IS 
    TYPE varray_typ1 IS VARRAY(5) OF INTEGER;
    TYPE varray_typ2 IS VARRAY(6) OF INTEGER;
    
    varray_variable1 varray_typ1 := varray_typ1(1, 2, 3);
    varray_variable2 varray_typ2 := varray_typ2(1, 2, 3, 4);
BEGIN
    DBMS_OUTPUT.PUT_LINE(varray_variable1.LIMIT);
    DBMS_OUTPUT.PUT_LINE(varray_variable2.LIMIT);
END;
/

CALL collection_limit();
Copy
결과

DBMS OUTPUT

5

6

PRIOR/NEXT

이 메서드는 인덱스가 주어지면 이전/다음 인덱스를 반환합니다. 이전/다음 항목이 없으면 null을 반환합니다. 컬렉션을 탐색하는 데 가장 자주 사용됩니다.

Oracle
CREATE OR REPLACE PROCEDURE collection_prior_next
IS 
    TYPE varray_typ1 IS VARRAY(5) OF INTEGER;
    TYPE aa_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(20);
    
    varray_variable1 varray_typ1 := varray_typ1(-1, -2, -3);
    associative_array1 aa_typ := aa_typ('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
BEGIN
    DBMS_OUTPUT.PUT_LINE(varray_variable1.PRIOR(1));
    DBMS_OUTPUT.PUT_LINE(varray_variable1.PRIOR(2));
    DBMS_OUTPUT.PUT_LINE(varray_variable1.NEXT(2));
    DBMS_OUTPUT.PUT_LINE(varray_variable1.NEXT(3));
    
    DBMS_OUTPUT.PUT_LINE(associative_array1.PRIOR('abc'));
    DBMS_OUTPUT.PUT_LINE(associative_array1.PRIOR('def'));
    DBMS_OUTPUT.PUT_LINE(associative_array1.NEXT('ghi'));
    DBMS_OUTPUT.PUT_LINE(associative_array1.NEXT('jkl'));
    DBMS_OUTPUT.PUT_LINE(associative_array1.PRIOR('not found'));
END;
/

CALL collection_prior_next();
Copy
결과

DBMS OUTPUT

– null 결과로 인해 공백이 발생함

1

3

abc

jkl

jkl

Known Issues

1. Limit method is not supported in Snowflake

Snowflake는 제한된 공간 배열을 지원하지 않습니다. 이러한 이유로 이 방법은 지원되지 않습니다.

관련 EWIs

EWIs 관련 없음.

중첩된 테이블 배열 유형 정의

이는 Oracle 중첩 테이블 배열 선언을 Snowflake로 변환하기 위한 변환 참조입니다.

경고

이 섹션은 진행 중인 작업으로 향후 정보가 변경될 수 있습니다.

참고

이 섹션은 중첩 테이블 배열의 PL/SQL 버전입니다. 독립 실행형 버전의 경우 중첩 테이블 유형 정의를 참조하세요.

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

설명

데이터베이스에서 중첩된 테이블은 특정 순서 없이 지정되지 않은 수의 행을 저장하는 열 유형입니다.

데이터베이스에서 PL/SQL 중첩 테이블 변수로 중첩된 테이블 값을 검색하면 PL/SQL 은 행에 1부터 시작하여 연속 인덱스를 부여합니다. 이러한 인덱스를 사용하면 중첩된 테이블 변수의 개별 행에 액세스할 수 있습니다. 구문은 variable_name(index) 입니다. 데이터베이스에서 중첩된 테이블을 저장하고 검색할 때 중첩된 테이블의 인덱스와 행 순서가 안정적으로 유지되지 않을 수 있습니다.

(Oracle PL/SQL Language Reference NESTED TABLES)

변환의 경우, 유형 정의가 ARRAY 반정형 데이터 타입 으로 대체된 후 모든 작업에서 그 용도가 그에 따라 변경됩니다. 중첩 테이블과 배열의 변환이 어떻게 동일한지 참고하십시오.

중첩된 테이블 배열 유형을 정의하는 구문은 다음과 같습니다.

type_definition := TYPE IS TABLE OF datatype;

Copy

이 유형의 변수를 선언하려면:

variable_name collection_type;

Copy

샘플 소스 패턴

중첩된 테이블 배열 정의

서로 다른 중첩된 테이블 배열을 생성하는 방법과 변수에 대한 정의를 마이그레이션하는 방법을 설명합니다.

Oracle
CREATE OR REPLACE PROCEDURE nested_table_procedure
IS
    TYPE nested_table_array_typ IS TABLE OF INTEGER;
    TYPE nested_table_array_typ2 IS TABLE OF DATE;
    
    nested_table_array nested_table_array_typ;
    nested_table_array2 nested_table_array_typ2;
BEGIN
    NULL;
END;
Copy
Snowflake
CREATE OR REPLACE PROCEDURE nested_table_procedure()
RETURNS INTEGER
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    -- NO LONGER NEEDED
    /*
    TYPE associative_array_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(30);
    TYPE associative_array_typ2 IS TABLE OF INTEGER INDEX BY PLS_INTEGER;
    */
    
    associative_array ARRAY;
    associative_array2 ARRAY;
BEGIN
    NULL;
END;
$$;
Copy

중첩된 테이블 반복

Oracle
CREATE OR REPLACE PROCEDURE nested_table_iteration
IS
    TYPE nested_table_typ IS TABLE OF INTEGER;
    nested_table_variable nested_table_typ := nested_table_typ (10, 20, 30);
BEGIN
    FOR i IN 1..nested_table_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(nested_table_variable(i));
    END LOOP;
    
    nested_table_variable (1) := 40;
    
    FOR i IN 1..nested_table_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(nested_table_variable(i));
    END LOOP;
END;
/

CALL nested_table_iteration();
Copy
결과

DBMS OUTPUT

10

20

30

40

20

30

Snowflake

참고

요소 업데이트 기능을 구현하기 위해 UDF 가 추가되었습니다.

이 UDF 는 추후 개정에 추가될 예정입니다.

CREATE OR REPLACE PROCEDURE PUBLIC.nested_table_iteration()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    nested_table_variable ARRAY := ARRAY_CONSTRUCT(10, 20, 30);
BEGIN
    FOR i IN 1 TO ARRAY_SIZE(nested_table_variable)
    LOOP
        CALL DBMS_OUTPUT.PUT_LINE(:nested_table_variable[:i-1]);
    END LOOP;

    nested_table_variable:= INSERT_REPLACE_COLLECTION_ELEMENT_UDF(nested_table_variable, 1, 40);
    
    FOR i IN 1 TO ARRAY_SIZE(nested_table_variable)
    LOOP
        CALL DBMS_OUTPUT.PUT_LINE(:nested_table_variable[:i-1]);
    END LOOP;
END;
$$;

CALL PUBLIC.nested_table_iteration();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
UDF
CREATE OR REPLACE FUNCTION PUBLIC.INSERT_REPLACE_COLLECTION_ELEMENT_UDF(varray ARRAY, position INTEGER, newValue VARIANT)
RETURNS ARRAY
LANGUAGE SQL
AS
$$
    ARRAY_CAT(
        ARRAY_APPEND(ARRAY_SLICE(varray, 0, (position)-1), newValue),
        ARRAY_SLICE(varray, position, ARRAY_SIZE(varray)))
$$;
Copy
결과

DBMS OUTPUT

10

20

30

40

20

30

Known Issues

1. They are currently not being converted

SnowConvert AI는 이러한 요소의 변환을 지원하지 않습니다.

2. Indexing needs to be modified

Oracle의 인덱스는 1부터 시작하지만, Snowflake에서는 0부터 시작합니다.

관련 EWIs

EWIs 관련 없음.

레코드 유형 정의

Oracle 레코드 선언을 Snowflake로 변환하기 위한 변환 참조

경고

이 섹션은 진행 중인 작업으로 향후 정보가 변경될 수 있습니다.

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

설명

레코드 변수는 필드라고 하는 내부 구성 요소가 서로 다른 데이터 타입을 가질 수 있는 복합 변수입니다. 레코드 변수의 값과 해당 필드의 값은 변경될 수 있습니다.

전체 레코드 변수를 이름으로 참조합니다. 레코드 필드는 record.field 구문으로 참조할 수 있습니다.

다음 중 한 가지 방법으로 레코드 변수를 생성할 수 있습니다.

  • 레코드 유형을 정의한 다음 해당 유형의 변수를 선언합니다.

  • %ROWTYPE 을 사용하여 데이터베이스 테이블 또는 뷰의 전체 또는 일부 행을 나타내는 레코드 변수를 선언합니다.

  • %TYPE 을 사용하여 이전에 선언한 레코드 변수와 동일한 유형의 레코드 변수를 선언합니다.

(Oracle PL/SQL Language Reference RECORD VARIABLES)

변환의 경우, 유형 정의가 OBJECT 반정형 데이터 타입 으로 대체된 후 모든 작업에서 그 용도가 그에 따라 변경됩니다.

레코드 유형을 정의하는 구문은 다음과 같습니다.

type_definition := TYPE IS RECORD ( field_definition [, field_definition...] );

field_definition := field_name datatype [ { [NOT NULL default ] | default } ]

default := [ { := | DEFAULT } expression]

Copy

이 유형의 변수를 선언하려면:

variable_name { record_type
              | rowtype_attribute
              | record_variable%TYPE
              };

Copy

샘플 소스 패턴

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

레코드 초기화 및 할당

이 샘플은 프로시저 중간에 재할당되는 레코드 변수를 사용하여 2개의 새 행을 삽입하려고 시도합니다.

Oracle
CREATE TABLE record_table(col1 FLOAT, col2 INTEGER);

CREATE OR REPLACE PROCEDURE record_procedure
IS
    TYPE record_typ IS RECORD(col1 INTEGER, col2 FLOAT);
    record_variable record_typ := record_typ(1, 1.5);--initialization
BEGIN
    INSERT INTO record_table(col1, col2)
        VALUES (record_variable.col2, record_variable.col1);--usage
        
    --reassignment of properties
    record_variable.col1 := 2;
    record_variable.col2 := 2.5;
    
    INSERT INTO record_table(col1, col2)
        VALUES (record_variable.col2, record_variable.col1);--usage
END;

CALL record_procedure();
SELECT * FROM record_table;
Copy
결과

COL1

COL2

1.5

1

2.5

2

Snowflake

재할당이 열이 이미 존재하는 경우 업데이트되는 OBJECT_INSERT 로 대체되는 방식과 VALUES 절이 SELECT 로 대체되는 방식에 주목하십시오.

CREATE OR REPLACE TABLE record_table (col1 FLOAT,
    col2 INTEGER)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE record_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        !!!RESOLVE EWI!!! /*** SSC-EWI-0056 - CUSTOM TYPES ARE NOT SUPPORTED IN SNOWFLAKE BUT REFERENCES TO THIS CUSTOM TYPE WERE CHANGED TO OBJECT ***/!!!
        TYPE record_typ IS RECORD(col1 INTEGER, col2 FLOAT);
        record_variable OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - record_typ DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT('COL1', 1, 'COL2', 1.5);--initialization

    BEGIN
        INSERT INTO record_table(col1, col2)
        SELECT
            :record_variable:COL2,
            :record_variable:COL1;--usage

        --reassignment of properties
        record_variable := OBJECT_INSERT(record_variable, 'COL1', 2, true);
        record_variable := OBJECT_INSERT(record_variable, 'COL2', 2.5, true);

        INSERT INTO record_table(col1, col2)
        SELECT
            :record_variable:COL2,
            :record_variable:COL1;--usage

    END;
$$;

CALL record_procedure();

SELECT * FROM
    record_table;
Copy
결과

COL1

COL2

1.5

1

2.5

2

%ROWTYPE Record and Values Record

연산는 구조를 정의하는 연산이므로 이러한 정의는 OBJECT 데이터 타입으로 대체할 수 있지만, 레코드를 ‘있는 그대로’ 삽입하는 기능은 지원되지 않으므로 레코드의 값을 분해해야 합니다.

Oracle
CREATE TABLE record_table(col1 INTEGER, col2 VARCHAR2(50), col3 DATE);
CREATE OR REPLACE PROCEDURE insert_record
IS
    record_variable record_table%ROWTYPE;
BEGIN
    record_variable.col1 := 1;
    record_variable.col2 := 'Hello';
    record_variable.col3 := DATE '2020-12-25';
    
    INSERT INTO record_table VALUES record_variable;
END;

CALL insert_record();
SELECT * FROM record_table;
Copy
결과

COL1

COL2

COL3

1

“Hello”

25-DEC-20

Snowflake

마지막으로 OBJECT 변수를 초기화해야 정보를 추가할 수 있다는 점에 유의하십시오.

CREATE OR REPLACE TABLE record_table (col1 INTEGER,
    col2 VARCHAR(50),
    col3 TIMESTAMP /*** SSC-FDM-OR0042 - DATE TYPE COLUMN HAS A DIFFERENT BEHAVIOR IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE insert_record ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        record_variable OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - ROWTYPE DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT();
    BEGIN
        record_variable := OBJECT_INSERT(record_variable, 'COL1', 1, true);
        record_variable := OBJECT_INSERT(record_variable, 'COL2', 'Hello', true);
        record_variable := OBJECT_INSERT(record_variable, 'COL3', DATE '2020-12-25', true);
        INSERT INTO record_table
        SELECT
            :record_variable:COL1,
            :record_variable:COL2,
            :record_variable:COL3;
    END;
$$;

CALL insert_record();

SELECT * FROM
    record_table;
Copy
결과

COL1

COL2

COL3

1

“Hello”

25-DEC-20

레코드로 데이터 가져오기

Oracle
CREATE TABLE record_table(col1 INTEGER, col2 VARCHAR2(50), col3 DATE);
INSERT INTO record_table(col1, col2 , col3)
    VALUES (1, 'Hello', DATE '2020-12-25');

CREATE OR REPLACE PROCEDURE load_cursor_record
IS
    CURSOR record_cursor IS
        SELECT *
        FROM record_table;
        
    record_variable record_cursor%ROWTYPE;
BEGIN
    OPEN record_cursor;
    LOOP
        FETCH record_cursor INTO record_variable;
        EXIT WHEN record_cursor%NOTFOUND;
        
        DBMS_OUTPUT.PUT_LINE(record_variable.col1);
        DBMS_OUTPUT.PUT_LINE(record_variable.col2);
        DBMS_OUTPUT.PUT_LINE(record_variable.col3);
    END LOOP;
    CLOSE record_cursor;
END;

CALL load_cursor_record();
Copy
결과

DBMS OUTPUT

1

Hello

25-DEC-20

Snowflake

커서 정의에 OBJECT_CONSTRUCT 를 추가하면 OBJECT 를 추출할 수 있으며, 이를 통해 FETCH 문을 원활하게 마이그레이션할 수 있습니다.

CREATE OR REPLACE TABLE record_table (col1 INTEGER,
    col2 VARCHAR(50),
    col3 TIMESTAMP /*** SSC-FDM-OR0042 - DATE TYPE COLUMN HAS A DIFFERENT BEHAVIOR IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
;

INSERT INTO record_table(col1, col2 , col3)
    VALUES (1, 'Hello', DATE '2020-12-25');

CREATE OR REPLACE PROCEDURE load_cursor_record ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        --** SSC-PRF-0009 - PERFORMANCE REVIEW - CURSOR USAGE **
        record_cursor CURSOR
        FOR
            SELECT
                OBJECT_CONSTRUCT( *) sc_cursor_record
            FROM
                record_table;
    record_variable OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - ROWTYPE DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT();
    BEGIN
        OPEN record_cursor;
        --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
    LOOP
            --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        FETCH record_cursor INTO
                :record_variable;
        IF (record_variable IS NULL) THEN
                EXIT;
        END IF;
        --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
        CALL DBMS_OUTPUT.PUT_LINE_UDF(:record_variable:COL1);
        --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
        CALL DBMS_OUTPUT.PUT_LINE_UDF(:record_variable:COL2);
        --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
        CALL DBMS_OUTPUT.PUT_LINE_UDF(:record_variable:COL3::DATE);
    END LOOP;
    CLOSE record_cursor;
    END;
$$;

CALL load_cursor_record();
Copy
결과

DBMS OUTPUT

1

Hello

25-DEC-20

SELECT INTO 에 레코드 변수 할당하기

이 변환은 OBJECT_CONTRUCT 함수를 활용해 SELECT 열을 인자로 레코드를 초기화하는 방식으로 구성됩니다.

샘플 보조 코드

Oracle
create table sample_table(ID number, NAME varchar2(23));
CREATE TABLE RESULTS (COL1 VARCHAR(20), COL2 VARCHAR(40));
insert into sample_table values(1, 'NAME 1');
insert into sample_table values(2, 'NAME 2');
insert into sample_table values(3, 'NAME 3');
insert into sample_table values(4, 'NAME 4');
Copy
Snowflake
CREATE OR REPLACE TABLE sample_table (ID NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
NAME VARCHAR(23))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE TABLE RESULTS (COL1 VARCHAR(20),
COL2 VARCHAR(40))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

insert into sample_table
values(1, 'NAME 1');

insert into sample_table
values(2, 'NAME 2');

insert into sample_table
values(3, 'NAME 3');

insert into sample_table
values(4, 'NAME 4');
Copy
Oracle
CREATE OR REPLACE PROCEDURE sp_sample1 AS
-- Rowtype variable
rowtype_variable sample_table%rowtype;

--Record variable
TYPE record_typ_def IS RECORD(ID number, NAME varchar2(23));
record_variable_def record_typ_def;

-- Auxiliary variable
name_var VARCHAR(20);
BEGIN
   SELECT * INTO rowtype_variable FROM sample_table WHERE ID = 1 FETCH NEXT 1 ROWS ONLY;
   name_var := rowtype_variable.NAME;
   INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 1', name_var);
  
   SELECT ID, NAME INTO rowtype_variable FROM sample_table WHERE ID = 2 FETCH NEXT 1 ROWS ONLY;
   name_var := rowtype_variable.NAME;
   INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 2', name_var);
  
   SELECT * INTO record_variable_def FROM sample_table WHERE ID = 3 FETCH NEXT 1 ROWS ONLY;
   name_var := record_variable_def.NAME;
   INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 3', name_var);
  
   SELECT ID, NAME INTO record_variable_def FROM sample_table WHERE ID = 4 FETCH NEXT 1 ROWS ONLY;
   name_var := record_variable_def.NAME;
   INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 4', name_var);
END;


call sp_sample1();

SELECT * FROM results;
Copy
결과

COL1

COL2

SELECT 1

NAME 1

SELECT 2

NAME 2

SELECT 3

NAME 3

SELECT 4

NAME 4

Snowflake
CREATE OR REPLACE PROCEDURE sp_sample1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
   DECLARE
      -- Rowtype variable
      rowtype_variable OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - ROWTYPE DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT();

      --Record variable
      !!!RESOLVE EWI!!! /*** SSC-EWI-0056 - CUSTOM TYPES ARE NOT SUPPORTED IN SNOWFLAKE BUT REFERENCES TO THIS CUSTOM TYPE WERE CHANGED TO OBJECT ***/!!!
      TYPE record_typ_def IS RECORD(ID number, NAME varchar2(23));
      record_variable_def OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - record_typ_def DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT();

      -- Auxiliary variable
      name_var VARCHAR(20);
   BEGIN
      SELECT
         OBJECT_CONSTRUCT( *) INTO
         :rowtype_variable
      FROM
         sample_table
      WHERE ID = 1
      FETCH NEXT 1 ROWS ONLY;
      name_var := :rowtype_variable:NAME;
      INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 1', :name_var);

      SELECT
         OBJECT_CONSTRUCT()
      INTO
         :rowtype_variable
      FROM
         sample_table
      WHERE ID = 2
      FETCH NEXT 1 ROWS ONLY;
      name_var := :rowtype_variable:NAME;
      INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 2', :name_var);

      SELECT
         OBJECT_CONSTRUCT( *) INTO
         :record_variable_def
      FROM
         sample_table
      WHERE ID = 3
      FETCH NEXT 1 ROWS ONLY;
      name_var := :record_variable_def:NAME;
      INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 3', :name_var);

      SELECT
         OBJECT_CONSTRUCT('ID', ID, 'NAME', NAME) INTO
         :record_variable_def
      FROM
         sample_table
      WHERE ID = 4
      FETCH NEXT 1 ROWS ONLY;
      name_var := :record_variable_def:NAME;
      INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 4', :name_var);
   END;
$$;

call sp_sample1();

SELECT * FROM
   results;
Copy
결과

COL1

COL2

SELECT 1

NAME 1

SELECT 2

NAME 2

SELECT 3

NAME 3

SELECT 4

NAME 4

Known Issues

1. The following functionalities are currently not being converted:

  • 레코드로 데이터 가져오기.

  • 중첩된 레코드(레코드 내 레코드).

  • 레코드 내부의 컬렉션.

관련 EWIs

  1. SSC-EWI-0036: 데이터 타입이 다른 데이터 타입으로 변환되었습니다.

  2. SSC-EWI-0056: 생성 유형이 지원되지 않음

  3. SSC-FDM-0006: 숫자 유형 열이 Snowflake에서 유사하게 동작하지 않을 수 있습니다.

  4. SSC-FDM-OR0042: 타임스탬프로 변환된 날짜 유형의 동작이 다릅니다.

  5. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE의 UDF구현 확인.

  6. SSC-PRF-0003: 루프 내부의 가져오기는 복잡한 패턴으로 간주되므로 Snowflake 성능을 저하시킬 수 있습니다.

varray 유형 정의

Oracle Varray 선언을 Snowflake로 변환하기 위한 변환 참조

경고

이 섹션은 진행 중인 작업으로 향후 정보가 변경될 수 있습니다.

참고

이 섹션은 Varray의 PL/SQL 버전입니다. 독립 실행형 버전의 경우 배열 테이블 유형 정의를 참조하세요.

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

설명

변수 배열(가변 크기 배열)은 요소의 수가 0(비어 있음)에서 선언된 최대 크기까지 다양할 수 있는 배열입니다.

Varray 변수의 요소에 액세스하려면 variable_name(index) 구문을 사용하십시오. 인덱스 의 하한은 1이고 상한은 현재 요소 수입니다. 상한은 요소를 추가하거나 삭제할 때 변경되지만 최대 크기를 초과할 수는 없습니다. 데이터베이스에서 varray를 저장하고 검색할 때 인덱스와 요소 순서는 안정적으로 유지됩니다.

(Oracle PL/SQL Language Reference VARRAYS)

변환의 경우, 유형 정의가 ARRAY 반정형 데이터 타입 으로 대체된 후 모든 작업에서 그 용도가 그에 따라 변경됩니다. 중첩 테이블과 배열의 변환이 어떻게 동일한지 참고하십시오.

Varray 유형을 정의하는 구문은 다음과 같습니다.

type_definition := { VARRAY | [VARYING] ARRAY } (size_limit) OF datatype
            [NOT NULL];

Copy

이 유형의 변수를 선언하려면:

variable_name collection_type;

Copy

샘플 소스 패턴

Varray 정의

변수를 생성하는 세 가지 방법과 변수에 대한 정의를 마이그레이션하는 방법을 설명합니다.

Oracle
CREATE OR REPLACE PROCEDURE associative_array_procedure
IS
    TYPE varray_typ IS ARRAY(10) OF INTEGER;
    TYPE varray_typ2 IS VARRAY(10) OF INTEGER;
    TYPE varray_typ3 IS VARYING ARRAY(10) OF INTEGER;

    array_variable varray_typ;
    array_variable2 varray_typ2;
    array_variable3 varray_typ3;
BEGIN
    NULL;
END;
Copy
Snowflake
CREATE OR REPLACE PROCEDURE associative_array_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
--        !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--        TYPE varray_typ IS ARRAY(10) OF INTEGER;
--        !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--        TYPE varray_typ2 IS VARRAY(10) OF INTEGER;
--        !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--        TYPE varray_typ3 IS VARYING ARRAY(10) OF INTEGER;

        array_variable VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'varray_typ' USAGE CHANGED TO VARIANT ***/!!!;
        array_variable2 VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'varray_typ2' USAGE CHANGED TO VARIANT ***/!!!;
        array_variable3 VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'varray_typ3' USAGE CHANGED TO VARIANT ***/!!!;
    BEGIN
        NULL;
    END;
$$;
Copy

varray 반복

Oracle
CREATE OR REPLACE PROCEDURE varray_iteration
IS
    TYPE varray_typ IS VARRAY(3) OF INTEGER;
    varray_variable varray_typ := varray_typ(10, 20, 30);
BEGIN
    FOR i IN 1..varray_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(varray_variable(i));
    END LOOP;
    
    varray_variable(1) := 40;
    
    FOR i IN 1..varray_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(varray_variable(i));
    END LOOP;
END;
/

CALL varray_iteration();
Copy
결과

DBMS OUTPUT

10

20

30

40

20

30

Snowflake

참고

요소 업데이트 기능을 구현하기 위해 UDF 가 추가되었습니다.

이 UDF 는 추후 개정에 추가될 예정입니다.

CREATE OR REPLACE PROCEDURE varray_iteration ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
--        !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--        TYPE varray_typ IS VARRAY(3) OF INTEGER;
        varray_variable VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'varray_typ' USAGE CHANGED TO VARIANT ***/!!! := varray_typ(10, 20, 30);
    BEGIN
        --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
        FOR i IN 1 TO 0 /*varray_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'VARRAY CUSTOM TYPE EXPRESSION' NODE ***/!!!
        --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
        LOOP
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            CALL DBMS_OUTPUT.PUT_LINE_UDF(varray_variable(i));
        END LOOP;
            !!!RESOLVE EWI!!! /*** SSC-EWI-OR0108 - THE FOLLOWING ASSIGNMENT STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
            varray_variable(1) := 40;
            --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
            FOR i IN 1 TO 0 /*varray_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'VARRAY CUSTOM TYPE EXPRESSION' NODE ***/!!!
            --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
               LOOP
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            CALL DBMS_OUTPUT.PUT_LINE_UDF(varray_variable(i));
               END LOOP;
    END;
$$;

CALL varray_iteration();
Copy
UDF
CREATE OR REPLACE FUNCTION PUBLIC.INSERT_REPLACE_COLLECTION_ELEMENT_UDF(varray ARRAY, position INTEGER, newValue VARIANT)
RETURNS ARRAY
LANGUAGE SQL
AS
$$
    ARRAY_CAT(
        ARRAY_APPEND(ARRAY_SLICE(varray, 0, (position)-1), newValue),
        ARRAY_SLICE(varray, position, ARRAY_SIZE(varray)))
$$;
Copy
결과

DBMS OUTPUT

10

20

30

40

20

30

Known Issues

1. They are currently not being converted

SnowConvert AI는 이러한 요소의 변환을 지원하지 않습니다.

2. Indexing needs to be modified

Oracle의 인덱스는 1부터 시작하지만, Snowflake에서는 0부터 시작합니다.

3. Array Density may not match the original

ARRAY 데이터 타입은 희소해질 수 있으므로 배열을 추가하거나 삭제할 때 주의를 기울여야 합니다. 밀도가 우려되는 경우 이러한 작업 후에 ARRAY_COMPACT()를 사용하면 도움이 될 수 있습니다.

관련 EWIs

  1. SSC-EWI-0058: 이 기능은 현재 Snowflake Scripting에서 지원되지 않습니다.

  2. SSC-EWI-0062: 사용자 지정 유형 사용법이 베리언트로 변경되었습니다.

  3. SSC-EWI-0073: 보류 중 함수 동등성 검토.

  4. SSC-EWI-OR0108: 다음 할당 문은 Snowflake Scripting에서 지원되지 않습니다.

  5. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE의 UDF구현 확인.

수집 대량 작업

Oracle 컬렉션 대량 작업을 Snowflake로 변환하기 위한 변환 참조

경고

이 섹션은 진행 중인 작업이며 향후 정보가 변경될 수 있습니다

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

설명

대량 SQL 의 기능인 BULK COLLECT 절은 SQL 에서 PL/SQL 로 결과를 한 번에 1개씩 반환하는 것이 아니라 일괄적으로 반환합니다.

BULK COLLECT 절은 다음에 표시될 수 있습니다.

  • SELECT INTO

  • FETCH

  • 다음의 RETURNING INTO 절:

    • DELETE

    • INSERT

    • UPDATE

    • EXECUTE IMMEDIATE

BULK COLLECT 절을 사용하면 앞의 각 문이 전체 결과 세트를 검색하여 단일 작업으로 1개 이상의 컬렉션 변수에 저장합니다(루프 문을 사용하여 한 번에 1개의 결과 행을 검색하는 것보다 더 효율적임).

(Oracle PL/SQL Language Reference BULK COLLECT CLAUSE)

이 섹션에는 Bulk가 포함된 SELECTs 및 FETCH Cursor 절에 대한 몇 가지 해결 방법이 나와 있습니다.

샘플 소스 패턴

원본 테이블

Oracle
CREATE TABLE bulk_collect_table(col1 INTEGER);

INSERT INTO bulk_collect_table VALUES(1);
INSERT INTO bulk_collect_table VALUES(2);
INSERT INTO bulk_collect_table VALUES(3);
INSERT INTO bulk_collect_table VALUES(4);
INSERT INTO bulk_collect_table VALUES(5);
INSERT INTO bulk_collect_table VALUES(6);
Copy
Snowflake
CREATE OR REPLACE TABLE bulk_collect_table (col1 INTEGER)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO bulk_collect_table
VALUES(1);

INSERT INTO bulk_collect_table
VALUES(2);

INSERT INTO bulk_collect_table
VALUES(3);

INSERT INTO bulk_collect_table
VALUES(4);

INSERT INTO bulk_collect_table
VALUES(5);

INSERT INTO bulk_collect_table
VALUES(6);
Copy

테이블에서 일괄 수집

Oracle
CREATE OR REPLACE PROCEDURE bulk_collect_procedure
IS
    CURSOR record_cursor IS
        SELECT *
        FROM bulk_collect_table;
        
    TYPE fetch_collection_typ IS TABLE OF record_cursor%ROWTYPE;
    fetch_collection_variable fetch_collection_typ;
    
    TYPE collection_typ IS TABLE OF bulk_collect_table%ROWTYPE;
    collection_variable collection_typ;
BEGIN
    SELECT * BULK COLLECT INTO collection_variable FROM bulk_collect_table;
    
    FOR i IN 1..collection_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(collection_variable(i).col1);
    END LOOP;
    
    collection_variable := null;
    OPEN record_cursor;
    FETCH record_cursor BULK COLLECT INTO collection_variable;
    CLOSE record_cursor;
    
    FOR i IN 1..collection_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(collection_variable(i).col1+6);
    END LOOP;
    
    collection_variable := null;
    EXECUTE IMMEDIATE 'SELECT * FROM bulk_collect_table' BULK COLLECT INTO collection_variable;
    
    FOR i IN 1..collection_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(collection_variable(i).col1+12);
    END LOOP;
END;
/

CALL bulk_collect_procedure();
Copy
결과

DBMS OUTPUT

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

Snowflake

위험

Bulk Collect가 포함된 EXECUTE IMMEDIATE 절에는 해결 방법이 제공되지 않습니다.

참고

FETCH Cursor는 대부분 그대로 사용할 수 있지만 성능 문제를 위해 가능하면 SELECT 문으로 변경하는 것이 좋습니다.

CREATE OR REPLACE PROCEDURE bulk_collect_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        --** SSC-PRF-0009 - PERFORMANCE REVIEW - CURSOR USAGE **
        record_cursor CURSOR
        FOR
            SELECT *
            FROM
                bulk_collect_table;
--                !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--                TYPE fetch_collection_typ IS TABLE OF record_cursor%ROWTYPE;
    fetch_collection_variable VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'fetch_collection_typ' USAGE CHANGED TO VARIANT ***/!!!;
--                !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!

--    TYPE collection_typ IS TABLE OF bulk_collect_table%ROWTYPE;
    collection_variable VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'collection_typ' USAGE CHANGED TO VARIANT ***/!!!;
    BEGIN
                !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'RECORDS AND COLLECTIONS' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
                SELECT * BULK COLLECT INTO collection_variable FROM bulk_collect_table;
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                FOR i IN 1 TO 0 /*collection_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE CUSTOM TYPE EXPRESSION' NODE ***/!!!
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                   LOOP
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            CALL DBMS_OUTPUT.PUT_LINE_UDF(:collection_variable(i).col1);
                   END LOOP;
                !!!RESOLVE EWI!!! /*** SSC-EWI-OR0108 - THE FOLLOWING ASSIGNMENT STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!

                collection_variable := null;
                OPEN record_cursor;
                --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
                record_cursor := (
            CALL FETCH_BULK_COLLECTION_RECORDS_UDF(:record_cursor)
                );
                collection_variable := :record_cursor:RESULT;
                CLOSE record_cursor;
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                FOR i IN 1 TO 0 /*collection_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE CUSTOM TYPE EXPRESSION' NODE ***/!!!
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                   LOOP
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            CALL DBMS_OUTPUT.PUT_LINE_UDF(
            !!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '+' MAY NOT BEHAVE CORRECTLY BETWEEN unknown AND Number ***/!!!
            :collection_variable(i).col1+6);
                   END LOOP;
                !!!RESOLVE EWI!!! /*** SSC-EWI-OR0108 - THE FOLLOWING ASSIGNMENT STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!

                collection_variable := null;
                !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
                EXECUTE IMMEDIATE 'SELECT * FROM
   bulk_collect_table'
                      !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'EXECUTE IMMEDIATE RETURNING CLAUSE' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
                      BULK COLLECT INTO collection_variable;
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                FOR i IN 1 TO 0 /*collection_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE CUSTOM TYPE EXPRESSION' NODE ***/!!!
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                   LOOP
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            CALL DBMS_OUTPUT.PUT_LINE_UDF(
            !!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '+' MAY NOT BEHAVE CORRECTLY BETWEEN unknown AND Number ***/!!!
            :collection_variable(i).col1+12);
                   END LOOP;
    END;
$$;

CALL bulk_collect_procedure();
Copy
결과

DBMS OUTPUT

1

2

3

4

5

6

7

8

9

10

11

– EXECUTE IMMEDIATE NOT EXECUTED는 지원되지 않음

SELECT INTO 문 케이스

이 경우 변환 사양은 RESULTSETs 을 사용합니다. WITH, SELECT 및 BULK COLLECT INTO 문에 대한 설명서는 다음에서 확인할 수 있습니다.

with-select-and-bulk-collect-into-statements.md

Known Issues

1. Heavy performance issues on FETCH Cursor workaround

Fetch 커서에 대한 해결 방법은 임시 테이블로 인해 성능 요구 사항이 높습니다. SELECT 문으로 수동으로 마이그레이션하는 것이 좋습니다

2. Execute immediate statements are not transformed

SnowConvert AI에서는 지원되지 않지만 SELECT 문으로 수동 변경할 수 있습니다.

관련 EWIs

  1. SSC-EWI-0058: 이 기능은 현재 Snowflake Scripting에서 지원되지 않습니다.

  2. SSC-EWI-0062: 사용자 지정 유형 사용법이 베리언트로 변경되었습니다.

  3. SSC-EWI-0073: 보류 중 함수 동등성 검토

  4. SSC-EWI-OR0036: 유형 확인 문제로 인해 문자열과 날짜 사이에서 산술 연산이 올바르게 동작하지 않을 수 있습니다.

  5. SSC-EWI-OR0108: 다음 할당 문은 Snowflake Scripting에서 지원되지 않습니다.

  6. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE의 UDF구현 확인.

  7. SSC-PRF-0001: 이 문에는 커서 가져오기 대량 작업의 사용법이 있습니다.

  8. SSC-EWI-0030: 아래 문에는 동적 SQL의 사용법이 있습니다.

WITH, SELECT 및 BULK COLLECT INTO 문

위험

이 섹션은 변환 사양입니다. 정보는 향후 변경될 수 있습니다.

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

설명

이 섹션은 BULK COLLECT INTO 문을 사용하는 SELECT 문 다음에 오는 WITH 문에 대한 변환 사양입니다. 자세한 내용은 다음 설명서를 참조하십시오.

샘플 소스 패턴

참고

출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.

다음 예제에는 다음 쿼리가 사용됩니다.

Oracle

-- Sample MySampleTable table
CREATE TABLE MySampleTable (
  MySampleID NUMBER PRIMARY KEY,
  FirstName VARCHAR2(50),
  Salary NUMBER,
  Department VARCHAR2(50)
);

-- Insert some sample data
INSERT INTO MySampleTable (MySampleID, FirstName, Salary, Department)
VALUES (1, 'Bob One', 50000, 'HR');

INSERT INTO MySampleTable (MySampleID, FirstName, Salary, Department)
VALUES (2, 'Bob Two', 60000, 'HR');

INSERT INTO MySampleTable (MySampleID, FirstName, Salary, Department)
VALUES (3, 'Bob Three', 75000, 'IT');

INSERT INTO MySampleTable (MySampleID, FirstName, Salary, Department)
VALUES (4, 'Bob Four', 80000, 'IT');
Copy
Snowflake
-- Sample MySampleTable table
CREATE OR REPLACE TABLE MySampleTable (
   MySampleID NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/ PRIMARY KEY,
   FirstName VARCHAR(50),
   Salary NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
   Department VARCHAR(50)
 )
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

-- Insert some sample data
INSERT INTO MySampleTable(MySampleID, FirstName, Salary, Department)
VALUES (1, 'Bob One', 50000, 'HR');

INSERT INTO MySampleTable(MySampleID, FirstName, Salary, Department)
VALUES (2, 'Bob Two', 60000, 'HR');

INSERT INTO MySampleTable(MySampleID, FirstName, Salary, Department)
VALUES (3, 'Bob Three', 75000, 'IT');

INSERT INTO MySampleTable(MySampleID, FirstName, Salary, Department)
VALUES (4, 'Bob Four', 80000, 'IT');
Copy

1. Inside procedure simple case

위험

이는 결과 집합 데이터 타입을 사용하는 접근법입니다. 사용자 정의 유형을 검토해야 합니다. RESULTSETs 에 대한 자세한 내용은 다음 Snowflake 설명서 를 검토하십시오.

다음 예제에서는 사용자 정의 유형을 사용하며 테이블로 간접적으로 선언됩니다. 이 경우의 변환은 RESULTSET 을 Snowflake의 데이터 타입으로 구현합니다. 결과 집합은 변수에 저장되며 TABLE() 함수에 래핑되어 반환되어야 합니다.

Oracle
CREATE OR REPLACE PROCEDURE simple_procedure
IS
  TYPE salary_collection IS TABLE OF NUMBER;
  v_salaries salary_collection := salary_collection();

BEGIN
  WITH IT_Employees AS (
    SELECT Salary
    FROM MySampleTable
    WHERE Department = 'IT'
  )
  SELECT Salary BULK COLLECT INTO v_salaries
  FROM IT_Employees;
END;

CALL simple_procedure();
Copy
결과

참고

쿼리 결과는 반환되지 않지만 예상되는 수집 정보는 예제에 사용되는 IT 급여 정보입니다.

IT_Salary

75000

80000

위험

RESULTSETs 의 제한 사항 중 하나는 테이블로 사용할 수 없다는 것입니다. 예: my_result_set의 `select *. (이는 오류입니다. 자세한 내용은 다음 설명서 를 참조하십시오).

Snowflake
CREATE OR REPLACE PROCEDURE simple_procedure ()
RETURNS STRING
LANGUAGE JAVASCRIPT
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
  // SnowConvert AI Helpers Code section is omitted.

  !!!RESOLVE EWI!!! /*** SSC-EWI-OR0072 - PROCEDURAL MEMBER TYPE DEFINITION NOT SUPPORTED. ***/!!!
  /*   TYPE salary_collection IS TABLE OF NUMBER */
  ;
  !!!RESOLVE EWI!!! /*** SSC-EWI-OR0104 - UNUSABLE VARIABLE, ITS TYPE WAS NOT TRANSFORMED ***/!!!
  /*   v_salaries salary_collection := salary_collection() */
  ;
  EXEC(`SELECT Salary
    FROM
       MySampleTable
    WHERE Department = 'IT'`);
  [
    !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'PlBulkCollectionItem' NODE ***/!!!
    //v_salaries
    null,V_SALARIES] = EXEC(`SELECT
   Salary
 FROM IT_Employees`);
$$;

CALL simple_procedure();
Copy
결과

SALARY

77500

80000

2. Simple case for iterations: FOR LOOP statement

다음은 FOR...LOOP 를 사용하여 반복에 대한 변환을 정의하는 경우입니다. 이 경우 사용자 정의 유형은 암시적으로 테이블이므로 커서를 사용하여 반복할 수 있습니다. 자세한 내용은 다음 설명서를 참조하십시오.

  • [커서를 위한 테이블] 반환에 대한 Snowflake 설명서.(https://docs.snowflake.com/developer-guide/snowflake-scripting/cursors#returning-a-table-for-a-cursor)

  • 이 경우 반복을 위한 커서를 생성해야 합니다. 다음 커서 할당 구문 설명서를 검토하십시오.

Oracle
CREATE OR REPLACE PROCEDURE simple_procedure
IS
  TYPE salary_collection IS TABLE OF NUMBER;
  v_salaries salary_collection := salary_collection();
  v_average_salary NUMBER;
  salaries_count NUMBER;

BEGIN
  salaries_count := 0;
  WITH IT_Employees AS (
    SELECT Salary
    FROM MySampleTable
    WHERE Department = 'IT'
  )
  SELECT Salary BULK COLLECT INTO v_salaries
  FROM IT_Employees;

  -- Calculate the average salary
  IF v_salaries.COUNT > 0 THEN
    v_average_salary := 0;
    FOR i IN 1..v_salaries.COUNT LOOP
		v_average_salary := v_average_salary + v_salaries(i);
		salaries_count := salaries_count + 1;
    END LOOP;
    v_average_salary := v_average_salary / salaries_count;
  END IF;

  -- Display the average salary
  DBMS_OUTPUT.PUT_LINE('Average Salary for IT Department: ' || v_average_salary);
END;
/

CALL simple_procedure();
Copy
결과
Statement processed.
Average Salary for IT Department: 77500

Copy
Snowflake
CREATE OR REPLACE PROCEDURE simple_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
	DECLARE
--		!!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--		TYPE salary_collection IS TABLE OF NUMBER;
		v_salaries VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'salary_collection' USAGE CHANGED TO VARIANT ***/!!! := salary_collection();
		v_average_salary NUMBER(38, 18);
		salaries_count NUMBER(38, 18);
	BEGIN
		salaries_count := 0;
		WITH IT_Employees AS
		(
		  SELECT Salary
		  FROM
		  	MySampleTable
		  WHERE Department = 'IT'
		)
		!!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'RECORDS AND COLLECTIONS' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
		SELECT Salary BULK COLLECT INTO v_salaries
		FROM IT_Employees;
		-- Calculate the average salary
		IF (null /*v_salaries.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE CUSTOM TYPE EXPRESSION' NODE ***/!!! > 0) THEN
		  v_average_salary := 0;
		  --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
		  FOR i IN 1 TO 0 /*v_salaries.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE CUSTOM TYPE EXPRESSION' NODE ***/!!!
 		                                                                                                                                                                        --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
 		                                                                                                                                                                        LOOP
		  	v_average_salary :=
		  	!!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '+' MAY NOT BEHAVE CORRECTLY BETWEEN NUMBER AND salary_collection ***/!!!
		  	:v_average_salary + v_salaries(i);
		  	salaries_count := :salaries_count + 1;
 		                                                                                                                                                                           END LOOP;
		  v_average_salary := :v_average_salary / :salaries_count;
		END IF;
		-- Display the average salary
		--** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
		CALL DBMS_OUTPUT.PUT_LINE_UDF('Average Salary for IT Department: ' || NVL(:v_average_salary :: STRING, ''));
	END;
$$;

CALL simple_procedure();
Copy
결과

SIMPLE_PROCEDURE

IT 부서의 평균 급여: 77500

Known Issues

1. Resulset limitations.

RESULTSET 데이터 타입을 사용하는 데는 제한이 있습니다. 자세한 내용은 다음 Snowflake 설명서 를 참조하십시오. 표시 가능한 제한 사항은 다음과 같습니다.

  • RESULTSET 타입의 열 선언.

  • RESULTSET 타입의 매개 변수 선언 .

  • 저장 프로시저의 반환 유형을 RESULTSET 으로 선언합니다.

2. Execute statements with Bulk Collect clause are not supported.

다음 설명서를 검토하십시오.

관련 EWIs

  1. SSC-EWI-0058: 이 기능은 현재 Snowflake Scripting에서 지원되지 않습니다.

  2. SSC-EWI-0062: 사용자 지정 유형 사용법이 베리언트로 변경되었습니다.

  3. SSC-EWI-0073: 보류 중 함수 동등성 검토

  4. SSC-EWI-OR0036: 유형 확인 문제로 인해 문자열과 날짜 사이에서 산술 연산이 올바르게 동작하지 않을 수 있습니다.

  5. SSC-EWI-OR0072: 프로시저 멤버는 지원되지 않음

  6. SSC-EWI-OR0104: 사용할 수 없는 컬렉션 변수입니다.

  7. SSC-FDM-0006: 숫자 유형 열이 Snowflake에서 유사하게 동작하지 않을 수 있습니다.

  8. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE의 UDF구현 확인.