Как написать скрипт который выполняет другие скрипты по условию?
Пытаюсь написать скрипт развертывания БД для запуска с SQL*Plus в CI/CD конвейере. Не могу найти способ выполнить скрипты по условию.
Вот сокращенная версия скрипта release.sql:
DECLARE
val NUMBER;
BEGIN
SELECT value INTO val
FROM par WHERE name = 'version';
IF val = 1.23 THEN -- run create scripts
@ddl/da_001.sql
@ddl/da_002.sql
@dml/version.sql -- set initial version
END IF;
END;
/
Скрипт da_001.sql вглядит так:
CREATE TABLE TAB (
COL1 NUMBER NOT NULL,
CONSTRAINT TABLE_NAME_PK PRIMARY KEY (COL1) ENABLE)
/
Когда запускаю:
sqlplus connection_string @release.sql
То получаю ошибку:
CREATE TABLE TAB (
- ERROR at line 7: ORA-06550: line 7, column 1: PLS-00103: Encountered the symbol "CREATE" when expecting one of the following: [...]
Ему не нравится CREATE... в начале, но не знаю почему. Чего здесь не хватает?
Свободный перевод вопроса PL/SQL DB Deployment Script от участника @HasaniH
Ответы (3 шт):
Я однажды уже прошел по этому минному полю полю с граблями...
Очень советую не полениться и установить Liquibase - очень мощный инструмент для релиз-менеджмента на стороне БД, который поддерживает накатывание SQL скриптов до определенного тега (версии) и откат скриптов (самая болезненная часть).
Создайте установочный скрипт, который запустит другие скрипты, например:
prompt START install.sql
@ddl/da_001.sql
@ddl/da_002.sql
@dml/version.sql
prompt Installed successfully
А затем вызывайте его по условию в release.sql:
set feedback off pages 0
spool runme.sql
SELECT
case
when value = 1.23 then '@@install.sql'
else 'prompt Skipped install.sql' end
FROM par WHERE name = 'version'
/
spool off
@runme.sql
exit
Запуск и результат:
$ sqlplus -s -l connect_args @ release.sql
@@install.sql
start install.sql
Installed successfully
Свободный перевод ответа от участника @Connor McDonald
Решение с полностью динамическим созданием запускающего скрипта с аргументами для его отдельных скриптов в PL/SQL блоке:
set autoprint on
set termout off
column sqls new_value sqls noprint
var sqls varchar2 (4000);
declare
val varchar2 (8);
nl constant char (1) := chr (10);
begin
select value into val
from par where name = 'version';
if val = 1.23 then
:sqls :=
'@ddl/da_001.sql arg1'||nl||
'@ddl/da_002.sql arg2'||nl||
'@dml/version.sql arg3'||nl||
'prompt Version '||val||' instaled successfully'||nl||
'exit';
else
:sqls := 'prompt Skipped due to version='||val;
end if;
end;
/
spool tmp.sql
prompt &sqls
spool off
set termout on
@ tmp
Запуск и результат:
sqlplus -s -l connect_string @ release.sql
## executing da_001 arg1
## executing da_002 arg2
## executing version arg3
Version 1.23 instaled successfully