初识oracle数据库

Author Avatar
Orange 3月 23, 2021
  • 在其它设备中阅读本文章

Install

Manual

  1. request Oracle Database Express Edition (XE) Release 11.2.0.2.0 (11gR2)
  2. click Oracle Database 11gR2 Express Edition for Linux x64
  3. copy the straight-download-link https://download.oracle.com/otn/linux/oracle11g/xe/oracle-xe-11.2.0-1.0.x86_64.rpm.zip?AuthParam=...
  4. run wget -b straight-download-link -P /opt/oracle and wait…
  5. run unzip /opt/oracle/oracle-xe-11.2.0-1.0.x86_64.rpm.zip
  6. run rpm -hvi /opt/oracle/oracle-xe-11.2.0-1.0.x86_64.rpm

    Docker

    docker run -d -p 1521:1521 -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g-r2

    username: system

    username: sys

    password: oracle

    sid: xe

    also see https://github.com/wnameless/docker-oracle-xe-11g

Rule

Normal Form Rule

  1. 1st_Normal_Form
    1. Single value
DATA CORRECT
JAVA T
C,C++ F
  1. solution: C,C++->2 line
  1. Same domain
DATA CORRECT
abc T
123 F
  1. solution: 123->"123"
  1. Diff column names
  2. Orderless
    1. 2nd_Normal_Form extends 1st_Normal_Form
  3. non-exist partial dependency: all column dependency all primary key
F1(PK) F2(PK) DATA1(dependencyF1+F2) DATA2(dependencyF1)
1 1 CORRECT:T CORRECT:F
  1. solution: column DATA2 move to F1's table
  1. 3rd_Normal_Form extends 2nd_Normal_Form
    1. non-exist transitive dependency: all column no dependency all non-primary key
F1(PK) DATA1 DATA2(dependencyDATA1)
1 abc CORRECT:F
  1. solution: column DATA1,DATA2 create to new table, add F2 column

Non-Normal Form Rule

  1. add TOTAL column
  2. copy foreign table
  3. move-in foreign table
  4. add CURRENT columns
  5. add foreign’s foreign key column

Table space

Principle

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  1. |-Database---------------------|
    | |-TableSpace-(muti *.dbf)--| |
    | | |-Segment--------------| | |
    | | | |-Extent-----------| | | |
    | | | | |----------| | | | |
    | | | | |data block|| | | | |
    | | | | |----------|| | | | |
    | | | | |----------| | | | |
    | | | |------------------| | | |
    | | |----------------------| | |
    | |--------------------------| |
    |------------------------------|

Default

  • users
  • system
  • sysaux: system auxiliary table space
  • undotbs1: undo table space 1
  • temp: temp table space for order or sum

    Usage

  • for table space

    1. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
    1. -- readonly; show non-temp *.dbf
      SELECT * FROM v$datafile;
      -- readonly; show relations between non-temp TableSpace<->*.dbf
      SELECT * FROM dba_data_files;
      -- readonly; show temp *.dbf
      SELECT * FROM v$tempfile;
      -- readonly; show relations between temp TableSpace<->*.dbf
      SELECT * FROM dba_temp_files;
      -- create (muti small data) permanent table space
      CREATE SMALLFILE TABLESPACE myts DATAFILE '/tmp/myts.dbf' SIZE 10m AUTOEXTEND on NEXT 2m MAXSIZE unlimited;
      -- create (muti small data) temp table space and add to tgroup
      CREATE SMALLFILE TEMPORARY TABLESPACE mytmpts TEMPFILE '/tmp/mytmpts.dbf' SIZE 10m AUTOEXTEND on NEXT 2m MAXSIZE unlimited TABLESPACE GROUP tgroup;
      -- create single big file table space
      CREATE BIGFILE TABLESPACE mytmpts TEMPFILE '/tmp/mytmpts.dbf' SIZE 10m AUTOEXTEND on NEXT 2m MAXSIZE unlimited TABLESPACE GROUP tgroup;
      -- create undo table space
      CREATE UNDO TABLESPACE myundots DATAFILE '/tmp/myundots.dbf' SIZE 10m;
      -- change status to offline & flush cache
      ALTER TABLESPACE myts OFFLINE NORMAL;
      -- change status to offline for recover
      ALTER TABLESPACE myts OFFLINE FOR RECOVER;
      -- change status to online
      ALTER TABLESPACE myts ONLINE;
      -- change enabled to r/w
      ALTER TABLESPACE myts READ WRITE;
      -- rename, make sure status is online
      ALTER TABLESPACE myts RENAME TO myts_rename;
      -- resize
      ALTER DATABASE DATAFILE '/tmp/myts' RESIZE 5m;
      -- append *.dbf
      ALTER TABLESPACE myts ADD DATAFILE '/tmp/myts.dbf' SIZE 10m AUTOEXTEND on NEXT 2m MAXSIZE unlimited, '/tmp/myts2.dbf' SIZE 10m AUTOEXTEND on NEXT 2m MAXSIZE unlimited;
      -- delete *.dbf
      ALTER TABLESPACE myts DROP DATAFILE '/tmp/myts2.dbf';
      -- rename *.dbf, make sure offline before
      ALTER TABLESPACE myts OFFLINE NORMAL;
      ALTER TABLESPACE myts RENAME DATAFILE '/tmp/myts.dbf' TO '/tmp/myts.dbf';
      ALTER TABLESPACE myts ONLINE;
      -- delete table space but keep *.dbf
      DROP TABLESPACE myts INCLUDING CONTENTS;
      -- delete table space within *.dbf
      DROP TABLESPACE myts INCLUDING CONTENTS AND DATAFILES;
      -- delete undo table space, make sure unused before
      ALTER SYSTEM SET undo_tablespace = 'undotbs1';
      DROP TABLESPACE myundots INCLUDING CONTENTS;
  • for table

    1. 1
      2
      3
      4
      5
      6
    1. -- create
      CREATE TABLE mytb(column1 INT,column2 VARCHAR2(11)) TABLESPACE myts;
      -- change
      ALTER TABLE mytb MOVE TABLESPACE myts;
      -- change (C/B)LOB Segment
      ALTER TABLE mytb MOVE TABLESPACE USERS LOB(lobcolumn1,lobcolumn2) STORE AS(TABLESPACE myts);
  • for index

    1. 1
    1. ALTER INDEX myid REBUILD TABLESPACE myts;

Segment

  • Data Segment: include (C/B)LOB Segment
  • Index Segment: head of table space if need
  • Temp Segment: auto delete
  • Rollback Segment: only in system table space

    data block

    Principle

    1. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
    1. |-----------------------------|
      |header(link Segment) |
      |-----------------------------|
      |table dir(ink table) |
      |-----------------------------|
      | row dir(link used row space)|
      |-----------------------------|
      |row space |
      |... |
      |-----------------------------|

Usage

Run in SQL*Plus

  1. 1
    2
  1. -- readonly
    SHOW PARAMETER db_block_size

Extent(Only in Enterprise Version)

  • Hash

    1. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
    1. -- create
      CREATE TABLE mytb(column1 INT,column2 VARCHAR2(11)) PARTITION BY HASH(column1) (
      PARTITION mypart1 TABLESPACE myts,
      PARTITION mypart2 TABLESPACE myts2
      );
      -- add, make sure table was extented
      ALTER TABLE mytb ADD PARTITION mypart3 TABLESPACE myts3;
      -- merge
      ALTER TABLE mytb MERGE PARTITIONS mypart1,mypart2 INTO PARTITION mypart1;
      -- delete
      ALTER TABLE mytb DROP PARTITION mypart1;
  • List

    1. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
    1. -- create
      CREATE TABLE mytb(column1 INT,column2 VARCHAR2(11)) PARTITION BY LIST(column2) (
      PARTITION mypart1 VALUES('Y') TABLESPACE myts,
      PARTITION mypart2 VALUES('N') TABLESPACE myts2
      );
      -- add, make sure table was extented
      ALTER TABLE mytb ADD PARTITION mypart3 VALUES('y') TABLESPACE myts3;
      ALTER TABLE mytb ADD PARTITION mypart4 VALUES(DEFAULT) TABLESPACE myts4;
      -- merge
      ALTER TABLE mytb MERGE PARTITIONS mypart1,mypart2 INTO PARTITION mypart1;
      -- delete
      ALTER TABLE mytb DROP PARTITION mypart1;
  • Range

    1. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
    1. -- create
      CREATE TABLE mytb(column1 INT,column2 VARCHAR2(11)) PARTITION BY RANGE(column1) (
      PARTITION mypart1 VALUES LESS THAN(10) TABLESPACE myts,
      PARTITION mypart2 VALUES LESS THAN(MAXVALUE) TABLESPACE myts2
      );
      -- add within MAXVALUE, make sure table was extented
      ALTER TABLE mytb SPLIT PARTITION mypart2 AT(20) INTO(
      PARTITION mypart2 TABLESPACE myts2,
      PARTITION mypart3 TABLESPACE myts3
      );
      -- add without MAXVALUE, make sure table was extented and condition greater than any partitions
      ALTER TABLE mytb ADD PARTITION mypart4 VALUES LESS THAN(20) TABLESPACE myts4;
      -- merge
      ALTER TABLE mytb MERGE PARTITIONS mypart1,mypart2 INTO PARTITION mypart1;
      -- delete
      ALTER TABLE mytb DROP PARTITION mypart1;
    • with Hash

      1. 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
      1. -- create into 2 range and each range divde into 3 hash
        CREATE TABLE mytb(column1 INT,column2 VARCHAR2(11)) PARTITION BY RANGE(column1)
        SUBPARTITION BY HASH(column2)
        SUBPARTITIONS 3 STORE IN (myts,myts2)
        (
        PARTITION mypart1 VALUES LESS THAN(10),
        PARTITION mypart2 VALUES LESS THAN(MAXVALUE)
        );
        -- add within MAXVALUE, make sure table was extented
        ALTER TABLE mytb SPLIT PARTITION mypart2 AT(20) INTO(
        PARTITION mypart2 TABLESPACE myts2,
        PARTITION mypart3 TABLESPACE myts3
        );
        -- add without MAXVALUE, make sure table was extented and condition greater than any partitions
        ALTER TABLE mytb ADD PARTITION mypart4 VALUES LESS THAN(20) TABLESPACE myts4;
        -- merge
        ALTER TABLE mytb MERGE PARTITIONS mypart1,mypart2 INTO PARTITION mypart1;
        -- delete
        ALTER TABLE mytb DROP PARTITION mypart1;
    • with List

      1. 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
      1. -- create into 2 range and each range divde into 2 list
        CREATE TABLE mytb(column1 INT,column2 VARCHAR2(11)) PARTITION BY RANGE(column1)
        SUBPARTITION BY LIST(column2)
        SUBPARTITIONS 3 STORE IN (myts,myts2)
        (
        PARTITION mypart1 VALUES LESS THAN(10) (
        SUBPARTITION mypart1_1 VALUES('Y') TABLESPACE myts,
        SUBPARTITION mypart1_2 VALUES('N') TABLESPACE myts
        ),
        PARTITION mypart2 VALUES LESS THAN(MAXVALUE) (
        SUBPARTITION mypart2_1 VALUES('Y') TABLESPACE myts2,
        SUBPARTITION mypart2_2 VALUES('N') TABLESPACE myts2
        )
        );
        -- add within MAXVALUE, make sure table was extented
        ALTER TABLE mytb SPLIT PARTITION mypart2 AT(20) INTO(
        PARTITION mypart2 TABLESPACE myts2,
        PARTITION mypart3 TABLESPACE myts3
        );
        -- add without MAXVALUE, make sure table was extented and condition greater than any partitions
        ALTER TABLE mytb ADD PARTITION mypart4 VALUES LESS THAN(20) TABLESPACE myts4;
        -- merge
        ALTER TABLE mytb MERGE PARTITIONS mypart1,mypart2 INTO PARTITION mypart1;
        -- delete
        ALTER TABLE mytb DROP PARTITION mypart1;

System

Principle

S(ystem) G(lobal) A(rea)

  • Database buffer cache(DB_CACHE_SIZE): default size data block cache
  • Shared pool(SHARE_POOL_SIZE)
    • Library cache: SQL or PL/SQL and theirs execution plan cache
    • Data Dictionary(Default VIEWs) cache: sql and execution plan cache
    • U(ser) G(lobal) A(rea): clustor session cache if need
  • Large pool: large objects cache for clustor
    • U(ser) G(lobal) A(rea): clustor session cache if need
  • Keep buffer cache(DB_KEEP_CACHE_SIZE): persistent data block cache
  • Recycle buffer cache:ephemeral data block cache
  • nK block size buffer(DB_2/4/8/16/32K_CACHE_SIZE): custom size data block cache

Usage

Run in SQL*Plus

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
  1. -- readonly
    SHOW PARAMETER SGA_MAX_SIZE;
    SHOW PARAMETER SGA_TARGET;
    -- turn on A(utomatic) S(hared) M(emory) M(anagement), make sure SGA_MAX_SIZE >= SGA_TARGET; Also can use `ALTER SESSION SET statistics_level=ALL`
    ALTER SESSION SET statistics_level=TYPICAL;
    ALTER SYSTEM SET SGA_MAX_SIZE=y;
    ALTER SYSTEM SET SGA_TARGET=x;
    -- turn off A(utomatic) S(hared) M(emory) M(anagement)
    ALTER SYSTEM SET SGA_TARGET=0;

Process

Principle

P(rogram) G(lobal) A(rea)

Usage

Run in SQL*Plus

  1. 1
    2
    3
    4
    5
    6
  1. -- readonly
    SHOW PARAMETER PGA_AGGREGATE_TARGET;
    -- turn on A(utomatic) P(rogram) M(emory) M(anagement), 20% of SGA_TARGET default
    ALTER SYSTEM SET PGA_AGGREGATE_TARGET=x;
    -- turn off A(utomatic) P(rogram) M(emory) M(anagement)
    ALTER SYSTEM SET PGA_AGGREGATE_TARGET=0;

DBW[0-9a-z]

db writer process [0-9a-z]

Principle

  1. 1
    2
    3
    4
    5
  1. |---------------| full |------------| DBW[0-9a-z] process |------|
    >>R>>|LRU Cache block||>>R>>>| DIRTY LIST |>>>>>>>>>>R>>>>>>>>>>|*.dbf ||
    <<W<<| (PGA Memery) ||<<W<<<|(PGA Memery)|<<<<<<<<<<W<<<<<<<<<<|(Disk)||
    |---------------|| |------------| |------||
    |---------------| |------|

Usage

  1. 1
    2
  1. -- readonly; PADDR == 00 means not start
    SELECT RAWTOHEX(PADDR), PSERIAL#, NAME, DESCRIPTION, ERROR FROM v$bgprocess;

Run in SQL*Plus

  1. 1
    2
  1. -- readonly
    SHOW PARAMETER db_writer_process

Data Directory(Default VIEWs)

  • Static:
    • dba_xxxs
    • all_xxxs: authorized info & user_xxx
    • user_xxxs
  • Dynamic:
    • gv$xxx(SELECT xxx FROM x$xxx): distributed
    • v$xxx(SELECT xxx FROM gv$xxx WHERE inst_id = USERENV(‘instance’))

      Principle

      1. 1
        2
        3
        4
        5
        6
      1. |--------------------| exec |--------------------| instance auto |--------| exec |-------| |-------|
        | bootstrap$ |>>>>>>>>>>>>>>>>>>>>>|base table: obj$,...|>>>>>>>>>>>>>>>>>| x$xxx |>>>>>>>>>>>>>|gv$xxx |>>>>| v$xxx |
        |(SYSTEM table space)|>>>>>>>>>>>>>>>>>>>>>|(SYSTEM table space)|>>>>>>>>>>>>>>>>>|(Memory)|>>>>>>>>>>>>>|(VIEW) |>>>>|(VIEW) |
        |--------------------| sql_text from *.bsq |--------------------| map from kernel |--------| catalog.sql |↑alias↑| |↑alias↑|
        |gv_$xxx| |v_$xxx |
        |-------| |-------|

Oracle will automatic modify those base table data after each DDL(CREATE/ALTER/DROP)
WARN: Only SYSDBA can access x$xxx

Usage

  1. 1
    2
    3
    4
  1. -- list all x$xxx
    SELECT * FROM v$fixed_table;
    -- list all Data Directories
    SELECT * FROM dict;

Variable

Run in SQL*Plus

  • Manual define
    • console: &variable_name or &&variable_name
    • *.sql: @variable_name, run @ xxx/xxx.sql
  • Automic define
    • DEF(INE) key=value

      Schema

      • Oracle(owned by user): datas + objects
      • MySQL: = database
      • SQLServer: name of tables, fields, types and primary/foreign keys

      Object

      Table

      organization type:
  • H(eap)-o(rganization)-T(able): unordered; physical rowid

    • without index(default): replace any unused(such as deleted) block from start to end or append to end when add
    • with index: index physical rowid in index segment then add, update or delete

      same as MySQL myISAM

      1. 1
      1. CREATE TABLE mytb(column1 INT,column2 VARCHAR2(11)) ORGANIZATION HEAP;
  • I(ndex)-o(rganization)-T(able): ordered; logical rowid; all data are stored in B-Tree type index segment if P(er)C(en)T_THRESHOLD is 100

    same as MySQL innoDB

    1. 1
    1. CREATE TABLE mytb(column1 INT,column2 VARCHAR2(11)) ORGANIZATION INDEX;
  • Cluster-Table: join data segments by foreign key

    1. 1
    1. CREATE TABLE mytb(column1 INT,f1 VARCHAR2(11)) CLUSTER mytb2(f1);
  • External-Table: readonly external text

    1. 1
      2
      3
      4
      5
      6
      7
      8
    1. -- path of external text is '/tmp/my.txt'
      CREATE DIRECTORY mydir AS '/tmp';
      CREATE TABLE mytb(column1 INT,column2 VARCHAR2(11)) ORGANIZATION EXTERNAL(
      TYPE oracle_loader
      DEFAULT DIRECTORY mydir
      ACCESS PARAMETERS(FIELDS TERMINATED BY ',')
      LOCATION('my.txt')
      );

Type

  • NUMBER(length, length after point)
    • INT
  • CHAR/NCHAR
  • VARCHAR2/NVARCHAR2: In Oracle 11g, VARCHAR2 and NVARCHAR2‘s max size limit is 4000
  • DATE
  • CLOB/NCLOB
  • BLOB
  • BFILE

start with ‘N’ means store type must be national charset(‘AF16UTF16’(default) or ‘UTF8’) char
start without ‘N’ means store type can be byte or database charset char

Constraint

  • primary/foreign key
  • not null
  • unique
  • check
    1. 1
      2
      3
      4
      5
      6
    1. -- add
      ALTER TABLE mytb ADD CHECK (column2 IN ('Y','N'));
      -- disable
      ALTER TABLE mytb MODIFY CONSTRAINT xxx DISABLE;
      -- no-validate exist data
      ALTER TABLE mytb MODIFY CONSTRAINT xxx DISABLE NOVALIDATE;

Column

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  1. -- add
    ALTER TABLE mytb ADD column1 varchar2;
    ALTER TABLE mytb ADD column2 varchar2;
    -- remove
    ALTER TABLE mytb DROP (column1,column2);
    -- rename
    ALTER TABLE mytb RENAME COLUMN column1 TO column3;
    -- change type
    ALTER TABLE mytb MODIFY column1 varchar2;
    -- hide, manual modify base table if need undo
    ALTER TABLE mytb SET UNUSED (column1,column2);

Index(of H(eap)-o(rganization)-T(able))

  • B-Tree

    • by value(default)

      1. 1
      1. CREATE INDEX myid ON mytb(column) TABLESPACE myts;
    • by Func

      1. 1
      1. CREATE BITMAP INDEX myid ON mytb(FUNC(column)) TABLESPACE myts;
  • BitMap for limit status flag(Only in Enterprise Version)

    1. 1
    1. CREATE BITMAP INDEX myid ON mytb(column) TABLESPACE myts;
  1. 1
    2
    3
    4
  1. -- merge and prune
    ALTER INDEX myid COALESCE DEALLOCATE UNUSED;
    -- prune rebuild
    ALTER INDEX myid REBUID;

View

Simple map column support modified without check by default

  1. 1
    2
  1. -- checkout if modifiable
    SELECT * FROM user_updatable_columns WHERE table_name = 'myv';

Sequence

Synonym

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  1. -- create or replace user's synonym
    CREATE OR REPLACE SYNONYM mysy FOR mytb;
    SELECT * FROM sys.mysy;
    -- create public synonym
    CREATE OR REPLACE PUBLIC SYNONYM mysy FOR mytb;
    SELECT * FROM mysy;
    -- recreate
    ALTER SYNONYM mysy COMPILE;
    -- delete user's synonym
    DROP SYNONYM mysy;
    -- delete public synonym
    DROP PUBLIC SYNONYM mysy;

dual is public synonym of virtual table sys.dual(keeps one select result)

Log

*.LOG files group by group id, Oracle will automic turn to override next log group if full

Log group

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  1. -- show log group<->*.log
    SELECT * FROM v$logfile;
    -- create log group
    ALTER DATABASE ADD LOGFILE GROUP 4 ('/tmp/redo01.log','/tmp/redo02.log') SIZE 5m;
    -- delete log group
    ALTER DATABASE DROP LOGFILE GROUP 4;
    -- clear log group's data
    ALTER DATABASE CLEAR UNACHIVED LOGFILE GROUP 4;
    -- turn next log group
    ALTER SYSTEM SWITCH LOGFILE;

Log

  1. 1
    2
    3
    4
  1. -- add log to group, size must be equals
    ALTER DATABASE ADD LOGFILE MEMBER '/tmp/redo03.log' TO GROUP 4,'/tmp/redo04.log' TO GROUP 4;
    -- remove log from group, make sure group not in 'CURRENT' status
    ALTER DATABASE DROP LOGFILE MEMBER '/tmp/redo04.log';

Archive

There are 2 override modes:

  • without archive(default): each override without package history
  • with archive: each override will package history to dests 1-31 before
    Run in SQL*Plus
    1. 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
    1. -- readonly; show default log dir, similar to `ALTER SYSTEM SET log_archive_dest_1 = 'LOCATION=USE_DB_RECOVERY_FILE_DEST';`
      SHOW PARAMETER db_recovery_file_dest
      -- readonly; show log dir
      SHOW PARAMETER log_archive_dest
      -- readonly; show current override mode
      ARCHIVE LOG LIST;
      -- override with archive, must be 'MOUNT' but not 'OPEN' status before, make sure dir is exist
      SHUTDOWN IMMEDIATE;
      STARTUP MOUNT;
      ALTER DATABASE ARCHIVELOG;
      ALTER SYSTEM SET log_archive_dest_[1-31] = 'LOCATION=/tmp';
      ALTER SYSTEM SET log_archive_format = 'redo%S_%R.%T';
      ALTER DATABASE OPEN;

SQL

merge: similar union

  1. 1
  1. MERGE INTO mytb1 USING mytb2 ON mytb2.column1 = mytb1.column1 WHEN MATCHED THEN UPDATE SET mytb1.column2 = mytb2.column2 WHEN NOT MATCHED THEN INSERT (column1,column2) VALUES(mytb2.column1,mytb2.column2);

PL/SQL

Constrant

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  1. -- make sure `SET SERVEROUTPUT ON` before if Run in SQL*Plus
    DECLARE
    c CONSTANT VARCHAR2(1) := 'Y';
    BEGIN
    DBMS_OUTPUT.PUT_LINE('c:'||c);
    END;
    /
    -- use column type
    DECLARE
    c CONSTANT mytb.column2%TYPE := 'Y';
    BEGIN
    DBMS_OUTPUT.PUT_LINE('c:'||c);
    END;
    /

Variable

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
  1. -- make sure `SET SERVEROUTPUT ON` before if Run in SQL*Plus
    DECLARE
    v1 INT;
    v2 VARCHAR2(1) := 'Y';
    BEGIN
    DBMS_OUTPUT.PUT_LINE('v1:'||v1||' and v2:'||v2);
    END;
    /
    -- use column type
    DECLARE
    v1 mytb.column1%TYPE;
    v2 mytb.column2%TYPE := 'Y';
    BEGIN
    DBMS_OUTPUT.PUT_LINE('before v1:'||v1||' and v2:'||v2);
    SELECT column1,column2 INTO v1,v2 FROM mytb WHERE column1 = 1;
    DBMS_OUTPUT.PUT_LINE('after v1:'||v1||' and v2:'||v2);
    END;
    /
    -- use single row data
    DECLARE
    r mytb%ROWTYPE;
    BEGIN
    SELECT * INTO r FROM mytb WHERE column1 = 1;
    DBMS_OUTPUT.PUT_LINE('row.column1:'||r.column1||'row.column2'||r.column2);
    END;
    /
    -- use single custom data
    DECLARE
    TYPE myrdtype IS RECORD(column1 INT,column2 VARCHAR2(11));
    t myrdtype;
    BEGIN
    SELECT column1, column2 INTO t FROM mytb WHERE column1 = 1;
    DBMS_OUTPUT.PUT_LINE('column1:'||t.column1||' and column2:'||t.column2);
    END;
    /
    -- use multi data
    DECLARE
    TYPE mytbtype1 IS TABLE OF INT INDEX BY BINARY_INTEGER;
    TYPE mytbtype2 IS TABLE OF mytb%ROWTYPE INDEX BY BINARY_INTEGER;
    TYPE myrdtype IS RECORD(column1 INT,column2 VARCHAR2(11));
    TYPE mytbtype3 IS TABLE OF myrdtype INDEX BY BINARY_INTEGER;
    tb1 mytbtype1;
    tb2 mytbtype2;
    tb3 mytbtype3;
    BEGIN
    tb1(1) := 1;
    tb1(2) := 2;
    tb1(3) := 3;
    tb1.DELETE(3);
    tb2(1).column1 := 1;
    tb2(1).column2 := 'Y';
    SELECT * INTO tb3 FROM mytb;
    DBMS_OUTPUT.PUT_LINE('count:'||tb1.COUNT||'tb1[1]:'||tb1(1)||' tb1[2]:'||tb1(2));
    DBMS_OUTPUT.PUT_LINE('tb2[1].column1:'||tb2(1).column1||'tb2[1].column2:'||tb2(1).column2);
    DBMS_OUTPUT.PUT_LINE('tb3[1].column1:'||tb3(1).column1||'tb3[1].column2:'||tb3(1).column2);
    END;
    /

Cursor

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
  1. -- make sure `SET SERVEROUTPUT ON` before if Run in SQL*Plus
    -- readonly
    DECLARE
    /* define; CAN NOT SET LENGTH OF params TYPE */
    CURSOR mycs(param1 INT,param2 VARCHAR2 := 'Y') IS
    SELECT * FROM mytb WHERE column1 = param1 and column2 = param2;
    -- r mytb%ROWTYPE;
    BEGIN
    -- OPEN mycs;
    FOR r IN mycs
    LOOP
    -- FETCH mycs INTO r;
    -- EXIT WHEN mycs%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE('id:'||mycs%ROWCOUNT||'row.column1:'||r.column1||'row.column2'||r.column2);
    END LOOP;
    -- CLOSE mycs;
    END;
    /
    -- updatable
    DECLARE
    /* define; CAN NOT SET LENGTH OF params TYPE; NOWAIT means return fail immediately if OPEN parallel */
    CURSOR mycs(param1 INT,param2 VARCHAR2 := 'Y') IS
    SELECT * FROM mytb WHERE column1 = param1 and column2 = param2 FOR UPDATE OF column1,column2 NOWAIT;
    -- r mytb%ROWTYPE;
    BEGIN
    -- OPEN mycs;
    FOR r IN mycs
    LOOP
    -- FETCH mycs INTO r;
    -- EXIT WHEN mycs%NOTFOUND;
    UPDATE mytb SET column2 = 'N' WHERE CURRENT OF mycs;
    DBMS_OUTPUT.PUT_LINE('id:'||mycs%ROWCOUNT||'row.column1:'||r.column1||'row.column2'||r.column2);
    END LOOP;
    -- CLOSE mycs;
    END;
    /

Exception

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
  1. -- make sure `SET SERVEROUTPUT ON` before if Run in SQL*Plus
    DECLARE
    v VARCHAR2(3):='数1';
    e EXCEPTION;
    PRAGMA EXCEPTION_INT(e, -2290);
    BEGIN
    CAST(v as INT);
    EXCEPTION WHEN VALUE_ERROR THEN
    DBMS_OUTPUT.PUT_LINE('catch VALUE_ERROR');
    INSERT INTO mytb(column2) VALUES(v);
    EXCEPTION WHEN e THEN
    DBMS_OUTPUT.PUT_LINE('catch check option fail code -2290');
    WHEN OTHERS THEN
    /* error code [-20000 - -20999] */
    RISE_APPLICATION_ERROR(-20000, 'uncatched exception');
    END;
    /

Procedure

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
  1. -- list all Procedures
    SELECT * FROM user_source;
    -- make sure `SET SERVEROUTPUT ON` before if Run in SQL*Plus
    -- create or update without params, make sure name not end with '()'
    CREATE OR REPLACE PROCEDURE myp AS
    c CONSTANT VARCHAR2(1) := 'Y';
    BEGIN
    DBMS_OUTPUT.PUT_LINE('c:'||c);
    END;
    /
    -- create or update with input params
    /* CAN NOT SET LENGTH OF params TYPE */
    CREATE OR REPLACE PROCEDURE myp(param1 IN INT, param2 IN VARCHAR2 DEFAULT 'Y') AS
    c CONSTANT VARCHAR2(1) := param2;
    BEGIN
    DBMS_OUTPUT.PUT_LINE('c:'||c);
    END;
    /
    -- create or update with output params
    /* CAN NOT SET LENGTH OF params TYPE */
    CREATE OR REPLACE PROCEDURE myp(param1 OUT INT, param2 OUT VARCHAR2) AS
    c CONSTANT VARCHAR2(1) := param2;
    BEGIN
    DBMS_OUTPUT.PUT_LINE('c:'||c);
    END;
    /
    -- create or update with input and output params
    /* CAN NOT SET LENGTH OF params TYPE; CAN NOT SET DEFAULT VALUE */
    CREATE OR REPLACE PROCEDURE myp(param1 IN OUT INT, param2 IN OUT VARCHAR2) AS
    c CONSTANT VARCHAR2(1) := param2;
    BEGIN
    param1 := 2
    param2 := 'F'
    DBMS_OUTPUT.PUT_LINE('c:'||c);
    END;
    /
    --- run without params
    CALL myp();
    --- run with input params
    CALL myp(1, 'F');
    -- delete
    DROP PROCEDURE myp;

Run in SQL*Plus

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  1. /* transform EXEC into `BEGIN ... END;` */
    --- run without params
    EXEC myp;
    --- run with input params
    EXEC myp(1, 'F');
    EXEC myp(param2 => 'F', param1 => 1);
    --- run with output params
    VARIABLE v1 NUMBER;
    VARIABLE v2 VARCHAR2(1);
    CALL myp(:v1, :v2);
    SELECT :v1, :v2 FROM mytb;
    --- run with input and output params
    VARIABLE v1 NUMBER;
    VARIABLE v2 VARCHAR2(1);
    CALL myp(:v1, :v2);
    SELECT :v1, :v2 FROM mytb;

Func

has one return

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
  1. -- make sure `SET SERVEROUTPUT ON` before if Run in SQL*Plus
    -- create or update without params, make sure name not end with '()'
    CREATE OR REPLACE FUNCTION myf RETURN VARCHAR2 AS
    c CONSTANT VARCHAR2(1) := 'Y';
    BEGIN
    DBMS_OUTPUT.PUT_LINE('c:'||c);
    RETURN c;
    END;
    /
    -- create or update with input params
    /* CAN NOT SET LENGTH OF params TYPE */
    CREATE OR REPLACE FUNCTION myf(param1 IN INT, param2 IN VARCHAR2 DEFAULT 'Y') RETURN VARCHAR2 AS
    c CONSTANT VARCHAR2(1) := param2;
    BEGIN
    DBMS_OUTPUT.PUT_LINE('c:'||c);
    RETURN c;
    END;
    /
    -- create or update with output params
    /* CAN NOT SET LENGTH OF params TYPE */
    CREATE OR REPLACE FUNCTION myf(param1 OUT INT, param2 OUT VARCHAR2) RETURN VARCHAR2 AS
    c CONSTANT VARCHAR2(1) := param2;
    BEGIN
    DBMS_OUTPUT.PUT_LINE('c:'||c);
    RETURN c;
    END;
    /
    -- create or update with input and output params
    /* CAN NOT SET LENGTH OF params TYPE; CAN NOT SET DEFAULT VALUE */
    CREATE OR REPLACE FUNCTION myf(param1 IN OUT INT, param2 IN OUT VARCHAR2) RETURN VARCHAR2 AS
    c CONSTANT VARCHAR2(1) := param2;
    BEGIN
    param1 := 2
    param2 := 'F'
    DBMS_OUTPUT.PUT_LINE('c:'||c);
    RETURN c;
    END;
    /
    --- run without params
    SELECT myf() FROM mytb;
    --- run with input params
    SELECT myf(1, 'F') FROM mytb;
    -- delete
    DROP FUNCTION myf;

Run in SQL*Plus

  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  1. --- run with output params
    VARIABLE v1 NUMBER;
    VARIABLE v2 VARCHAR2(1);
    SELECT myf(:v1, :v2) FROM mytb;
    SELECT :v1, :v2 FROM mytb;
    --- run with input and output params
    VARIABLE v1 NUMBER;
    VARIABLE v2 VARCHAR2(1);
    SELECT myf(:v1, :v2) FROM mytb;
    SELECT :v1, :v2 FROM mytb;

Trigger

  • attach

    • DML(INSERT, UPDATE, DELETE, …) event

      1. 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
      1. -- make sure `SET SERVEROUTPUT ON` before if Run in SQL*Plus
        -- create or update before insert
        CREATE OR REPLACE TRIGGER mytgbi BEFORE INSERT ON mytb FOR EACH ROW
        BEGIN
        DBMS_OUTPUT.PUT_LINE('trigger before insert mytb new.column1='||:NEW.column1||',new.column2='||:NEW.column2);
        END;
        /
        -- create or update before update
        CREATE OR REPLACE TRIGGER mytgbu BEFORE UPDATE ON mytb FOR EACH ROW
        BEGIN
        DBMS_OUTPUT.PUT_LINE('trigger before update mytb old.column1='||:OLD.column1||',old.column2='||:OLD.column2||' new.column1='||:NEW.column1||',new.column2='||:NEW.column2);
        END;
        /
        -- create or update after update
        CREATE OR REPLACE TRIGGER mytgau AFTER UPDATE ON mytb FOR EACH ROW
        BEGIN
        DBMS_OUTPUT.PUT_LINE('trigger after update mytb old.column1='||:OLD.column1||',old.column2='||:OLD.column2||' new.column1='||:NEW.column1||',new.column2='||:NEW.column2);
        END;
        /
        -- create or update before delete
        CREATE OR REPLACE TRIGGER mytgbd BEFORE DELETE ON mytb FOR EACH ROW
        BEGIN
        DBMS_OUTPUT.PUT_LINE('trigger before delete mytb old.column1='||:OLD.column1||',old.column2='||:OLD.column2);
        END;
        /
        -- disable
        ALTER TRIGGER mytgbi DISABLE;
        -- disable for table
        ALTER TRIGGER mytb DISABLE ALL TRIGGERS;
        -- delete
        DROP TRIGGER mytgbi;
    • System event
      WARN: Only SYSDBA can create system event trigger

      1. 1
        2
        3
        4
        5
        6
        7
      1. -- make sure `SET SERVEROUTPUT ON` before if Run in SQL*Plus
        -- create or update after loggon
        CREATE OR REPLACE TRIGGER mytgau AFTER LOGGON ON DATABASE
        BEGIN
        DBMS_OUTPUT.PUT_LINE('trigger after loggon user='||USER||' date='||SYSDATE);
        END;
        /
    • DDL(CREATE, DROP, ALTER, …) event
      WARN: Only SYSDBA can create ddl event trigger

      1. 1
        2
        3
        4
        5
        6
        7
      1. -- make sure `SET SERVEROUTPUT ON` before if Run in SQL*Plus
        -- create or update after create
        CREATE OR REPLACE TRIGGER mytgac AFTER CREATE ON DATABASE
        BEGIN
        DBMS_OUTPUT.PUT_LINE('trigger after create user='||USER||' obj_name='||SYS.DICTIONARY_OBJ_NAME||' obj_type='||SYS.DICTIONARY_OBJ_TYPE||' date='||SYSDATE);
        END;
        /
  • instead
    WARN: Only instead events on View

    1. 1
      2
      3
      4
      5
      6
    1. -- create or update instead of insert
      CREATE OR REPLACE TRIGGER mytgii INSTEAD OF INSERT ON myv FOR EACH ROW
      BEGIN
      INSERT INTO mytb(column1, column2) VALUES(:NEW.column1, :NEW.column2);
      END;
      /

Package

  • define
  • body
    • Procedure
    • Func

      PUT_LINE is one of procedures in DBMS_OUTPUT package

User

Role

Backup

  • expdp(Oracle 11g support): hot backup to files
  • rman: hot or cold backup to blocks

Flashback(Oracle 11g support)

  1. 1
  1. SELECT xxx, version_operation, version_starttime, version_endtime FROM mytb VERSION BETWEEN MINVALUE AND MAXVALUE;
  • Table commited DML(INSERT, UPDATE, DELETE, …)
  • Drop
  • Database(off default)

ASM(Oracle 10g support)

RAC

Optimize

Execution Plan

Principle

SQL process principle

  1. 1
    2
    3
    4
    5
    6
  1. |-------| DQL |---------------------------------| Execution |----------| |------|
    SQL | Query |>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>|R(ule)/C(ost)-B(ased)-O(ptimizer)|>>>>>>>>>>>|Share Pool|>>| ||
    >>>>>|Parsing| DML(INSERT, UPDATE, DELETE, ...) |---------------------------------| Plan | (SGA) | |Result||
    | | DDL/DCL |----------| | ||
    |-------|>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>|------||
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<|------|

Cardinality Feedback will add A(ctual)-Rows hint for the same DQL or DML(INSERT, UPDATE, DELETE, …) when use C(ost)-B(ased)-O(ptimizer) and A(ctual)-Rows large diff than E(xpect)-Rows at first time (Oracle 11.2g support)

Usage

  • Estimated

    • Explain plan(key F5 in PL/SQL Developer): store in plan_table(public synonym of session’s temp table SYS.PLAN_TABLE$) created by catplan.sql

      1. 1
        2
        3
        4
      1. -- save execution plan for `SELECT * FROM dual`
        EXPLAIN PLAN FOR SELECT * FROM dual;
        -- query last execution plan; pretty format `SELECT * FROM PLAN_TABLE`
        SELECT * FROM TABLE(dbms_xplan.display('PLAN_TABLE', null, 'ADVANCED'));
    • Auto trace(Run in SQL*Plus): same as Explain plan

      1. 1
        2
        3
      1. -- query execution plan for `SELECT * FROM dual`
        SET AUTOTRACE ON;
        SELECT * FROM dual;
  • Actual

    • Statistics: store in session’s temp view v$sql_plan_statistics_all

      1. 1
        2
        3
        4
        5
      1. -- save execution plan for `SELECT * FROM dual`; Also can use hint `SELECT /*+ gather_plan_statistics*/ * FROM dual`
        ALTER SESSION SET statistics_level=ALL;
        SELECT * FROM dual;
        -- query shared pool's last sql cursor's execution plan; pretty format `SELECT * FROM v$sql_plan_statistics_all`
        SELECT * FROM TABLE(dbms_xplan.display_cursor(null, null, 'ADVANCED ALLSTATS'));
    • A(utomatic) W(orkload) R(epository): store in views wrm$_* and wrh$_*(instead of Statspack)

      1. 1
        2
        3
        4
        5
        6
        7
      1. -- save execution plan for `SELECT * FROM dual`, make sure session's statistics_level >= TYPICAL
        SELECT * FROM dual;
        CALL dbms_workload_repository.create_snapshot();
        ALTER SYSTEM FLUSH shared_pool;
        -- query shared pool's execution plan; pretty format `SELECT * FROM PLAN_TABLE`
        SELECT sql_id FROM v$sqlarea WHERE sql_text LIKE 'SELECT * FROM dual'
        SELECT * FROM TABLE(dbms_xplan.display_awr('sql_id', null, null, 'ADVANCED ALLSTATS'));
    • Trace Dump: store *.trc in user_dump_dest dir; you can use tool tkprof pretty format file

      1. 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
      1. -- query trace dump dir
        show parameter user_dump_dest;
        -- query SID and Serial#
        SELECT * FROM V$SESSION;
        -- turn on sql_trace for session; Also can use `ALTER SESSION SET sql_trace=TRUE` for current session
        EXECUTE dbms_system.set_sql_trace_in_session(SID, Serial#, TRUE);
        -- save execution plan for `SELECT * FROM dual`
        SELECT * FROM dual;
        -- turn off sql_trace for session; Also can use `ALTER SESSION SET sql_trace=FALSE` for current session
        EXECUTE dbms_system.set_sql_trace_in_session(SID, Serial#, FALSE);
    • 10046 Event: store *.trc in user_dump_dest dir; you can use tool tkprof pretty format file

      • lv1: same as Trace Dump
      • lv4: lv1 + bind values
      • lv8: lv1 + events
      • lv12: lv4 + lv8
        1. 1
          2
          3
          4
          5
          6
          7
          8
        1. -- query trace dump dir
          show parameter user_dump_dest;
          -- turn on 10046 event trace for current session
          ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 12';
          -- save execution plan for `SELECT * FROM dual`
          SELECT * FROM dual;
          -- turn off 10046 event trace for current session
          ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT OFF';

CC许可协议署名非商业性使用相同方式共享
本文采用 CC BY-NC-SA 3.0 Unported 协议进行许可