繁体   English   中英

如何将bash变量传递给sqlplus,然后将该输出传递给另一个变量

[英]How to pass a bash variable to sqlplus and then pass that output to another variable

因此,我要做的是清除Oracle数据库中PDB的审核日志。 PDB的名称每次都可以不同,因此我不能使用tnsnames将sqlplus直接输入PDB来执行此操作。 我将命令传递到bash中,然后将其传递到SQLPLUS命令中。 所有这些工作都除一项之外,我似乎无法弄清楚如何使其工作。

我的代码是

AUDIT="DELETE FROM SYS.AUD$ WHERE NTIMESTAMP# < sysdate-30;"
FINDPDB="select pdb_name from dba_pdbs where pdb_name != 'PDB\$SEED';"
ALTER="alter session set container=$FINDPDB;"


sqlplus -S /nolog <<EOF1
  connect / as sysdba
  set echo off feedback off head off pages 0
  set serveroutput on
  $FINDPDB
  $ALTER
  $AUDIT
  exit;
EOF1

我不断收到的错误是

alter session set container=select pdb_name from dba_pdbs where pdb_name != 'PDB$SEED';
                              *
ERROR at line 1:
ORA-65015: missing or invalid container name

这告诉我,它不是将select语句的输出传递给$ FINDPDB,而是传递给实际的select语句本身。

有没有一种方法可以将这个值传递给ALTER变量,并使它更改会话并清除sys.aud $表?

我手头没有Oracle实例,但是我看到两种方法可以做到这一点:

  1. 通过SQL * Plus建立许多连接
    1. 首先,检索pdb_name
    2. 其次,设置容器并删除审核。
  2. 使用单个SQL * Plus,但使用两个命名管道
    1. 一个发送生成的SQL命令
    2. 秒读SQL * Plus输出

作为替代方式,我应该使用一种“真正的”编程语言(Ruby,Python,JavaScript),该语言更适合处理从数据库读取的数据。

编辑:经过一些搜索,它可能在PL / SQL中完成

DECLARE
   v_pdb_name VARCHAR2(255);
BEGIN
   SELECT pdb_name INTO v_pdb_name FROM dba_pdbs WHERE pdb_name != 'PDB\$SEED';
   EXECUTE IMMEDIATE 'ALTER SESSION SET container='||v_pdb_name;
   DELETE FROM sys.aud$ WHERE ntimestamp# < sysdate-30;
END;
/

我不断收到的错误是

 alter session set container=select pdb_name from dba_pdbs where pdb_name != 'PDB$SEED'; * ERROR at line 1: ORA-65015: missing or invalid container name 

这告诉我,它不是将select语句的输出传递给$ FINDPDB,而是传递给实际的select语句本身。

我不明白为什么您会期望将SELECT查询的输出传递到$FINDPDB 您将一个很大的长字符串放在一起,bash传递给sqlplus的标准输入,然后将其写入sqlplus的输出。 bash绝不挑选sqlplus输出的某些行并将其放入shell变量中。

实际上,在调用sqlplus之前,尝试将echo $ALTER添加到bash脚本中。 您很可能会发现输出为

alter session set container=select pdb_name from dba_pdbs where pdb_name != 'PDB$SEED';

如果是这样,那么bash在开始sqlplus之前就已经完成了您不需要的替换。

您似乎希望bash和sqlplus具有某种来回对话框。 我会放弃这种方法。 与其尝试将PDB名称放入shell变量中,不如将其放入sqlplus替代变量中。 我会尝试以下类似方法(未经测试):

sqlplus -S /nolog <<"EOF1"
  connect / as sysdba
  set echo off feedback off head off pages 0
  set serveroutput on
  column pdb_name new_value pdb
  select pdb_name from dba_pdbs where pdb_name != 'PDB\$SEED';
  alter session set container = &pdb.;
  delete from sys.aud$ where ntimestamp# < sysdate - 30;
  exit;
EOF1

我们使用column pdb_name new_value pdb将替换变量pdb设置为要从名为pdb_name的列中选择的下一个值。 然后,我们运行一个select查询以获取PDB名称,并将其存储在pdb 一旦在替换变量中获得了该值,就可以发出alter session语句更改PDB,最后发出delete语句从PDB中删除数据。

我很想避免为此使用PL / SQL块,正如另一个答案中所建议的那样。 我希望在更改PDB之后解析delete语句,因为我想确保删除来自“正确” PDB的数据。 我对此使用PL / SQL的担心是,PL / SQL编译器将确定在解析该块时要从哪个表中删除该表,该表将在运行该块之前,因此在执行alter session语句以更改该表之前PDB。 但是,我对Oracle 12c中的PDB和CDB不够了解,无法说出这是一个真正的问题还是毫无根据的废话。

我无权访问可插拔的Oracle 12c数据库来对此类数据库进行运行,因此我无法告诉您此脚本是否有效。 如果没有,希望它可以使您知道去哪里。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM