感谢公司资助的Oracle培训,我自己也摸索学习了其中一些东西,整理了一篇小文章,希望能帮到大家。
目录
Oracle备份(Backup)与恢复(Recovery)方案
12c, 18c, 19c
12c版本号是12.1.0.2.0。
18c版本号是12.2.0.2,19c版本号是12.2.0.3,这两个年度版本仍然处于 12c 的发布序列中, 19c 属于 12c 体系的最后一个版本。
OCA/OCP 12c 认证
OCA 12c 认证包括 071, 062 两门认证考试
OCP 12c 认证包括 071, 062 & 063三门认证考试
071: Oracle Database SQL Exam
062: Oracle Database Installation and Adminstration
063: Oracle Database Advanced Adminstration
以下是知识点分类总结+自己的实操体会
(后续会从OneNote整理出来)
Oracle体系结构
Oracle12c体系结构:
Oracle11g体系结构:
Oracle逻辑结构
Oracle物理结构
Oracle内存结构
ASM(Automatic Storage Management, 自动存储管理)
Oracle备份(Backup)与恢复(Recovery)方案
RMAN
Oracle Secure Backup (OSB)
与RMAN一起,Oracle Secure Backup(OSB)将从FRA中提取RMAN备份,并将其复制到磁带设备或云存储中,以防止数据中心发生灾难性故障而丢失数据。OSB还在OS级别上提供了对RMAN的扩展,以备份Linux服务器以及诸如NAS设备之类的任何附加存储。
Oracle Data Guard
Oracle安装
Linux版已装过; Mac版用了最快的Docker方法, 起了个实例, 以下是Mac, Windows类似.(您可以先下载安装Mac/Windows Docker Desktop)
bethxfchen:~ cxf$ docker --version
Docker version 20.10.0, build 7287ab3
bethxfchen:~ cxf$ docker info
Client:
Context: default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Build with BuildKit (Docker Inc., v0.4.2-docker)
scan: Docker Scan (Docker Inc., v0.5.0)
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 20.10.0
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 269548fa27e0089a8b8278fc4fc781d7f65a939b
runc version: ff819c7e9184c13b7c2607fe6c30ae19403a7aff
init version: de40ad0
Security Options:
seccomp
Profile: default
Kernel Version: 4.19.121-linuxkit
Operating System: Docker Desktop
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 1.943GiB
Name: docker-desktop
ID: J7YZ:4YZP:B2NL:KWV5:Q7IC:GPTY:LLVA:CTUB:IGKW:AFCO:7MC3:CBNV
Docker Root Dir: /var/lib/docker
Debug Mode: true
File Descriptors: 40
Goroutines: 45
System Time: 2020-12-16T14:45:20.4562986Z
EventsListeners: 3
HTTP Proxy: gateway.docker.internal:3128
HTTPS Proxy: gateway.docker.internal:3129
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Product License: Community Engine
bethxfchen:~ cxf$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
bethxfchen:~ cxf$ docker login
Authenticating with existing credentials...
Login Succeeded
bethxfchen:~ cxf$ docker pull store/oracle/database-enterprise:12.2.0.1
12.2.0.1: Pulling from store/oracle/database-enterprise
4ce27fe12c04: Pull complete
9d3556e8e792: Pull complete
fc60a1a28025: Pull complete
0c32e4ed872e: Pull complete
b465d9b6e399: Pull complete
Digest: sha256:40760ac70dba2c4c70d0c542e42e082e8b04d9040d91688d63f728af764a2f5d
Status: Downloaded newer image for store/oracle/database-enterprise:12.2.0.1
docker.io/store/oracle/database-enterprise:12.2.0.1
bethxfchen:~ cxf$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
store/oracle/database-enterprise 12.2.0.1 12a359cd0528 3 years ago 3.44GB
bethxfchen:~ cxf$ docker run -d -it --name Oracle-DB -p 1521:1521/tcp store/oracle/database-enterprise:12.2.0.1
2fae09ee962d409fc41cdba57b2bb706bd1d7ab385b8668315356e7afd00cdef
bethxfchen:~ cxf$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2fae09ee962d store/oracle/database-enterprise:12.2.0.1 "/bin/sh -c '/bin/ba…" 17 seconds ago Up 16 seconds (health: starting) 0.0.0.0:1521->1521/tcp, 5500/tcp Oracle-DB
通过SQL Developer连接:
连接成功:
因为题目很多是会用到HR, 但Docker装的Oracle里默认没有Sample HR Schema, 所以docker exec -it Oracle-DB /bin/bash进入到Docker装的oracle env, sqlplus / as sysdba进入到SQL env后:
SQL> @?/demo/schema/human_resources/hr_main.sql就可以生成hr schema相关objects.
注意: 因为遇到了ORA-20000: Schema "HR" does not exist or insufficient privileges的问题,所以
alter session set "_ORACLE_SCRIPT"=true;
create user hr identified by hr;
drop user hr cascade;
@?/demo/schema/human_resources/hr_main.sql;
可以成功创建HR Sample Schema。
SQL> alter session set "_ORACLE_SCRIPT"=true;
Session altered.
SQL> create user hr identified by hr;
User created.
SQL> drop user hr cascade;
User dropped.
SQL> @?/demo/schema/human_resources/hr_main.sql
specify password for HR as parameter 1:
Enter value for 1: hr
specify default tablespeace for HR as parameter 2:
Enter value for 2: users
specify temporary tablespace for HR as parameter 3:
Enter value for 3: temp
specify log path as parameter 4:
Enter value for 4: $ORACLE_HOME/demo/schema/log/
PL/SQL procedure successfully completed.
验证如下:
Some OCA/OCP(071) Testing SQL
--------------------------------------------------------------分组函数 start---------------------------------------------------------
--count
select department_id from employees; --总共107行,第79行的department_id为null
select count(*) from employees; --107
--count(expr)返回expr非空的记录总数。
select count(department_id) from employees; --106
--count(distinct expr)返回expr非空且不重复的记录总数。
select count(distinct department_id) from employees; --11
select count(distinct last_name) from employees; --102
select distinct department_id from employees; --12,包括null值
select distinct job_id from employees; --19
select distinct job_id, department_id from employees; --20
select distinct department_id, job_id from employees; --20
--nvl
select commission_pct from employees;
--组函数忽略空值。
select avg(commission_pct) from employees; --0.2228571428571428571428571428571428571429
--在组函数中使用NVL函数, NVL函数使分组函数无法忽略空值。
select avg(nvl(commission_pct, 0)) from employees; --0.072897196261682242990654205607476635514
--avg, sum可以对数值型数据使用;min, max可以对任意数据类型数据使用。
select min(hire_date), max(hire_date) from employees;
select min(first_name) from employees; --Adam
--在select列表中所有未包含在组函数中的列都应该包含在group by子句中。
select department_id, avg(salary) from employees group by department_id;
--包含在group by子句中的列不必包含在select列表中。
select avg(salary) from employees group by department_id;
--使用多个列分组,在group by子句中包含多个列。
select department_id, job_id,sum(salary) from employees group by department_id, job_id;
--不能在where子句中使用组函数。可以在having子句中使用组函数。
--比如下面这句就不对:
select department_id, avg(salary) from employees where avg(salary) >8000 group by department_id;
--过滤分组:使用having。
select job_id, sum(salary) payroll from employees where job_id not like '%REP%' group by job_id having sum(salary)>13000 order by sum(salary);
--嵌套组函数
select max(avg(salary)) from employees group by department_id;
select max(salary) from employees group by salary; --multiple values
select avg(max(salary)) from employees group by salary; --7067.379310344827586206896551724137931034
select department_id, sum(salary) from employees where hire_date<'01-JAN-19' group by department_id;
select department_id, sum(salary) from employees group by department_id;
select department_id, max(sum(salary)) from employees group by department_id; --ORA-00937: not a single-group group function
select department_id, max(salary) from employees group by department_id;
select department_id, avg(salary) from employees group by department_id;
select department_id, max(avg(salary)) from employees group by department_id; --ORA-00937: not a single-group group function
select department_id, avg(max(salary)) from employees group by department_id, salary; --ORA-00937: not a single-group group function
select department_id, avg(max(salary)) from employees group by department_id having hire_date<'01-JAN-19'; --ORA-00937: not a single-group group function
--题目中以下四个语句中错的是第一句
--ORA-00934: group function is not allowed here
select department_id, count(*) from employees where department_id <> 90 and count(*) >=3 group by department_id;
--以下三句是可以的,where是对分组前进行过滤,having是对分组后进行过滤,group by和having顺序没有限制
select department_id, count(*) from employees where department_id <> 90 having count(*) >=3 group by department_id;
select department_id, count(*) from employees having department_id <> 90 and count(*) >= 3 group by department_id;
select department_id, count(*) from employees where department_id <> 90 group by department_id having count(*) >=3;
--------------------------------------------------------------分组数据 end---------------------------------------------------------
--------------------------------------------------------------连接 start---------------------------------------------------------
--(+)外连接的符号
select * from employees e, departments d where e.department_id = d.department_id;
--SQL:1999语法连接
select * from employees e join departments d on e.department_id = d.department_id;
--增加连接条件
select * from employees e join departments d on e.department_id = d.department_id and e.manager_id = 149;
select * from employees e join departments d on (e.department_id = d.department_id) and e.manager_id = 149;
select * from employees e join departments d on e.department_id = d.department_id where e.manager_id = 149;
--或
select * from employees e join departments d using (department_id);
select * from employees e join departments d using (department_id) and e.manager_id = 149; --ORA-00933: SQL command not properly ended
-- full/left/right <outer> join; natural join会以两个表中具有相同名字的列为条件创建等值连接,如果只是列名相同而数据类型不同,则会产生错误;cross join叉集就是笛卡尔集。
select count(*) from "123"; --5
select count(*) from employees; --107
select * from "123", employees; --535行的数据
select count(*) from "123", employees; --535
--------------------------------------------------------------连接 end---------------------------------------------------------
--------------------------- --------------------------------- NVL & NVL2 & NULLIF & coalesce start ----------------------------------------------------------------------------------------------------
--NVL & NVL2 & NULLIF & coalesce:
--(1)NVL(expr1,expr2),将空值替换成一个值,若expr1为null, 返回expr2; 不为null,返回expr1。
-- 数据类型可以是日期,数字,字符。
-- 数据类型必须匹配:
-- nvl(commision,0)
-- nvl(hiredate,'01-JAN-87')
-- nvl(job_id,'no manager') nvl(to_char(job_id),'no manager')
-- nvl能够转换任何数据类型,但是转换的数据类型返回值必须是nvl(expr1,expr2)第一个参数expr的类型。如:date,number, varchar2 or char
select NVL(commission_pct, 0) from employees;
select NVL('DATE', SYSDATE) from dual;
select NVL('DATE', 200) from (select null as "DATE" from dual);
--(2)NVL2 (expr1, expr2, expr3),通俗的理解就是一个值非不非空都替换,非空是一个,空是另一个;若expr1不为NULL,返回expr2 ;为NULL,返回expr3。注意:expr2 和expr3 类型不同的话,expr3 会转换为expr2 的类型
SELECT NVL2(commission_pct, commission_pct*100, 0) FROM employees;
select hire_date from employees;
SELECT EMPLOYEE_ID, NVL2(HIRE_DATE, SYSDATE - HIRE_DATE, SYSDATE) from employees;
select EMPLOYEE_ID, NVL2(EMPLOYEE_ID, EMPLOYEE_ID*.25, "Not Available") from employees; --ORA-00904: "Not Available": invalid identifier
--(3)NULLIF (expr1, expr2),通俗的理解就是对比两个值相不相等;expr1和expr2相等时,返回结果null, 不相等时返回expr1
select NULLIF(length(first_name),length(last_name)) result from employees;
--(4)coalesce用途
select * from employees; --总共107行,第79行的department_id为null
--coalesce用途1:将控制替换成其他值;
select coalesce(department_id,1) from employees; --总共107行,第79行的department_id为1
--coalesce用途2:返回第一个非空值
select coalesce(commission_pct,salary,10) from employees;
select coalesce('DATE', SYSDATE) from dual; --ORA-00932: inconsistent datatypes: expected CHAR got DATE
--------------------------- --------------------------------- NVL & NVL2 & NULLIF & coalesce end ----------------------------------------------------------------------------------------------------
--------------------------- --------------------------------- 日期/时间 start ----------------------------------------------------------------------------------------------------
--日期函数 默认的日期格式是DD-MON-RR
select months_between('01-SEP-95','11-JAN-94') from dual; -- 19.67741935483870967741935483870967741935
select add_months(sysdate,-2) from dual;
select next_day('19-DEC-2020', 'FRIDAY') from dual; -- 25-DEC-20
select last_day(sysdate) from dual;
select last_day(to_date('1992-10-09','yyyy-mm-dd')) from dual;
select round(sysdate, 'MONTH') from dual; -- 01-JAN-21
select trunc(sysdate, 'MONTH') from dual; -- 01-DEC-20
--timestamp & timezone & date
select current_timestamp from dual; --20-DEC-20 10.50.19.189027000 PM ASIA/SHANGHAI
select sessiontimezone from dual; --Asia/Shanghai
select LOCALTIMESTAMP from dual; --28-DEC-20 05.28.23.897737000 PM
select SYSTIMESTAMP from dual; --28-DEC-20 09.28.32.197928000 AM GMT
select dbtimezone from dual; --+00:00
select current_date from dual; --20-DEC-20
select SYSDATE from dual; --20-DEC-20
alter session set NLS_DATE_FORMAT='DD-MON-YYYY HH24:MI:SS';
select current_date from dual; --05-JAN-2021 23:10:02
select SYSDATE from dual; --05-JAN-2021 15:10:29
select DATE'2017-08-01' from dual; --01-AUG-17
SELECT (SYSDATE-DATE'2019-01-01')/1 FROM DUAL;
SELECT SYSDATE-DATE'2019-01-01'-1 FROM DUAL;
SELECT SYSDATE-1-DATE'2019-01-01' FROM DUAL; --SYSDATE-1查询结果是20-DEC-20
select round(sysdate - to_date('01-JAN-2019')) from dual; --739
select round(sysdate - to_date('01/JANUARY/2019')) from dual; --739
select round(sysdate - '01-JAN-2019') from dual; --ORA-01722: invalid number
select trunc(sysdate - to_date('01-JAN-2019')) from dual; --739
select trunc(sysdate) from dual; --09-JAN-21
select round(sysdate) from dual; --09-JAN-21
alter session set nls_date_format='DD-MM-YYYY';
select to_date('29-10-2019') + INTERVAL '2' MONTH from dual; --29-12-2019
select to_date('29-10-2019') + INTERVAL '2' MONTH + INTERVAL '5' DAY from dual; --03-01-2020
select INTERVAL '120' SECOND from dual; --+00 00:02:00.000000
select to_date('29-10-2019') + INTERVAL '2' MONTH + INTERVAL '5' DAY - INTERVAL '120' SECOND from dual; --02-01-2020
select to_char(to_date('29-10-2019') + INTERVAL '2' MONTH + INTERVAL '5' DAY - INTERVAL '120' SECOND, 'DD-MON-YYYY') as "date" from dual; --03-01-2020相当于03-01-2020 00:00:00,减去120秒也是02-01-2020
select to_char(INTERVAL '800' SECOND, 'HH24:MM') from dual; --+00 00:13:20.000000
select to_date(INTERVAL '800' SECOND, 'HH24:MM') from dual; --ORA-01843: not a valid month
select to_number(INTERVAL '800' SECOND, 'HH24:MM') from dual; --ORA-01481: invalid number format model
select to_date(to_number(INTERVAL '800' SECOND, 'HH24:MM')) from dual; --ORA-01481: invalid number format model
select to_number(to_date(INTERVAL '800' SECOND, 'HH24:MM')) from dual; --ORA-01843: not a valid month
select to_date('2019-DEC-25 15:30', 'YYYY-MON-DD HH24:MI', 'NLS_DATE_LANGUAGE = AMERICAN') from dual; --25-DEC-19
select to_char(to_date('2019-DEC-25 15:30', 'YYYY-MON-DD HH24:MI')) from dual; --25-DEC-19
select salary from employees where hire_date > '01-03-2019'; --日期格式有问题,ORA-01843: not a valid month
select salary from employees where hire_date < '01-march-2019';
select SYSTIMESTAMP from dual; --02-JAN-21 02.05.13.650093000 AM GMT
select SYSTIMESTAMP + INTERVAL '0 12' DAY TO HOUR from dual; --02-JAN-21 02.05.24.311813000 PM GMT
--Set the time zone at database level (alter database)
select dbtimezone from dual; --+00:00
alter database set time_zone='Europe/London'; --OR alter database set time_zone='-08:00';
----restart the database: Shutdown immediate; => startup
SELECT dbtimezone FROM DUAL; --Europe/London
--Set the time zone at session level (alter session)
--alter session set time_zone=local;
--alter session set time_zone=dbtimezone;
alter session set time_zone='Asia/Hong_Kong'; --OR alter session set time_zone='+08:00';
select sessiontimezone from dual; --Asia/Hong_Kong
--------------------------- --------------------------------- 日期/时间 end ----------------------------------------------------------------------------------------------------
--------------------------- --------------------------------- 相关/关联子查询 start ----------------------------------------------------------------------------------------------------
create table orders(
customer_name varchar2(8),
customer_id number
);
create table customers(
customer_id number,
cust_last_name varchar2(8)
);
insert into orders(customer_name, customer_id) values('o1', 10);
insert into orders(customer_name, customer_id) values('o2', 20);
insert into orders(customer_name, customer_id) values('o3', 30);
insert into orders(customer_name, customer_id) values('o4', 40);
commit;
select * from orders;
insert into customers(cust_last_name, customer_id) values('c1', 10);
insert into customers(cust_last_name, customer_id) values('c2', 20);
insert into customers(cust_last_name, customer_id) values('c3', 30);
commit;
select * from customers;
--All existing rows in the ORDERS table are updated. The subquery is executed for every updated row in the ORDERS table.
update orders o set customer_name = (select cust_last_name from customers where customer_id = o.customer_id); --4 rows updated.
select * from orders; --customer_name四行的结果分别是c1 c2 c3 (null)
create table customers_history as select * from customers;
select * from customers_history;
insert into customers_history values(50, 'c5'); --customers_history四行,customers三行
commit;
delete from customers c where exists (select 'dummy' from customers_history where customer_id=c.customer_id); --3 rows deleted. customers三行被删掉了
rollback;
select * from customers;
select * from customers_history;
insert into customers values(60, 'c6'); --customers_history四行,customers三行
commit;
--相关子查询,只会将父表中匹配条件的行记录删除,保留其他行。
--The subquery is executed for every row in the CUSTOMERS table.
delete from customers c where exists (select 'dummy' from customers_history where customer_id=c.customer_id); --3 rows deleted. customers三行被删掉了,剩下60,c6一行
--------------------------- --------------------------------- 相关/关联子查询 end ----------------------------------------------------------------------------------------------------
--------------------------- --------------------------------- 事务 start ----------------------------------------------------------------------------------------------------
insert into "123" values('c');
savepoint a;
delete from "123";
rollback to savepoint a;
rollback;
--测试transaction
insert into "123" values('b');
select xid, status from v$transaction; --0F000800E8010000 ACTIVE
truncate table "123";
select * from "123"; --truncated, no data.
select xid, status from v$transaction; --no data.
insert into "123" values('b');
select xid, status from v$transaction; --13001B00D2010000 ACTIVE
insert into "123" values('d');
select xid, status from v$transaction; --13001B00D2010000 ACTIVE
rollback;
select xid, status from v$transaction; --no data.
insert into "123" values('a');
select xid, status from v$transaction; --0E000600D6010000 ACTIVE
insert into "123" values('b');
select xid, status from v$transaction; --0E000600D6010000 ACTIVE
commit;
select xid, status from v$transaction; --no data.
insert into "123" values('e');
select xid, status from v$transaction; --13001900CF010000 ACTIVE
insert into "123" values('e', 'f'); --SQL Error: ORA-00913: too many values
select xid, status from v$transaction; --13001900CF010000 ACTIVE
insert into "123" values('f');
select xid, status from v$transaction; --13001900CF010000 ACTIVE
delete from "123" where test='a';
select xid, status from v$transaction; --13001900CF010000 ACTIVE
create table test_transaction as select * from "123";
select xid, status from v$transaction; --no data.
select * from "123"; -- e, f were inserted. a was deleted.
insert into "123" values('a');
select xid, status from v$transaction; --0F000F00EC010000 ACTIVE
select * from "123" for update;
create table test_transaction1 as select * from "123";
select xid, status from v$transaction; --no data
insert into "123" values('a');
select xid, status from v$transaction; --0A000F00DC010000 ACTIVE
create index test_index on "123" (test);
select xid, status from v$transaction; --no data
create table test_table1 (
column1 varchar2(2),
column2 number
);
select xid, status from v$transaction; --no data
--------------------------------------------------------------事务 end---------------------------------------------------------
--------------------------------------------------------------转义 start---------------------------------------------------------
--escape
select 'The first_name is ' || first_name || '' from employees; --The first_name is Ellen
select 'The first_name is ''' || first_name || '''' from employees; --The first_name is 'Ellen'
select 'The first_name is ''' || first_name || ''' from employees; --ORA-01756: quoted string not properly terminated
select 'The first_name is '' || first_name || '' from employees; --ORA-01756: quoted string not properly terminated
select 'The first_name is \'' || first_name || '\'' from employees; --ORA-00911: invalid character *Cause: The identifier name started with an ASCII character other than a letter or a number. After the first character of the identifier name, ASCII characters are allowed including "$", "#" and "_".
--The most simple and most used way to escape in strings
SELECT 'test single quote''' from dual; --test single quote'
SELECT '''test single quote''' from dual; --'test single quote'
--q'!!'; q'[]'; q'{}'; q'()'; q'<>'五种符号都可以
select q'!Hello! We're ready!' from dual; --Hello! We are ready
select q'[Hello! We're ready]' from dual; --Hello! We are ready
--下面这两种都不行
--select '[Hello! We\'re ready]' escape '\' from dual; --ORA-00923: FROM keyword not found where expected
select "Hello! We're ready" from dual; --ORA-00904: "Hello! We're ready": invalid identifier
--------------------------------------------------------------转义 end---------------------------------------------------------
--------------------------------------------------------------Merge start---------------------------------------------------------
--Merge:
-- 语法如下:
-- MERGE INTO table_name alias1
-- USING (table|view|sub_query) alias2
-- ON (join condition)
-- WHEN MATCHED THEN
-- UPDATE table_name
-- SET col1 = col_val1,
-- col2 = col2_val
-- WHEN NOT MATCHED THEN
-- INSERT (column_list) VALUES (column_values);
-- UPDATE子句后面可以跟DELETE子句来去除一些不需要的行
-- UPDATE或INSERT子句是可选的
--------------------------------------------------------------Merge end---------------------------------------------------------
--------------------------------------------------------------All set operators(UNION, UNION ALL, INTERSECT and MINUS) start---------------------------------------------------------
--Union/union all:
-- The first column in the first select of the compound query with the union operator issued by default to sort output in the absence of an order by clause.
-- Only column names from the first select statement in the compound query are recognized.
-- All set operators(UNION, UNION ALL, INTERSECT and MINUS) are valid on columns of all data types.
-- The data type of each column returned by the second query must be implicitly convertible to the data type of the corresponding column returned by the first query
-- The number, but not names of columns must be identical for all SELECT statements in the query
-- UNION ALL
-- NULLS are not ignored during duplicate checking
-- The number of columns selected in each SELECT statement must be identical
--INTERSECT
-- returns rows common to both sides of the compound query.
SELECT 1 AS id, 'John' AS first_name, NULL AS commission FROM dual INTERSECT
SELECT 1,'John', null FROM dual ORDER BY 3;
-- What is returned upon execution?[
-- D) 1 ROW
-- (1)Column names in each SELECT in the compound query can be different.
-- (2)The number of columns and data types must be identical for all SELECT statements in the query
--INTERSECT does not ignore NULLs
SELECT COL1 FROM (SELECT 1 COL1 FROM DUAL UNION ALL
SELECT 1 FROM DUAL UNION ALL
SELECT NULL FROM DUAL)
INTERSECT
SELECT COL2 FROM (SELECT NULL COL2 FROM DUAL UNION ALL
SELECT 1 FROM DUAL UNION ALL
SELECT NULL FROM DUAL)
ORDER BY 1 NULLS FIRST;
--------------------------------------------------------------All set operators(UNION, UNION ALL, INTERSECT and MINUS) end---------------------------------------------------------
--------------------------------------------------------------系统视图 start---------------------------------------------------------
select * from session_privs;
select * from user_synonyms;
select * from user_objects;
select * from dictionary;
--------------------------- --------------------------------- 系统视图 end ----------------------------------------------------------
--------------------------------------------------------------其他 start---------------------------------------------------------
--order by
--(1)多个列排序 order by department_id, salary desc: 是在第一列department_id asc的前提下, 第一列相等时,才按照第二列salary desc
select last_name, department_id, salary from employees order by department_id, salary desc;
--(2)order by后可以用别名,可以按照别名排序;Table aliases can improve performance.
select last_name, department_id, salary s from employees order by s desc;
select department_id AS "Department", avg(salary) AverageSalary, max(salary) AS "Max Salary" from employees where salary>=12000 group by department_id order by AverageSalary;
--(3)group by后不能用别名
select department_id AS "Department", avg(salary) AverageSalary, max(salary) AS "Max Salary" from employees where salary>=12000 group by "Department" order by AverageSalary;
--(4)order by后如果加1、2等数字看第一个select语句的column顺序
--(5)多个select时,order by放最后select
--(6)order by排序时是大小写敏感的,order by XXX默认asc先按大写A到Z,再小写a到z。
update employees set first_name=lower(first_name) where first_name like 'E%';
update employees set first_name=lower(first_name) where first_name like 'S%';
select first_name from employees order by first_name;
--where里不要用别名
select last_name, 12*salary as annual_salary from employees where 12*salary > 100000 order by annual_salary;
--下面两种都报错:ORA-00904: "ANNUAL_SALARY": invalid identifier
select last_name, 12*salary as annual_salary from employees where annual_salary > 100000 order by annual_salary;
select last_name, 12*salary as annual_salary from employees where annual_salary > 100000 order by 12*salary;
--字符数字控制函数
SELECT concat('Hello','World') FROM dual;
--0和1都是表示截取的开始位置为第一个字符; 以及length
SELECT substr('HelloWorld',0,5) FROM dual;
SELECT substr('HelloWorld',1,5) FROM dual;
SELECT instr('HelloWorld','H') FROM dual; -- 1
SELECT length('HelloWorld') FROM dual;
SELECT lpad(salary, 10, '*') FROM employees;
SELECT rpad(salary, 10, '*') FROM employees;
SELECT upper(last_name) FROM employees; -- or lower, initcap
--round四舍五入&trunc截断,expr2默认是0,可正可负,0是个位数,以此为分界点,数字往左是负数
select round(45.923, -1) from dual;
select trunc(45.923, -2) from dual;
--mod取余
--数据类型转换 0和9均可代表数字,L是本地货币符号,逗号是千位符
SELECT to_char(salary,'$99,999,00') FROM employees;
SELECT to_char(salary,'L00,000.00') FROM employees;
SELECT to_char(hire_date,'MON DD, YYYY') FROM employees; -- JUN 17, 2003;如果写MONTH是月份全拼
--注意是HH24:MI:SS
SELECT to_char(sysdate,'HH24:MI:SS AM, DAY') FROM dual; -- 12:11:12 PM, FRIDAY
select salary from employees where salary between '4000' and '8000'; --隐式转换
--包含空值的数学表达式的值都为空值
select last_name || 12*salary*commission_pct from employees where commission_pct is null;
--注意可以这么用
SELECT DISTINCT * FROM employees WHERE first_name IS NOT NULL;
--条件表达式
--(1)case是IF-THEN-ELSE逻辑
select last_name, job_id, salary,
case job_id when 'IT_PROG' then 1.10*salary
when 'ST_CLERK' then 1.15*salary
when 'SA_REP' then 1.20*salary
else salary end "revised_salary"
from employees;
--(2)decode是IF-THEN-ELSE逻辑:decode(col|expr, search1, result1[,search2, result1,...,][,default])
--以下两个查询返回相同的结果:all rows for employees whose salary is greater than the average salary in their department
select * from employees e1 where salary > (select avg(salary) from employees e2 where e1.department_id=e2.department_id);
--over(partition by XXX)
select * from (select e.*, avg(salary) over(partition by department_id) avg_sal from employees e) where salary > avg_sal;
drop table "123";
create table "123" (
test varchar2(10)
); --create时不加引号和单引号都不可以
insert into "123" values('a');
insert into "123" values('b');
commit;
select * from 123; --不加引号和单引号都不可以
select * from '123'; --不加引号和单引号都不可以
select * from \'123\'; --加转义符号也不可以
select * from "123";
delete from "123" where test='a';
delete "123" where test='b';
delete from "123";
truncate table "123";
create table "123" (
testNum number(6,2) NOT NULL
);
desc "123";
INSERT INTO "123" VALUES (-.9); --0.9
INSERT INTO "123" VALUES (0.999); --1
commit;
create table "new_123" as select * from "123";
desc "new_123"; -- 新表也有NOT NULL constraint
INSERT INTO "123" VALUES (-.9); --0.9
INSERT INTO "123" VALUES (0.999); --1
INSERT INTO "123" VALUES (0.551);
INSERT INTO "123" VALUES (-10);
create or replace view view_123 as select * from "123";
create or replace view view_123_b as select * from "123" where test='b';
select * from view_123;
select * from view_123_b;
--purge
drop table "123" purge; --table和所有的views都会删除,不能rollback
--accessible to all users: PUBLIC
CREATE PUBLIC SYNONYM emp FOR hcm.Employee_records;
--Which two are true about external tables that use the ORACLE_DATAPUMP access driver?
--A)When creating an external table, data can be selected from another external table or from a
--table whose rows are stored in database blocks
--B) Creating an external table creates a dump file that can be used by an external table in the
--same or a different database
--测试返回结果是否相同
select emp.* from employees emp
join employees mgr
on emp.manager_id=mgr.employee_id
and emp.department_id <> mgr.department_id; --18 rows
select emp.* from employees emp
right join employees mgr
on emp.manager_id=mgr.employee_id
and emp.department_id <> mgr.department_id
where emp.employee_id is not null; --18 rows
select emp.* from employees emp
left join employees mgr
on emp.manager_id=mgr.employee_id
and emp.department_id <> mgr.department_id; --107 rows
select emp.* from employees emp where manager_id not in (select mgr.employee_id from employees mgr where emp.manager_id<>mgr.manager_id); --15 rows
select mgr.* from employees mgr where manager_id not in (select emp.employee_id from employees emp where emp.manager_id<>mgr.manager_id); --15 rows
--------------------------------------------------------------其他 end---------------------------------------------------------
Some DBA SQL
--oracle lock
SELECT c.owner
,c.object_name
,c.object_type
,b.sid
,b.serial#
,b.status
,b.osuser
,b.machine
FROM v$locked_object a
,v$session b
,dba_objects c
WHERE b.sid = a.session_id
AND a.object_id = c.object_id;
--oracle long query
SELECT s.username,
sl.sid,
sq.executions,
sl.last_update_time,
sl.sql_id,
sl.sql_hash_value,
opname,
target,
elapsed_seconds,
time_remaining,
sq.sql_fulltext
FROM v$session_longops sl
INNER JOIN v$sql sq ON sq.sql_id = sl.sql_id
INNER JOIN v$session s ON sl.SID = s.SID AND sl.serial# = s.serial#
WHERE time_remaining > 0;
--oracle active session
SELECT s.sid sid
,sa.sql_id
,s.serial# serial_id
,s.status session_status
,s.username oracle_username
,s.osuser os_username
,p.spid os_pid
,s.machine session_machine
,s.program session_program
,s.client_info
,s.sql_exec_start
,substr(sa.sql_text, 1, 1024) current_sql
FROM gv$process p, gv$session s, gv$sqlarea sa
WHERE p.addr(+) = s.paddr
AND s.sql_address = sa.address(+)
AND s.sql_hash_value = sa.hash_value(+)
AND s.username IS NOT NULL
AND s.status = 'ACTIVE'
ORDER BY sid;
查询结果局部截图:
--oracle tablespace
SELECT /* + RULE */ df.tablespace_name "Tablespace",
df.bytes / (1024 * 1024) "Size (MB)",
SUM(fs.bytes) / (1024 * 1024) "Free (MB)",
Nvl(Round(SUM(fs.bytes) * 100 / df.bytes),1) "% Free",
Round((df.bytes - SUM(fs.bytes)) * 100 / df.bytes) "% Used"
FROM dba_free_space fs,
(SELECT tablespace_name,SUM(bytes) bytes
FROM dba_data_files
GROUP BY tablespace_name) df
WHERE fs.tablespace_name (+) = df.tablespace_name
GROUP BY df.tablespace_name,df.bytes
UNION ALL
SELECT /* + RULE */ df.tablespace_name tspace,
fs.bytes / (1024 * 1024),
SUM(df.bytes_free) / (1024 * 1024),
Nvl(Round((SUM(fs.bytes) - df.bytes_used) * 100 / fs.bytes), 1),
Round((SUM(fs.bytes) - df.bytes_free) * 100 / fs.bytes)
FROM dba_temp_files fs,
(SELECT tablespace_name,bytes_free,bytes_used
FROM v$temp_space_header
GROUP BY tablespace_name,bytes_free,bytes_used) df
WHERE fs.tablespace_name (+) = df.tablespace_name
GROUP BY df.tablespace_name,fs.bytes,df.bytes_free,df.bytes_used
ORDER BY 4 DESC;
查询结果:
--oracle table size
SELECT * FROM (
SELECT DS.TABLESPACE_NAME,
SEGMENT_NAME,
ROUND(SUM(DS.BYTES) / (1024 * 1024)) AS SIZEINMB
FROM DBA_SEGMENTS DS
WHERE SEGMENT_NAME IN (SELECT TABLE_NAME FROM DBA_TABLES)
GROUP BY DS.TABLESPACE_NAME,
SEGMENT_NAME
ORDER BY SIZEINMB DESC)
WHERE ROWNUM<=100;
查询结果局部截图:
--oracle block(locked object)
SELECT SUBSTR(TO_CHAR(w.session_id),1,5) "WSid",
P1.spid "WPid",
SUBSTR(s1.username,1,12) "WAITING User",
SUBSTR(s1.osuser,1,8) "OS User",
SUBSTR(s1.program,1,20) "WAITING Program",
s1.client_info "WAITING Client",
SUBSTR(TO_CHAR(h.session_id),1,5) "HSid",
P2.spid "HPid",
SUBSTR(s2.username,1,12) "HOLDING User",
SUBSTR(s2.osuser,1,8) "OS User",
SUBSTR(s2.program,1,20) "HOLDING Program",
s2.client_info "HOLDING Client",
o.object_name "HOLDING Object"
FROM v$process P1, v$process P2, v$session S1,
v$session S2, dba_locks w, dba_locks h, dba_objects o
WHERE w.last_convert > 120
AND h.mode_held != 'None'
AND h.mode_held != 'Null'
AND w.mode_requested != 'None'
AND s1.row_wait_obj# = o.object_id
AND w.lock_type(+) = h.lock_type
AND w.lock_id1(+) = h.lock_id1
AND w.lock_id2 (+) = h.lock_id2
AND w.session_id = S1.sid (+)
AND h.session_id = S2.sid (+)
AND S1.paddr = P1.addr (+)
AND S2.paddr = P2.addr (+)
ORDER BY w.last_convert desc;
--db host cpu
select value busy, inst_id from gv$sysmetric where metric_name='Host CPU Utilization (%)' and group_id=2
查询结果:
--db total size
select sum(round(bytes/(1024*1024),2))/1024 sizeinmb from dba_segments where segment_type in ('TABLE', 'TABLE PARTITION', 'TABLE SUBPARTITION') order by bytes desc
查询结果:
--other common query
select * from dba_objects;
show parameters;
select * from v$sql;
select * from v$sysstat;
select * from v$segment_statistics;
select * from v$active_session_history;
select * from dba_tab_stats_history;
-- 联机重做日志
select group#, sequence#, members, status from v$log;
alter system switch logfile;
select group#, member, status from v$logfile;
select * from v$log join v$logfile using (group#);
alter database add logfile member '/u04/app/oracle/redo/redo001a.log' to group 1;
alter database add logfile member '/u04/app/oracle/redo/redo002a.log' to group 2;
alter database add logfile member '/u04/app/oracle/redo/redo003a.log' to group 3;
select * from v$logfile;
-- 控制文件
select name from v$controlfile;
select value from v$parameter2 where name = 'control_files';
-- 归档日志
select log_mode from v$database;
select archiver from v$instance;
alter system archive log current;
select name, is_recovery_dest_file from v$archived_log;
-- 快速恢复区
select * from v$recovery_file_dest;
select * from v$recovery_area_usage;
select name, value from v$parameter where name like 'db_recovery%';
alter system set db_recovery_file_dest_size = 10g;
Generate AWR report
[oracle@28d4718eb450 oracle]$ sqlplus / as sysdba
SQL*Plus: Release 12.2.0.1.0 Production on Mon Sep 14 09:52:14 2020
Copyright (c) 1982, 2016, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> @$ORACLE_HOME/rdbms/admin/awrrpt.sql
Specify the Report Type
~~~~~~~~~~~~~~~~~~~~~~~
AWR reports can be generated in the following formats. Please enter the
name of the format at the prompt. Default value is 'html'.
'html' HTML format (default)
'text' Text format
'active-html' Includes Performance Hub active report
Enter value for report_type: html
old 1: select 'Type Specified: ',lower(nvl('&&report_type','html')) report_type from dual
new 1: select 'Type Specified: ',lower(nvl('html','html')) report_type from dual
Type Specified: html
old 1: select '&&report_type' report_type_def from dual
new 1: select 'html' report_type_def from dual
old 1: select '&&view_loc' view_loc_def from dual
new 1: select 'AWR_PDB' view_loc_def from dual
Current Instance
~~~~~~~~~~~~~~~~
DB Id DB Name Inst Num Instance Container Name
-------------- -------------- -------------- -------------- --------------
2722566360 ORCLCDB 1 ORCLCDB CDB$ROOT
Instances in this Workload Repository schema
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DB Id Inst Num DB Name Instance Host
------------ ---------- --------- ---------- ------
1465335565 1 ORCL ORCL dc6573fc4856
2722566360 1 ORCLCDB ORCLCDB ea25ab458e7a
* 2722566360 1 ORCLCDB ORCLCDB 28d4718eb450
Using 2722566360 for database Id
Using 1 for instance number
Specify the number of days of snapshots to choose from
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Entering the number of days (n) will result in the most recent
(n) days of snapshots being listed. Pressing <return> without
specifying a number lists all completed snapshots.
Enter value for num_days: 1
Listing the last day's Completed Snapshots
Instance DB Name Snap Id Snap Started Snap Level
------------ ------------ ---------- ------------------ ----------
ORCLCDB ORCLCDB 1 14 Sep 2020 05:02 1
2 14 Sep 2020 06:00 1
3 14 Sep 2020 07:00 1
4 14 Sep 2020 08:00 1
5 14 Sep 2020 09:00 1
Specify the Begin and End Snapshot Ids
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Enter value for begin_snap: 2
Begin Snapshot Id specified: 2
Enter value for end_snap: 4
End Snapshot Id specified: 4
Specify the Report Name
~~~~~~~~~~~~~~~~~~~~~~~
The default report file name is awrrpt_1_2_4.html. To use this name,
press <return> to continue, otherwise enter an alternative.
Enter value for report_name:
Using the report name awrrpt_1_2_4.html
<此处省略 html具体内容>
Report written to awrrpt_1_2_4.html
SQL> exit
Disconnected from Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
[oracle@28d4718eb450 oracle]$ ls
audit awrrpt_1_2_4.html checkpoints diag product
Chens-MacBook-Pro:~ cxf$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
28d4718eb450 store/oracle/database-enterprise:12.2.0.1 "/bin/sh -c '/bin/ba…" 5 hours ago Up 5 hours (healthy) 0.0.0.0:1521->1521/tcp, 5500/tcp Oracle-DB
Chens-MacBook-Pro:~ cxf$ docker cp 28d4718eb450:/u01/app/oracle/awrrpt_1_2_4.html /Users/cxf/Documents/
Chens-MacBook-Pro:~ cxf$ cd Documents/
Chens-MacBook-Pro:Documents cxf$ ls
awrrpt_1_2_4.html
打开html文件:
AWR Data:
Base statistics, SQL statistics, Advisor results, Metrics, ASH, etc
ADDM results
归档日志
-
用sqlplus启用并验证归档日志
Chens-MacBook-Pro:~ cxf$ docker exec -it Oracle-DB /bin/bash
[oracle@28d4718eb450 /]$ sqlplus / as sysdb
SQL*Plus: Release 12.2.0.1.0 Production
Copyright (c) 1982, 2016, Oracle. All rights reserved.
Use SQL*Plus to execute SQL, PL/SQL and SQL*Plus statements.
Usage 1: sqlplus -H | -V
-H Displays the SQL*Plus version and the
usage help.
-V Displays the SQL*Plus version.
Usage 2: sqlplus [ [<option>] [{logon | /nolog}] [<start>] ]
<option> is: [-AC] [-C <version>] [-L] [-M "<options>"] [-NOLOGINTIME] [-R <level>]
[-S]
-AC Enable Application Continuity.
-C <version> Sets the compatibility of affected commands to the
version specified by <version>. The version has
the form "x.y[.z]". For example, -C 10.2.0
-L Attempts to log on just once, instead of
reprompting on error.
-M "<options>" Sets automatic HTML or CSV markup of output. The options
have the form:
{HTML html_options|CSV csv_options}
See SQL*Plus User's Guide for detailed HTML and CSV options.
-NOLOGINTIME Don't display Last Successful Login Time.
-R <level> Sets restricted mode to disable SQL*Plus commands
that interact with the file system. The level can
be 1, 2 or 3. The most restrictive is -R 3 which
disables all user commands interacting with the
file system.
-S Sets silent mode which suppresses the display of
the SQL*Plus banner, prompts, and echoing of
commands.
<logon> is: {<username>[/<password>][@<connect_identifier>] | / }
[AS {SYSDBA | SYSOPER | SYSASM | SYSBACKUP | SYSDG | SYSKM | SYSRAC}] [EDITION=value]
Specifies the database account username, password and connect
identifier for the database connection. Without a connect
identifier, SQL*Plus connects to the default database.
The AS SYSDBA, AS SYSOPER, AS SYSASM, AS SYSBACKUP, AS SYSDG,
AS SYSKM and AS SYSRAC options are database administration privileges.
<connect_identifier> can be in the form of Net Service Name
or Easy Connect.
@[<net_service_name> | [//]Host[:Port]/<service_name>]
<net_service_name> is a simple name for a service that resolves
to a connect descriptor.
Example: Connect to database using Net Service Name and the
database net service name is ORCL.
sqlplus myusername/mypassword@ORCL
Host specifies the host name or IP address of the database
server computer.
Port specifies the listening port on the database server.
<service_name> specifies the service name of the database you
want to access.
Example: Connect to database using Easy Connect and the
Service name is ORCL.
sqlplus myusername/mypassword@Host/ORCL
The /NOLOG option starts SQL*Plus without connecting to a
database.
The EDITION specifies the value for Session Edition.
<start> is: @<URL>|<filename>[.<ext>] [<parameter> ...]
Runs the specified SQL*Plus script from a web server (URL) or the
local file system (filename.ext) with specified parameters that
will be assigned to substitution variables in the script.
When SQL*Plus starts, and after CONNECT commands, the site profile
(e.g. $ORACLE_HOME/sqlplus/admin/glogin.sql) and the user profile
(e.g. login.sql in the working directory) are run. The files may
contain SQL*Plus commands.
Refer to the SQL*Plus User's Guide and Reference for more information.
[oracle@28d4718eb450 /]$ sqlplus / as sysdba
SQL*Plus: Release 12.2.0.1.0 Production on Fri Nov 13 01:16:12 2020
Copyright (c) 1982, 2016, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount;
ORACLE instance started.
Total System Global Area 1342177280 bytes
Fixed Size 8792536 bytes
Variable Size 402654760 bytes
Database Buffers 922746880 bytes
Redo Buffers 7983104 bytes
Database mounted.
SQL> alter database archivelog;
Database altered.
SQL> alter database open;
Database altered.
SQL> archive log list
Database log mode Archive Mode
Automatic archival Enabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 40
Next log sequence to archive 42
Current log sequence 42
SQL>
alter system archive log current;
归档日志已经在快速恢复区中生成:
、
控制文件
两个查询是相同结果