简体   繁体   English

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

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

So what I'm trying to do is to clear the audit logs of the PDB in an Oracle database. 因此,我要做的是清除Oracle数据库中PDB的审核日志。 The name of the PDB can be different each time, so I cannot use tnsnames to sqlplus directly into the PDB to do this. PDB的名称每次都可以不同,因此我不能使用tnsnames将sqlplus直接输入PDB来执行此操作。 I'm passing commands into bash and then passing those into a SQLPLUS command. 我将命令传递到bash中,然后将其传递到SQLPLUS命令中。 Each of these work except for one and I can't seem to figure out how to get it to work. 所有这些工作都除一项之外,我似乎无法弄清楚如何使其工作。

My code is 我的代码是

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

The error I keep getting is 我不断收到的错误是

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

This tells me that it's not passing the output of the select statement to $FINDPDB, but rather the actual select statement itself. 这告诉我,它不是将select语句的输出传递给$ FINDPDB,而是传递给实际的select语句本身。

Is there a way I can pass this value to the ALTER variable and have it alter the session and clear the sys.aud$ table? 有没有一种方法可以将这个值传递给ALTER变量,并使它更改会话并清除sys.aud $表?

I have no Oracle instance at hand but I see two ways to do this : 我手头没有Oracle实例,但是我看到两种方法可以做到这一点:

  1. Make many connections through SQL*Plus 通过SQL * Plus建立许多连接
    1. First, to retrieve pdb_name . 首先,检索pdb_name
    2. Second, to set container and delete audits. 其次,设置容器并删除审核。
  2. Uses a single SQL*Plus but uses two named pipes 使用单个SQL * Plus,但使用两个命名管道
    1. One to send generated SQL commands 一个发送生成的SQL命令
    2. Second to read SQL*Plus output 秒读SQL * Plus输出

As alternative way I should have used a "real" programming language (Ruby, Python, JavaScript) which are better dedicated to deal with data read from database. 作为替代方式,我应该使用一种“真正的”编程语言(Ruby,Python,JavaScript),该语言更适合处理从数据库读取的数据。

EDIT: After some search, it mays be done in PL/SQL 编辑:经过一些搜索,它可能在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;
/

The error I keep getting is 我不断收到的错误是

 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 

This tells me that it's not passing the output of the select statement to $FINDPDB, but rather the actual select statement itself. 这告诉我,它不是将select语句的输出传递给$ FINDPDB,而是传递给实际的select语句本身。

I don't see why you would expect this to pass the output of the SELECT query into $FINDPDB . 我不明白为什么您会期望将SELECT查询的输出传递到$FINDPDB You're putting together a big long string which bash passes to the standard input of sqlplus and then writes to stdout the output from sqlplus. 您将一个很大的长字符串放在一起,bash传递给sqlplus的标准输入,然后将其写入sqlplus的输出。 At no point is bash picking out certain lines of the sqlplus output and putting them into shell variables. bash绝不挑选sqlplus输出的某些行并将其放入shell变量中。

In fact, try adding echo $ALTER to your bash script before you call sqlplus. 实际上,在调用sqlplus之前,尝试将echo $ALTER添加到bash脚本中。 You will quite probably find that the output is 您很可能会发现输出为

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

If so, then bash has already done the substitution you didn't want before you've even started sqlplus . 如果是这样,那么bash在开始sqlplus之前就已经完成了您不需要的替换。

You seem to want bash and sqlplus to have some kind of back-and-forth dialog. 您似乎希望bash和sqlplus具有某种来回对话框。 I would give up on this approach. 我会放弃这种方法。 Instead of trying to put the PDB name into a shell variable, I would put it into a sqlplus substitution variable. 与其尝试将PDB名称放入shell变量中,不如将其放入sqlplus替代变量中。 I would try something like the following (not tested): 我会尝试以下类似方法(未经测试):

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

We use column pdb_name new_value pdb to set the substitution variable pdb to the next value to be selected from a column named pdb_name . 我们使用column pdb_name new_value pdb将替换变量pdb设置为要从名为pdb_name的列中选择的下一个值。 We then run a select query to fetch the PDB name and hence store it in pdb . 然后,我们运行一个select查询以获取PDB名称,并将其存储在pdb Once we've got this value in a substitution variable, we can then issue the alter session statement to change the PDB and finally the delete statement to delete data from the PDB. 一旦在替换变量中获得了该值,就可以发出alter session语句更改PDB,最后发出delete语句从PDB中删除数据。

I'm tempted to avoid the use of a PL/SQL block for this, as has been suggested in another answer. 我很想避免为此使用PL / SQL块,正如另一个答案中所建议的那样。 I would prefer that the delete statement is parsed after the PDB is changed as I would want to be sure that the data from the 'correct' PDB is being deleted. 我希望在更改PDB之后解析delete语句,因为我想确保删除来自“正确” PDB的数据。 My concern with using PL/SQL for this is that the PL/SQL compiler would determine which table to delete from when the block is parsed, which would be before it runs the block, and hence before it executes the alter session statement to change the PDB. 我对此使用PL / SQL的担心是,PL / SQL编译器将确定在解析该块时要从哪个表中删除该表,该表将在运行该块之前,因此在执行alter session语句以更改该表之前PDB。 However, I don't know PDBs and CDBs in Oracle 12c well enough to say whether this is a genuine problem or unfounded nonsense. 但是,我对Oracle 12c中的PDB和CDB不够了解,无法说出这是一个真正的问题还是毫无根据的废话。

I don't have access to a pluggable Oracle 12c database to run something like this against, so I can't tell you whether this script works. 我无权访问可插拔的Oracle 12c数据库来对此类数据库进行运行,因此我无法告诉您此脚本是否有效。 If not, hopefully it should give you an idea of where to go. 如果没有,希望它可以使您知道去哪里。

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

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