Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将bash变量传递给sqlplus,然后将该输出传递给另一个变量_Sql_Linux_Oracle_Bash - Fatal编程技术网

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

如何将bash变量传递给sqlplus,然后将该输出传递给另一个变量,sql,linux,oracle,bash,Sql,Linux,Oracle,Bash,所以我要做的是清除Oracle数据库中PDB的审核日志。PDB的名称每次都可能不同,因此我无法使用tnsnames将sqlplus直接输入PDB来完成此操作。我将命令传递到bash中,然后将它们传递到SQLPLUS命令中。除了一个,所有这些都有效,我似乎不知道如何让它发挥作用 我的代码是 AUDIT="DELETE FROM SYS.AUD$ WHERE NTIMESTAMP# < sysdate-30;" FINDPDB="select pdb_name from dba_pdbs wh

所以我要做的是清除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
这告诉我,它不是将select语句的输出传递给$FINDPDB,而是传递实际的select语句本身


是否有一种方法可以将此值传递给ALTER变量,让它改变会话并清除sys.aud$表?

我手头没有Oracle实例,但我看到了两种方法:

通过SQL*Plus建立多个连接 首先,检索pdb_名称。 第二,设置容器并删除审核。 使用单个SQL*Plus,但使用两个 一个是发送生成的SQL命令 第二步读取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
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的输出写入stdout。bash并没有选择sqlplus输出的某些行并将它们放入shell变量中

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

alter session set container=select pdb_name from dba_pdbs where pdb_name != 'PDB$SEED';
如果是这样的话,那么在启动sqlplus之前,bash已经完成了您不想要的替换

您似乎希望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
我们使用列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数据库的权限来运行类似的操作,因此我无法告诉您该脚本是否有效。如果没有,希望它能让您知道该去哪里。

这给了我一个错误SP2-0042:未知命令TESTPDB-忽略行的其余部分。SP2-0042:未知命令PDB$SEED-忽略行的其余部分。alter会话集容器=