Вопрос или проблема
Я пытаюсь преобразовать приведенную ниже функцию Oracle в функцию Snowflake: мне нужна помощь с этим, так как я не так хорошо знаком с Snowflake.
Я попробовал некоторые функции, чтобы преобразовать приведенный ниже код в совместимый с Snowflake, но сталкиваюсь с трудностями.
CREATE OR REPLACE function schema_1.getCName(CCodes VARCHAR2)
return varchar2
as
TYPE results_type IS REF CURSOR;
results results_type;
CValue VARCHAR2(1023 CHAR);
CCodesForInClause VARCHAR2(511 CHAR) DEFAULT '';
CCodesValue VARCHAR2(510 CHAR);
cursorQuery VARCHAR2(1023 CHAR) DEFAULT '';
CNames VARCHAR2(1023 CHAR);
begin
CNames := '';
IF(instr(CCodes,',') > 0) THEN
CCodesValue := CCodes;
WHILE (instr(CCodesValue,',') > 0)
LOOP
CCodesForInClause := CCodesForInClause || '''' ||
trim(substr(CCodesValue, 0, instr(CCodesValue,',')-1)) ||
''',';
CCodesValue := substr(CCodesValue, instr(CCodesValue,',') + 1,
LENGTH(CCodesValue) - instr(CCodesValue,','));
END LOOP;
CCodesForInClause := CCodesForInClause || '''' || trim(CCodesValue) || '''';
cursorQuery := 'SELECT DISTINCT C_NAME FROM Table1 WHERE C_ABBREV IN ' || '(' || CCodesForInClause || ') order by C_NAME';
OPEN results FOR cursorQuery;
LOOP
IF (length(trim(CValue)) > 0) THEN
CNames := CNames || CValue || ';';
END IF;
FETCH results INTO CValue;
EXIT WHEN results%NOTFOUND;
END LOOP;
IF (length(trim(CNames)) > 0) THEN
CNames := substr(CNames, 1, length(CNames)-1);
END IF;
CLOSE results;
ELSE
OPEN results FOR 'SELECT DISTINCT C_NAME FROM Table1 WHERE C_ABBREV = :cc' USING CCodes;
FETCH results into CValue;
IF (results%FOUND) THEN
CNames := CValue;
END IF;
CLOSE results;
END IF;
DBMS_Output.Put_Line(CNames);
return CNames;
end;
Ответ или решение
Конвертация функции Oracle в функцию Snowflake может быть сложной задачей, особенно если вы не знакомы с языком и синтаксисом Snowflake. В данном ответе я предложу шаг за шагом, как преобразовать предоставленную функцию Oracle в соответствующую функцию Snowflake, сохраняя семантику и логику исходного кода.
Шаг 1: Основные отличия
- Объявление функций: В Snowflake мы используем
CREATE OR REPLACE FUNCTION
подобно Oracle, ноRETURN
указывается позже, без ключевого словаAS
. - Указание типов данных: В Snowflake нет типа
VARCHAR2
. Вместо этого используетсяVARCHAR
. - Обработка курсоров: Snowflake не поддерживает курсоры в том виде, как это реализовано в Oracle. Вместо этого рекомендуется использовать оператор
RETURN TABLE
для возврата результатов. - Условие выборки с использованием конструкций
IF/ELSE
: В Snowflake это осуществляется несколько иначе, но мы можем придерживаться аналогичной логики.
Шаг 2: Преобразование кода
Ниже представлена новая версия функции, адаптированной под требования Snowflake.
CREATE OR REPLACE FUNCTION schema_1.getCName(CCodes VARCHAR)
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
DECLARE
CNames VARCHAR := '';
CCodesForInClause STRING := '';
CCodesValue VARCHAR := CCodes;
BEGIN
IF POSITION(',' IN CCodes) > 0 THEN
WHILE POSITION(',' IN CCodesValue) > 0 DO
CCodesForInClause := CCodesForInClause || '''' || TRIM(SUBSTRING(CCodesValue, 1, POSITION(',' IN CCodesValue) - 1)) || ''',';
CCodesValue := SUBSTRING(CCodesValue, POSITION(',' IN CCodesValue) + 1);
END WHILE;
CCodesForInClause := CCodesForInClause || '''' || TRIM(CCodesValue) || '''';
-- Выполнение запроса и сбор результатов
CNames := (
SELECT LISTAGG(C_NAME, ';') WITHIN GROUP (ORDER BY C_NAME)
FROM (SELECT DISTINCT C_NAME FROM Table1 WHERE C_ABBREV IN (CCodesForInClause))
);
ELSE
SELECT C_NAME INTO CNames
FROM Table1
WHERE C_ABBREV = CCodes
LIMIT 1;
END IF;
RETURN CNames;
END;
$$;
Шаг 3: Объяснение кода
- Инициализация переменных: Заменили тип
VARCHAR2
наVARCHAR
, что является соответствующим типом в Snowflake. - Проверка на наличие запятой: Используется
POSITION
вместоINSTR
для поиска запятой в строке. - Строковая агрегация: Для объединения имен используется функция
LISTAGG
, которая позволяет объединять строки с заданным разделителем. ФункцияORDER BY
вLISTAGG
управляет порядком объединения имен. - Выбор имени с помощью
SELECT INTO
: Это реализация аналогична получению значения через курсор в Oracle, но в Snowflake мы можем просто использоватьSELECT ... INTO
.
Шаг 4: Заключение
Этот пример демонстрирует, как преобразовать функцию Oracle в функцию Snowflake, сохраняя функциональность и при этом адаптируя синтаксис к специфике платформы. Если у вас есть дополнительные запросы или нужны уточнения по другим аспектам, пожалуйста, дайте знать!