Oracle PL/SQL数据库部署脚本
我正试图编写一个部署脚本,在CI/CD管道中使用SQL*Plus运行,但我找不到解决这个看似非常基本的问题的方法 下面是脚本release.sql的缩短版本:Oracle PL/SQL数据库部署脚本,oracle,plsql,sqlplus,Oracle,Plsql,Sqlplus,我正试图编写一个部署脚本,在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
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
我明白了
创建表DA_产品
*
第6行错误:
ORA-06550:第6行第1列:
PLS-00103:在预期以下情况时遇到符号“创建”:
所以它不喜欢da_001.sql开头的CREATE语句,但我不知道为什么。我在这里缺少什么?我自己没有用过,但您可以尝试类似的方法(简化演示):
要在
executeimmediate
中工作,调用的脚本必须包含一条语句,且不包含分号。为脚本创建一个安装文件,即
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理解/能够理解的内容与SQL和PLSQL语言内部的内容之间存在着严格的分离 脚本处理是这些不同的领域之一,这意味着您不能在PLSQL块中执行SQL脚本 此外,SQL*Plus对PLSQL逻辑结构没有任何理解 然而,考虑到您的需求,可能有一种方法。“康纳·麦克唐纳”的回答应该有效。下面是我使用基于PLSQL的方法的尝试 这种方法使用SQLPLus变量,可以在PLSQL和SQLPLus中引用和修改这些变量 首先,您需要一个“无操作”脚本,因为在使用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 substation变量(&),我们使用列。。。NEW_VALUE
命令将选择列表列别名映射到替换变量。因此,我们将有效地将scriptn
映射到子变量bl;esn
PLSQL块完成后,scriptn
变量的值为'noop.sql'或要运行的脚本的名称
最后,在“@”命令中引用subs变量
任何带有'noop.sql'的内容都将执行一个空白脚本。PL/sql语言没有
CREATE
关键字。您需要立即执行
或其他方法。@
是一个sqlplus
命令,而不是SQL甚至PL/SQL命令。它只能在sqlplus
命令行上使用。PL/SQL代码在服务器上运行时,不知道使用哪个客户端工具调用它,甚至不知道如何访问客户端上的文件。@如果这是SQL*Plus脚本的一部分,则SQL*Plus会在执行之前将引用的脚本嵌入PL/SQL块中。不过,引用的脚本必须是有效的PL/SQL。@WilliamRobertson:你确定吗?这需要sqlplus解析PL/SQL正文,并在将PL/SQL块发送到服务器之前用实际的文件内容替换对文件的引用。在第一个脚本中,结尾缺少“/”。如果没有这一点,它将假定创建表是PLSQL块的一部分。这是完美的。我开始将executeimmediate添加到我所有的DDL脚本中,不喜欢这种味道。
-- 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