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' 的东西都会执行一个空白脚本。