PL/SQL 数据库部署脚本
PL/SQL DB Deployment Script
我正在尝试在 CI/CD 管道中使用 SQL*Plus 为 运行 编写部署脚本,但我无法找到似乎是非常基本的问题。
这是脚本的简化版本 release.sql:
DECLARE
vnum NUMBER;
BEGIN
SELECT COUNT(tname) INTO vnum FROM tab WHERE tname = 'DA_VERSION';
IF vnum = 0 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 TABLE_NAME
(
COLUMN1 NUMBER NOT NULL
, CONSTRAINT TABLE_NAME_PK PRIMARY KEY
(
COLUMN1
)
ENABLE
);
当我运行
sqlplus.exe connection_string @release.sql
我明白了
CREATE TABLE DA_PRODUCTS
*
ERROR at line 6:
ORA-06550: line 6, column 1:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:...
所以它不喜欢da_001.sql开头的CREATE语句,但我不知道为什么。我在这里错过了什么?
我自己没用过这个,但你可以试试这样的东西(简化的演示):
declare
vnum number := 0;
begin
--select count(tname) into vnum from tab where tname = 'DA_VERSION';
if vnum = 0 then -- include create script
execute immediate q'[
@callthis.sql
]';
end if;
end;
要在 execute immediate
内工作,被调用的脚本必须包含单个语句且没有分号。
为您的脚本创建一个安装文件,即
install.sql
===========
@ddl/da_001.sql
@ddl/da_002.sql
@dml/version.sql -- set initial version
然后通过 SQL Plus
中的包装器有选择地调用它
set feedback off
set pages 0
spool /tmp/runme.sql
select
case when COUNT(tname) = 0 then '@@install.sql' else 'pro Skipped install.sql' end
FROM tab WHERE tname = 'DA_VERSION';
spool off
@/tmp/runme.sql
正如其他人所说,SQL*PLus understands/is 的能力与 SQL 和 PLSQL 语言之间存在严格的区分。
脚本处理是这些不同领域之一,这意味着您不能在 PLSQL 块中执行 SQL 脚本。
此外,SQL*Plus 对 PLSQL 逻辑结构没有任何理解。
但是,根据您的要求,可能会有办法。 @“Connor McDonald”的答案应该有效。这是我尝试使用更基于 PLSQL 的方法。
该方法使用了SQLPLus变量,在PLSQL和SQLPlus中都可以引用和修改。
首先您需要一个 'No Op' 脚本,因为在使用 SQL*PLus '@' 时您必须指定一个有效的脚本名称:
noop.sql:
PROMPT No Op
现在你的控制器脚本:
-- Declare your variables
VAR script1 VARCHAR2(256)
VAR script2 VARCHAR2(256)
VAR script3 VARCHAR2(256)
DECLARE
vnum NUMBER;
BEGIN
:script1 := 'noop.sql';
:script2 := 'noop.sql';
:script3 := 'noop.sql';
SELECT COUNT(tname) INTO vnum FROM tab WHERE tname = 'DA_VERSION';
IF vnum = 0 THEN -- run create scripts
-- Set variables
:script1 := 'ddl/da_001.sql';
:script2 := 'ddl/da_002.sql';
:script3 := 'dml/version.sql'; -- set initial version
END IF;
END;
/
-- Make variables referencable as SQLPLus defines
COLUMN s1 NEW_VALUE s1
COLUMN s2 NEW_VALUE s2
COLUMN s3 NEW_VALUE s3
SELECT :script1 s1, :script2 s2, :script3 s3
FROM dual;
-- RUN !!
@ &&s1
@ &&s2
@ &&s3
3个scriptn
变量可以在PLSQL中使用。
要用作 SQL_PLus 替换变量 (&),我们使用 COL ... NEW_VALUE
命令将 SELECT 列表列别名映射到替换变量。所以我们将有效地将 scriptn
映射到子变量;e sn
.
在 PLSQL 块完成后,scriptn
变量将具有值 'noop.sql' 或脚本的名称 运行。
最后,在'@'命令中引用子变量。
任何带有 'noop.sql' 的东西都会执行一个空白脚本。
我正在尝试在 CI/CD 管道中使用 SQL*Plus 为 运行 编写部署脚本,但我无法找到似乎是非常基本的问题。
这是脚本的简化版本 release.sql:
DECLARE
vnum NUMBER;
BEGIN
SELECT COUNT(tname) INTO vnum FROM tab WHERE tname = 'DA_VERSION';
IF vnum = 0 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 TABLE_NAME
(
COLUMN1 NUMBER NOT NULL
, CONSTRAINT TABLE_NAME_PK PRIMARY KEY
(
COLUMN1
)
ENABLE
);
当我运行
sqlplus.exe connection_string @release.sql
我明白了
CREATE TABLE DA_PRODUCTS * ERROR at line 6: ORA-06550: line 6, column 1: PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:...
所以它不喜欢da_001.sql开头的CREATE语句,但我不知道为什么。我在这里错过了什么?
我自己没用过这个,但你可以试试这样的东西(简化的演示):
declare
vnum number := 0;
begin
--select count(tname) into vnum from tab where tname = 'DA_VERSION';
if vnum = 0 then -- include create script
execute immediate q'[
@callthis.sql
]';
end if;
end;
要在 execute immediate
内工作,被调用的脚本必须包含单个语句且没有分号。
为您的脚本创建一个安装文件,即
install.sql
===========
@ddl/da_001.sql
@ddl/da_002.sql
@dml/version.sql -- set initial version
然后通过 SQL Plus
中的包装器有选择地调用它set feedback off
set pages 0
spool /tmp/runme.sql
select
case when COUNT(tname) = 0 then '@@install.sql' else 'pro Skipped install.sql' end
FROM tab WHERE tname = 'DA_VERSION';
spool off
@/tmp/runme.sql
正如其他人所说,SQL*PLus understands/is 的能力与 SQL 和 PLSQL 语言之间存在严格的区分。
脚本处理是这些不同领域之一,这意味着您不能在 PLSQL 块中执行 SQL 脚本。
此外,SQL*Plus 对 PLSQL 逻辑结构没有任何理解。
但是,根据您的要求,可能会有办法。 @“Connor McDonald”的答案应该有效。这是我尝试使用更基于 PLSQL 的方法。
该方法使用了SQLPLus变量,在PLSQL和SQLPlus中都可以引用和修改。
首先您需要一个 'No Op' 脚本,因为在使用 SQL*PLus '@' 时您必须指定一个有效的脚本名称:
noop.sql:
PROMPT No Op
现在你的控制器脚本:
-- Declare your variables
VAR script1 VARCHAR2(256)
VAR script2 VARCHAR2(256)
VAR script3 VARCHAR2(256)
DECLARE
vnum NUMBER;
BEGIN
:script1 := 'noop.sql';
:script2 := 'noop.sql';
:script3 := 'noop.sql';
SELECT COUNT(tname) INTO vnum FROM tab WHERE tname = 'DA_VERSION';
IF vnum = 0 THEN -- run create scripts
-- Set variables
:script1 := 'ddl/da_001.sql';
:script2 := 'ddl/da_002.sql';
:script3 := 'dml/version.sql'; -- set initial version
END IF;
END;
/
-- Make variables referencable as SQLPLus defines
COLUMN s1 NEW_VALUE s1
COLUMN s2 NEW_VALUE s2
COLUMN s3 NEW_VALUE s3
SELECT :script1 s1, :script2 s2, :script3 s3
FROM dual;
-- RUN !!
@ &&s1
@ &&s2
@ &&s3
3个scriptn
变量可以在PLSQL中使用。
要用作 SQL_PLus 替换变量 (&),我们使用 COL ... NEW_VALUE
命令将 SELECT 列表列别名映射到替换变量。所以我们将有效地将 scriptn
映射到子变量;e sn
.
在 PLSQL 块完成后,scriptn
变量将具有值 'noop.sql' 或脚本的名称 运行。
最后,在'@'命令中引用子变量。
任何带有 'noop.sql' 的东西都会执行一个空白脚本。