[英]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实例,但是我看到两种方法可以做到这一点:
pdb_name
。 作为替代方式,我应该使用一种“真正的”编程语言(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.