Можно ли вызвать глобальную переменную в исходной переменной в ODI?
Я пытаюсь построить процедуру ODI, которая будет принимать имя схемы, имя процедуры DB и параметры из таблицы метаданных базы данных оракула. Поле параметра содержит имя глобальной переменной ODI. Исходная команда выглядит следующим образом
SELECT SCHEMA_NAME VAR_SCHEMA, PROCEDURE_NAME VAR_PROCEDURE, PARAMETER_NAME
VAR_PARAMETER FROM SCHEMA-NAME.TABLE_NAME
вывод исходной команды выглядит так:
VAR_SCHEMA_NAME VAR_TABLE_NAME VAR_PARAMETER
ABC PROC_LIST TO_DATE('#VAR_ETL_LOAD_DATE','DD/MM/RRRR')
Здесь #VAR_ETL_LOAD_DATE является глобальной переменной в ODI.
В целевой команде процедуры я хочу использовать эту информацию из исходной команды для выполнения процедур, перечисленных в таблице метаданных. Я написал команду, как это:
DECLARE
VVC_SQL_STMT LONG;
BEGIN
VVC_SQL_STMT := 'BEGIN
#VAR_SCHEMA_NAME.#VAR_PROCEDURE_NAME(#VAR_PARAMETER);
END;';
INSERT INTO AK_TST2 VALUES(VVC_SQL_STMT,SYSDATE);
COMMIT;
EXECUTE IMMEDIATE (VVC_SQL_STMT);
END;
Этот код дает следующую ошибку в ODI:
ODI-1228: Task PROC_SP_HANDLER (Procedure) fails on the target ORACLE
connection OCDM_SYS.
Caused By: java.sql.SQLException: ORA-06550: line 8, column 61:
PLS-00103: Encountered the symbol "#" when expecting one of the following:
* & = - + ; < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
Каковы причины этого и как я могу выполнить хранимые процедуры в ODI, считывая имена процедур и параметры из таблицы метаданных?
1 ответ
Если вы выбираете данные из таблицы и используете результат в качестве кода для дальнейшего выполнения, обычно вы не можете использовать там переменные ODI. Потому что для ODI слишком поздно признать, что это переменная, и заменить ее переменной. Это одинаково для глобальных переменных и переменных проекта.
Если бы вы могли напечатать "#"+variable_name
от?- или%-замена чем будет работать. Но если @-substitution печатает имя переменной или если переменная появляется как окончательный код после извлечения значений из Source, это слишком поздно. В этом случае он остается в виде простого текста #VAR
,
В вашем конкретном случае вы можете сделать следующее:
- Объявите все переменные как
#VAR_ETL_LOAD_DATE
в пакете. Я имею в виду все переменные, которые потенциально могут появиться в таблице метаданных. Сценарий Bacause должен знать все переменные заранее. - Выбирайте и извлекайте записи в пределах?-Подстановки, используя odiRef.getJDBCConnection('SRC'). Соберите все результаты в java-переменную в форме исполняемого кода.
Например, исходный код может выглядеть так:
select 1 from dual;
<?
import java.sql.*;
String crlf = System.getProperty("line.separator");
String result = "begin"+crlf+"null;"+crlf;
PreparedStatement stmt = odiRef.getJDBCConnection("SRC").prepareStatement("select schema||'.'||proc||'('||param||')' from metatable");
ResultSet rs = stmt.executeQuery();
while(rs.next()){
result += "insert into ak_tst2 values('"+rs.getString(1).replaceAll("'",'"'.toString())+"');"+crlf;
result += "commit;"+crlf;
result += rs.getString(1)+";"+crlf;
}
result += "end;";
rs.close();
stmt.close();
?>
Целевой код должен быть очень простым
<?=result?>
Во время выполнения целевой код будет выглядеть так
begin
null;
insert into ak_tst2 values('qwe.asd("param_using_#var")');
commit;
qwe.asd('param_using_#var');
insert into ak_tst2 values('qwe2.asd2("param2_using_#var")');
commit;
qwe2.asd2('param2_using_#var');
insert into ak_tst2 values('qwe3.asd3("param3_using_#var")');
commit;
qwe3.asd3('param3_using_#var');
end;
И переменные ODI будут успешно заменены значениями.