Shell脚本在Oracle数据库中的使用(一)

1、Oracle数据库内调用单个shell变量

lv_table=T1

sqlplus / as sysdba <<EOF    #<<EOF必须紧跟在上述命令后以一个空格分开
		select count(*) from $lv_table;
EOF

[oracle@lissen db_sh]$ ./exec_stats.sh 

SQL*Plus: Release 19.0.0.0.0 - Production on Sat Jun 1 23:15:00 2019
Version 19.2.0.0.0

Copyright (c) 1982, 2018, Oracle.  All rights reserved.

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.2.0.0.0

SYS@lissen>
  COUNT(*)
----------
	 2

SYS@lissen>Disconnected from Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.2.0.0.0

2、Oracle数据库读取多个shell变量

命令输入
<<EOF
EOF

[oracle@lissen db_sh]$ cat 1.sh

<<COMMENT
lv_table=T1

sqlplus / as sysdba <<EOF
select count(*) from $lv_table;
EOF
COMMENT

for i in T1 T2
do
sqlplus / as sysdba <<EOF
	select count(*) from $i;
EOF
done

[oracle@lissen db_sh]$ ./1.sh

SQL*Plus: Release 19.0.0.0.0 - Production on Sat Jun 1 23:25:22 2019
Version 19.2.0.0.0

Copyright (c) 1982, 2018, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.2.0.0.0

SYS@lissen>
  COUNT(*)
----------
	 2

SYS@lissen>Disconnected from Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.2.0.0.0

SQL*Plus: Release 19.0.0.0.0 - Production on Sat Jun 1 23:25:22 2019
Version 19.2.0.0.0

Copyright (c) 1982, 2018, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.2.0.0.0

SYS@lissen>
  COUNT(*)
----------
	32

SYS@lissen>Disconnected from Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.2.0.0.0

#!/bin/bash


lv_table=T1
lv_table2=T2

for i in $lv_table $lv_table2
do

sqlplus -S scott/scott@TNS_PDB01 <<EOF

	select count(*) from $i;
	exit;	

EOF

done

3、shell使用SQLPLUS –S进行查询

-S 静默查询

[oracle@lissen-node1 test_shell]$ sqlplus -S / as sysdba;


select count(*) from scott.t1;

  COUNT(*)
----------
	14

#取消查询输出的标题
set heading off;
select count(*) from scott.t1;

	14

set verify off;
select count(*) from scott.t1;

	14

#不设置页大小
set pagesize 0;
select count(*) from scott.t1;
	14

set echo off;
select count(*) from scott.t;

select count(*) from scott.t1;
	14

4、从数据库中读取查询结果并保存在SHELL变量中

#!/bin/bash

#resultCount=`sqlplus -S scott/scott@TNS_PDB01 <<EOF
#	set heading off;
#	set feedback off;
#	set pagesize 0;
#	select count(*) from t1;
#	exit;
#EOF`

#echo $resultCount

#如果使用$(命令)方式”)”必须处于当单独一行
resultCount=$(sqlplus -S scott/scott@TNS_PDB01 <<EOF
	set heading off;
	set feedback off;
	set pagesize 0;
	select count(*) from t1;
EOF 		
)		

echo $resultCount

5、读取数据库内数据到shell变量并用for循环输出

set heading off 	去掉表头
set feedback off	去掉数据下方的空白行
set pagesize 0		去掉数据上方的空白行

[oracle@lissen db_sh]$ cat 2.sh
#!/bin/bash


for i in `sqlplus -S / as sysdba <<EOF
	set heading off;
	set pagesize 0;
	set feedback off;
	set verify off;
	set echo off;
	select id from t1;
EOF`
do
	echo $i
done
[oracle@lissen db_sh]$ ./2.sh
1
2
3
4

6、使用系统文件内容做为shell变量查询数据库中表数据

[oracle@lissen db_sh]$ cat /home/oracle/db_sh/exec_table.txt
T1
T2
T3
[oracle@lissen db_sh]$ bash -n exec_stats.sh
[oracle@lissen db_sh]$ cat exec_stats.sh
#!/bin/bash

lv_table=$(cat /home/oracle/db_sh/exec_table.txt)

for i in $lv_table
do
	sqlplus -S / as sysdba <<EOF
	host echo "Begin select data from $i";
	select count(*) from $i;
	host echo "End select data from $i";
EOF
done
[oracle@lissen db_sh]$ ./exec_stats.sh
Begin select data from T1


  COUNT(*)
----------
	 4

End select data from T1

Begin select data from T2


  COUNT(*)
----------
	32

End select data from T2

Begin select data from T3


  COUNT(*)
----------
	 4

End select data from T3

7、 抓取Oracle数据库内的SYS用户中10天内未收集统计信息的表,并收集其统计信息
抓取Oracle数据库内的SYS用户中10天内未收集统计信息的表并保存到OS文件上

[oracle@lissen db_sh]$ cat 3.sh
#!/bin/bash

#select table_name from dba_tab_statistics where owner = 'SYS' and sysdate - last_analyzed > 10;

lv_file=`sqlplus -S / as sysdba <<EOF
	set heading off;
	set pagesize 0;
	set feedback off;
	select table_name from dba_tab_statistics where owner = 'SYS' and sysdate - last_analyzed > 10;
	exit;	
EOF`

<<COMMENT
for i in $lv_file
do
	echo $i
done
COMMENT


for i in $lv_file
do
	echo $i
done >> /home/oracle/db_sh/sys_table.txt

收集SYS用户10天内未收集统计信息的表的统计信息

查询SCOTT用户下1分钟内未收集统计或者重未收集过统计信息
SCOTT@dgpri>select owner,table_name,last_analyzed from dba_tab_statistics where owner = 'SCOTT' and (sysdate - last_analyzed > 1/(1*24*60) or last_analyzed is null);

OWNER	   TABLE_NAME	   LAST_ANALYZED
---------- --------------- -------------------
SCOTT	   DEPT 	   2019-06-17 10:50:03
SCOTT	   EMP		   2019-06-17 10:50:04
SCOTT	   BONUS	   2019-06-17 10:50:05
SCOTT	   SALGRADE	   2019-06-17 10:50:05
SCOTT	   T1

查询SCOTT用户下10天内未收集统计或者重未收集过统计信息
SCOTT@dgpri>select owner,table_name,last_analyzed from dba_tab_statistics where owner = 'SCOTT' and (sysdate - last_analyzed > 10 or last_analyzed is null);

OWNER	   TABLE_NAME	   LAST_ANALYZED
---------- --------------- -------------------
SCOTT	   T1


合并起来脚本为

lv_file=`sqlplus -S / as sysdba <<EOF
	set heading off;
	set pagesize 0;
	set feedback off;
	select table_name from dba_tab_statistics where owner = 'SYS' and sysdate - last_analyzed > 10;
	exit;	
EOF`

for i in $lv_file
do
	sqlplus -S / as sysdba <<EOF
	host echo "Begin gather $i statistics!";
	exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => '$i',estimate_percent => 100,method_opt => 'FOR ALL COLUMNS SIZE 1',cascade => true,no_invalidate => false);
	host echo "End gather $i statistics!";
EOF
done

8、 收集N天未收集统计信息的表并收集其统计信息

可以使用如下SQL查询来做测试
SYS@TNS_PDB01>select owner,table_name from dba_tab_statistics where table_name like 'T_';

OWNER	   TABLE_NAME
---------- ---------------
SCOTT	   	T1
SCOTT	   	T3
SCOTT	   	T2
SCOTT	   	T4
SYS	   		T5
SYS	   		T6

6 rows selected.

SYS@TNS_PDB01>select owner,table_name,last_analyzed from dba_tab_statistics where table_name like 'T_';

OWNER	   TABLE_NAME	   LAST_ANALYZED
---------- --------------- -------------------
SCOTT	   	T1		   2020-01-13 01:27:37
SCOTT	   	T3		   2020-01-13 01:27:37
SCOTT	   	T2		   2020-01-13 01:27:37
SCOTT	   	T4		   2020-01-13 01:27:38
SYS	   		T5		   2020-01-13 01:27:38
SYS	   		T6		   2020-01-13 01:27:39

相关查询系统统计信息收集语句

10分钟内收集过的统计信息
SCOTT@GGG1>select owner,table_name,last_analyzed from dba_tab_statistics where owner = 'SCOTT' and sysdate - last_analyzed < 10/(1*24*60) or last_analyzed is null;

OWNER	   TABLE_NAME	   LAST_ANALYZED
---------- --------------- -------------------
SCOTT	   T1		   2019-12-12 15:07:18

last_analyzed is null		//表示从未收集过统计信息的情况

10天内未收集过的统计信息
select owner,table_name,last_analyzed from dba_tab_statistics where owner = 'SCOTT' and sysdate - last_analyzed > 10 or last_analyzed is null;

收集10天内未收集过的统计信息的OWNER和TABLE_NAME脚本

#!/bin/bash

#默认情况下读取数据为空格修改默认变量IFS为换行符$’\n’
old_IFS=$IFS

IFS=$'\n'

lv_1=$(sqlplus -S / as sysdba <<EOF
	set heading off;
	set pagesize 0;
	set feedback off;
	column table_name format a35;
	column owner format a20;
	select owner,table_name from dba_tab_statistics where sysdate - last_analyzed > 10 and table_name not like 'X$%' order by last_analyzed ;	
EOF
)

for i in $lv_1
do
	echo $i
done > /home/oracle/test_sh/tab1.txt

IFS=$old_IFS

合并后脚本

[oracle@lissen db_sh]$ cat gather_stats.sh 
#!/bin/bash

#指定未收集统计信息的表到一个文件
file_name=/home/oracle/db_sh/tab.txt
old_IFS=$IFS

#指定换行符为读取一行的结尾默认为空格
IFS=$'\n'


if [ ! -f $file_name ];then
	touch $file_name
else
	rm -rf $file_name
	touch $file_name
fi

#使用变量lv_table收集从Oracle数据库返回的表和owner
lv_table=`sqlplus -S sys/oracle@TNS_PDB01 as sysdba <<EOF
	
#屏蔽select语句
	set pagesize 0;

#屏蔽受影响的行数
	set feedback off;
	column table_name format a35;

#SQL语句根据实际情况进行修改,这里做测试只抓起1天内未收集信息的表的前10行
	select distinct table_name,owner from dba_tab_statistics where ((sysdate - last_analyzed) > 1 or last_analyzed is null) and table_name not like 'X$%' and table_name not like 'WRI$%' and rownum < 11;
EOF` 

#遍历变量lv_table并将结果重定向到文件
for i in $lv_table
do
	echo $i
done > $file_name

#逐行读取文件$file_name中table_name和owner,以/n为分隔符号
while read line
do
	for i in $line
	do
		#echo "-----------------------"
		#echo -n "$counter: "
		#echo $i | awk '{print $2}'
		#echo 
		#echo -n "$counter: "
		#echo $i | awk '{print $1}'
		#let counter++
		sqlplus -S sys/oracle@TNS_PDB01 as sysdba <<EOF
		host echo "Begin gather `echo $i | awk '{print $2}'`'s `echo $i | awk '{print $1}'` stats!";
		exec dbms_stats.gather_table_stats(ownname => '`echo $i | awk '{print $2}'`',tabname => '`echo $i | awk '{print $1}'`',estimate_percent => 100,cascade => true);
		host echo "End gather `echo $i | awk '{print $2}'`'s `echo $i | awk '{print $1}'` stats!";
EOF
	done
	
done < $file_name


IFS=$old_IFS




#!/bin/bash

old_IFS=$IFS

file_name=/home/oracle/test_sh/tab1.txt

IFS=$'\n'


lv_1=$(sqlplus -S / as sysdba <<EOF
	set heading off;
	set pagesize 0;
	set feedback off;
	column table_name format a35;
	column owner format a20;
	select owner,table_name from dba_tab_statistics where sysdate - last_analyzed > 10 and table_name not like 'X$%' order by last_analyzed ;	
EOF
)

for i in $lv_1
do
	echo $i
done 1> $file_name 

while read line
do
	for i in $line
	do
		lv_owner=$(echo $i | awk '{print $1}')
		lv_table=$(echo $i | awk '{print $2}')
		sqlplus -S / as sysdba <<EOF
		host echo "Begin exec $lv_owner.$lv_table's statistics.";
		exec dbms_stats.gather_table_stats(ownname => '$lv_owner',tabname => '$lv_table',estimate_percent => 100,method_opt => 'FOR ALL COLUMNS SIZE 1',cascade => true,no_invalidate => false);
		host echo "End exec $lv_owner.$lv_table's statistics.";
EOF

	done
done 0< $file_name

IFS=$old_IFS
发布了6 篇原创文章 · 获赞 6 · 访问量 390

猜你喜欢

转载自blog.csdn.net/u011285708/article/details/103957330
今日推荐