Oracle SQL 基础培训
Contents
1.SQL基础
1.1 基础语法
- create table
- 普通表
create table ANGU_TEST1
(
id NUMBER
)
tablespace USERS
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 64K
next 1M
minextents 1
maxextents unlimited
);
- 临时表
--基于回话
create global temporary table ANGU_TEMP
(
id NUMBER
)
on commit preserve rows;
--基于事务
create global temporary table ANGU_TEMP_1
(
id NUMBER
)
on commit delete rows;
- select
SELECT last_name, department_name
FROM employees@remote,
departments
WHERE
employees.department_id = departments.department_id;
--@dblink
- group by
--聚合函数
SELECT department_id, MIN(salary), MAX (salary)
FROM employees
GROUP BY department_id
ORDER BY department_id;
SELECT department_id, MIN(salary), MAX (salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary) < 5000
ORDER BY department_id;
- order by
SELECT t.* FROM angu_test1 t ORDER BY ID;
SELECT t.* FROM angu_test1 t ORDER BY 1;
SELECT t.* FROM angu_test1 t ORDER BY 1 DESC;
SELECT t.* FROM angu_test1 t ORDER BY 1 NULLS FIRST;
SELECT t.* FROM angu_test1 t ORDER BY 1 NULLS LAST;
- update
UPDATE employees SET
job_id = 'SA_MAN', salary = salary + 1000, department_id = 120
WHERE first_name||' '||last_name = 'Douglas Grant';
UPDATE employees a
SET department_id =
(SELECT department_id
FROM departments
WHERE location_id = '2100'),
(salary, commission_pct) =
(SELECT 1.1*AVG(salary), 1.5*AVG(commission_pct)
FROM employees b
WHERE a.department_id = b.department_id)
WHERE department_id IN
(SELECT department_id
FROM departments
WHERE location_id = 2900
OR location_id = 2700);
- delete
DELETE FROM product_descriptions
WHERE language_id = 'AR';
- insert
INSERT INTO departments
VALUES (280, 'Recreation', DEFAULT, 1700);
INSERT INTO bonuses
SELECT employee_id, salary*1.1
FROM employees
WHERE commission_pct > 0.25;
- merge
MERGE INTO bonuses D
USING (SELECT employee_id, salary, department_id FROM employees
WHERE department_id = 80) S
ON (D.employee_id = S.employee_id)
WHEN MATCHED THEN UPDATE SET D.bonus = D.bonus + S.salary*.01
WHEN NOT MATCHED THEN INSERT (D.employee_id, D.bonus)
VALUES (S.employee_id, S.salary*.01);
1.2 常用处理
- 对number的理解
Actual Data | Specified As | Stored As |
---|---|---|
123.89 | NUMBER | 123.89 |
123.89 | NUMBER(3) | 124 |
123.89 | NUMBER(3,2) | exceeds precision |
123.89 | NUMBER(4,2) | exceeds precision |
123.89 | NUMBER(5,2) | 123.89 |
123.89 | NUMBER(6,1) | 123.9 |
123.89 | NUMBER(6,-2) | 100 |
0.01234 | NUMBER(4,5) | 0.01234 |
0.00012 | NUMBER(4,5) | 0.00012 |
0.000127 | NUMBER(4,5) | 0.00013 |
0.0000012 | NUMBER(2,7) | 0.0000012 |
0.00000123 | NUMBER(2,7) | 0.0000012 |
- 日期的处理
- 系统日
select sysdate from daul;
- 格式化日期
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as nowTime from dual; select to_char(sysdate,'yyyy') as nowYear from dual; select to_char(sysdate,'mm') as nowMonth from dual; select to_char(sysdate,'dd') as nowDay from dual; select to_char(sysdate,'hh24') as nowHour from dual; select to_char(sysdate,'mi') as nowMinute from dual; select to_char(sysdate,'ss') as nowSecond from dual;
- 字符串转日期格式
SELECT TO_DATE('2009/03/02', 'YYYY/MM/DD') FROM DUAL;
-
日期计算
SELECT SYSDATE + 1,SYSDATE FROM dual; SELECT SYSDATE - 1,SYSDATE FROM dual; SELECT to_date('20180703','yyyymmdd') - to_date('20180701','yyyymmdd') FROM dual;
- 常用日期函数
SELECT add_months(SYSDATE,1),SYSDATE FROM dual; SELECT add_months(SYSDATE,-1),SYSDATE FROM dual; SELECT add_months(SYSDATE,12),SYSDATE FROM dual; SELECT add_months(SYSDATE,-12),SYSDATE FROM dual; SELECT SYSDATE, LAST_DAY(SYSDATE) "Last" FROM dual; SELECT NEXT_DAY(SYSDATE,'星期一') "NEXT DAY" FROM DUAL; SELECT MONTHS_BETWEEN (SYSDATE + 31,SYSDATE) "Months" FROM DUAL; SELECT TRUNC(SYSDATE,'yyyy') FROM dual; SELECT TRUNC(SYSDATE,'mm') FROM dual; SELECT TRUNC(SYSDATE,'dd') FROM dual;
- 字符串处理
SELECT LOWER('ABC') FROM dual; SELECT UPPER('abc') FROM dual; SELECT INSTR('CORPORATE FLOOR','OR', 2, 2) "Instring" FROM DUAL; SELECT Substr('CORPORATE FLOOR',3,3) FROM dual; SELECT LENGTH('abc') FROM dual;
- DUAL虚拟表
SELECT * FROM dual; select 1 + 1 from dual;
1.3 常用函数
- max
SELECT MAX(salary) "Maximum" FROM employees;
- min
SELECT MIN(salary) "Maximum" FROM employees;
- avg
--Null 值
SELECT AVG(salary) "Maximum" FROM employees;
- count
SELECT COUNT(*) FROM employees t;
- table
CREATE OR REPLACE TYPE strings_t IS TABLE OF VARCHAR2 (100);
CREATE OR REPLACE FUNCTION random_strings (
count_in IN INTEGER)
RETURN strings_t
IS
l_strings strings_t := strings_t ();
BEGIN
l_strings.EXTEND (count_in);
FOR indx IN 1 .. count_in
LOOP
l_strings (indx) := DBMS_RANDOM.string ('u', 10);
END LOOP;
RETURN l_strings;
END;
/
SELECT * FROM TABLE(random_strings(5));
1.4 分析函数
SELECT manager_id, last_name, salary,
MAX(salary) OVER (PARTITION BY manager_id) AS mgr_max
FROM employees;
SELECT
department_id, first_name, last_name, salary,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary desc) rn
FROM employees
SELECT hire_date, last_name, salary,
LAG(salary, 1, 0) OVER (ORDER BY hire_date) AS prev_sal
FROM employees
WHERE job_id = 'PU_CLERK'
ORDER BY hire_date;
SELECT LISTAGG(last_name, '; ')
WITHIN GROUP (ORDER BY hire_date, last_name) "Emp_list",
MIN(hire_date) "Earliest"
FROM employees
WHERE department_id = 30;
1.5 中级语法
- 如何理解rownum
For each row returned by a query, the ROWNUM pseudocolumn returns a number indicating the order in which Oracle selects the row from a table or set of joined rows. The first row selected has a ROWNUM of 1, the second has 2, and so on.
SELECT *
FROM employees
WHERE ROWNUM < 11;
SELECT *
FROM (SELECT * FROM employees ORDER BY employee_id)
WHERE ROWNUM < 11;
SELECT *
FROM employees
WHERE ROWNUM > 1;
- 如何理解null
Condition | Value of A | Evaluation |
---|---|---|
a IS NULL | 10 | FALSE |
a IS NOT NULL | 10 | TRUE |
a IS NULL | NULL | TRUE |
a IS NOT NULL | NULL | FALSE |
a = NULL | 10 | UNKNOWN |
a != NULL | 10 | UNKNOWN |
a = NULL | NULL | UNKNOWN |
a != NULL | NULL | UNKNOWN |
a = 10 | NULL | UNKNOWN |
a != 10 | NULL | UNKNOWN |
null 常用函数
SELECT NVL(NULL,'abc') FROM dual;
SELECT NVL('a','abc') FROM dual;
- 如何理解connect by 语法及其简单应用
SELECT t.id,t.name,
LEVEL
/*CONNECT_BY_ROOT NAME*/
/*SYS_CONNECT_BY_PATH(NAME, ';')*/
FROM t_distinct t
START WITH ID = 1
CONNECT BY PRIOR ID = pid;
SELECT t.id,t.name,LEVEL
/*CONNECT_BY_ROOT NAME*/
/*SYS_CONNECT_BY_PATH(NAME, ';')*/
FROM t_distinct t
START WITH ID = 12
CONNECT BY PRIOR pid = ID;
1.6 Oracle常用的视图
SELECT * FROM all_tables t;
SELECT * FROM all_views t;
SELECT * FROM all_tab_cols;
SELECT * FROM all_indexes t;
SELECT * FROM All_Dependencies t;
SELECT * FROM user_source t;
1.7 如何看Oracle的语法图
2. PL/SQL语法基础
2.1 变量
命名规范
1. 以字母开头
2. 可以包含$,#,_
3. 非保留字
--保留字数据字典
SELECT * FROM v$RESERVED_WORDS;
--定义变量
DECLARE
part_number NUMBER(6); -- SQL data type
part_name VARCHAR2(20); -- SQL data type
in_stock BOOLEAN; -- PL/SQL-only data type
part_price NUMBER(6,2); -- SQL data type
part_description VARCHAR2(50); -- SQL data type
credit_limit CONSTANT REAL := 5000.00; -- SQL data type
max_days_in_year CONSTANT INTEGER := 366; -- SQL data type
urban_legend CONSTANT BOOLEAN := FALSE; -- PL/SQL-only data type
surname employees.last_name%TYPE;--推荐
BEGIN
NULL;
END;
/
2.2 分支与循环
- 分支
IF condition THEN
statements
END IF;
-----------------------------------------------
IF condition THEN
statements
ELSE
else_statements
END IF;
-------------------------------------------
IF condition_1 THEN
statements_1
ELSIF condition_2 THEN
statements_2
ELSE
else_statements
END IF;
- 基本循环
DECLARE
x NUMBER := 0;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE ('Inside loop: x = ' || TO_CHAR(x));
x := x + 1;
IF x > 3 THEN
EXIT;
END IF;
END LOOP;
-- After EXIT, control resumes here
DBMS_OUTPUT.PUT_LINE(' After loop: x = ' || TO_CHAR(x));
END;
/
-------------------------------------------------
DECLARE
x NUMBER := 0;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE('Inside loop: x = ' || TO_CHAR(x));
x := x + 1; -- prevents infinite loop
EXIT WHEN x > 3;
END LOOP;
-- After EXIT statement, control resumes here
DBMS_OUTPUT.PUT_LINE('After loop: x = ' || TO_CHAR(x));
END;
/
-----------------------------------------------------
DECLARE
x NUMBER := 0;
BEGIN
LOOP -- After CONTINUE statement, control resumes here
DBMS_OUTPUT.PUT_LINE ('Inside loop: x = ' || TO_CHAR(x));
x := x + 1;
IF x < 3 THEN
CONTINUE;
END IF;
DBMS_OUTPUT.PUT_LINE
('Inside loop, after CONTINUE: x = ' || TO_CHAR(x));
EXIT WHEN x = 5;
END LOOP;
DBMS_OUTPUT.PUT_LINE (' After loop: x = ' || TO_CHAR(x));
END;
/
-----------------------------------------------------------------
DECLARE
x NUMBER := 0;
BEGIN
LOOP -- After CONTINUE statement, control resumes here
DBMS_OUTPUT.PUT_LINE ('Inside loop: x = ' || TO_CHAR(x));
x := x + 1;
CONTINUE WHEN x < 3;
DBMS_OUTPUT.PUT_LINE
('Inside loop, after CONTINUE: x = ' || TO_CHAR(x));
EXIT WHEN x = 5;
END LOOP;
DBMS_OUTPUT.PUT_LINE (' After loop: x = ' || TO_CHAR(x));
END;
/
- for loop 循环
BEGIN
DBMS_OUTPUT.PUT_LINE ('lower_bound < upper_bound');
FOR i IN 1..3 LOOP
DBMS_OUTPUT.PUT_LINE (i);
END LOOP;
DBMS_OUTPUT.PUT_LINE ('lower_bound = upper_bound');
FOR i IN 2..2 LOOP
DBMS_OUTPUT.PUT_LINE (i);
END LOOP;
DBMS_OUTPUT.PUT_LINE ('lower_bound > upper_bound');
FOR i IN 3..1 LOOP
DBMS_OUTPUT.PUT_LINE (i);
END LOOP;
END;
/
2.3 游标的使用
A cursor is a pointer to a private SQL area that stores information about processing a specific SELECT or DML statement.
DECLARE
CURSOR c1 IS
SELECT t1.department_id, department_name, staff
FROM departments t1,
( SELECT department_id, COUNT(*) AS staff
FROM employees
GROUP BY department_id
) t2
WHERE (t1.department_id = t2.department_id) AND staff >= 5
ORDER BY staff;
BEGIN
FOR dept IN c1
LOOP
DBMS_OUTPUT.PUT_LINE ('Department = '
|| dept.department_name || ', staff = ' || dept.staff);
END LOOP;
END;
/
2.4 函数
CREATE FUNCTION get_bal(acc_no IN NUMBER)
RETURN NUMBER
IS
acc_bal NUMBER(11,2);
BEGIN
SELECT order_total
INTO acc_bal
FROM orders
WHERE customer_id = acc_no;
RETURN(acc_bal);
END;
/
2.5 存储过程
2.5.1 语法
CREATE PROCEDURE remove_emp
(employee_id NUMBER)
AS
tot_emps NUMBER;--定义变量
BEGIN
--业务逻辑
DELETE FROM employees
WHERE employees.employee_id = remove_emp.employee_id;
tot_emps := tot_emps - 1;
END;
2.5.2 参数
- IN
- OUT
- INT OUT
--OUT 参数默认会被置空
CREATE OR REPLACE
PROCEDURE P_PARAMETER(A VARCHAR2,
B IN VARCHAR2,
C OUT VARCHAR2,
D IN OUT VARCHAR2) IS
BEGIN
dbms_output.put_line('a:'||a);
dbms_output.put_line('b:'||b);
dbms_output.put_line('c:'||c);
dbms_output.put_line('d:'||d);
c := 'return_c';
d := 'return_d';
END P_PARAMETER;
2.5.3 默认惨
- DEFAULT
create or replace procedure
P_DEFAULT(
a VARCHAR2 DEFAULT 'default value'
) is
begin
dbms_output.put_line('a:'||a);
end P_DEFAULT;
2.5.4 参数传递方式
- 位置参数
- 命名参数
- 混合参数
DECLARE
emp_num NUMBER(6) := 120;
bonus NUMBER(6) := 50;
PROCEDURE raise_salary (
emp_id NUMBER,
amount NUMBER
) IS
BEGIN
UPDATE employees
SET salary = salary + amount
WHERE employee_id = emp_id;
END raise_salary;
BEGIN
-- Equivalent invocations:
raise_salary(emp_num, bonus); -- positional notation
raise_salary(amount => bonus, emp_id => emp_num); -- named notation
raise_salary(emp_id => emp_num, amount => bonus); -- named notation
raise_salary(emp_num, amount => bonus); -- mixed notation
END;
/
2.6 包
2.6.1 包声明
CREATE OR REPLACE PACKAGE trans_data AS
TYPE TimeRec IS RECORD (
minutes SMALLINT,
hours SMALLINT);
TYPE TransRec IS RECORD (
category VARCHAR2(10),
account INT,
amount REAL,
time_of TimeRec);
minimum_balance CONSTANT REAL := 10.00;
number_processed INT;
insufficient_funds EXCEPTION;
PRAGMA EXCEPTION_INIT(insufficient_funds, -4097);
END trans_data;
/
2.6.2 包体
包声明中函数存储过程必须在包体中实现
包声明中不存在的也可以在包体中,属于私有程序
CREATE PACKAGE emp_bonus AS
PROCEDURE calc_bonus (date_hired employees.hire_date%TYPE);
END emp_bonus;
/
CREATE PACKAGE BODY emp_bonus AS
-- DATE does not match employees.hire_date%TYPE
PROCEDURE calc_bonus (date_hired DATE) IS
BEGIN
DBMS_OUTPUT.PUT_LINE
('Employees hired on ' || date_hired || ' get bonus.');
END;
END emp_bonus;
/
2.7 集合类型
2.7.1 集合类型
- Associative array (or index-by table)
- VARRAY (variable-size array)
- Nested table
2.7.2 Associative array
DECLARE
TYPE population IS TABLE OF NUMBER -- Associative array type
INDEX BY VARCHAR2(64); -- indexed by string
city_population population; -- Associative array variable
i VARCHAR2(64); -- Scalar variable
BEGIN
city_population('Smallville') := 2000;
city_population('Midland') := 750000;
city_population('Megalopolis') := 1000000;
i := city_population.FIRST; -- Get first element of array
WHILE i IS NOT NULL LOOP
DBMS_Output.PUT_LINE
('Population of ' || i || ' is ' || city_population(i));
i := city_population.NEXT(i); -- Get next element of array
END LOOP;
END;
2.7.3 VARRAY
DECLARE
TYPE Foursome IS VARRAY(4) OF VARCHAR2(15);
team Foursome := Foursome('John', 'Mary', 'Alberto', 'Juanita');
-- team Foursome := Foursome();
PROCEDURE print_team (heading VARCHAR2) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(heading);
FOR i IN 1..4 LOOP
DBMS_OUTPUT.PUT_LINE(i || '.' || team(i));
END LOOP;
DBMS_OUTPUT.PUT_LINE('---');
END;
BEGIN
/* team.extend();
team(1) := 'aa';
team.extend();
team(2) := 'aa';
team.extend();
team(3) := 'aa';
team.extend();
team(4) := 'aa';*/
print_team('2001 Team:');
team(3) := 'Pierre';
team(4) := 'Yvonne';
print_team('2005 Team:');
team := Foursome('Arun', 'Amitha', 'Allan', 'Mae');
print_team('2009 Team:');
END;
2.8.3 Nested table
DECLARE
TYPE Roster IS TABLE OF VARCHAR2(15);
names Roster := Roster('D Caruso', 'J Hamil', 'D Piro', 'R Singh');
-- names Roster := Roster();
PROCEDURE print_names (heading VARCHAR2) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(heading);
FOR i IN names.FIRST .. names.LAST LOOP
DBMS_OUTPUT.PUT_LINE(names(i));
END LOOP;
DBMS_OUTPUT.PUT_LINE('---');
END;
BEGIN
/* names.extend();
names(1) :='aaa';
names.extend();
names(2) :='bbb';
names.extend();
names(3) :='ccc';
names.extend();
names(4) :='ddd';*/
print_names('Initial Values:');
names(3) := 'P Perez';
print_names('Current Values:');
names := Roster('A Jansen', 'B Gupta');
print_names('Current Values:');
END;
2.8 异常处理
2.8.1 基本语法
declare
begin
NULL;
EXCEPTION
WHEN ex_name_1 THEN statements_1 -- Exception handler
WHEN ex_name_2 OR ex_name_3 THEN statements_2 -- Exception handler
WHEN NO_DATA_FOUND THEN statements_3
WHEN OTHERS THEN statements_4 -- Exception handler
END;
2.8.2 获取异常的基本信息
- SQLCODE
- Sqlerrm
declare
v_result NUMBER;
begin
v_result := 1/0;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(Sqlcode);
dbms_output.put_line(sqlerrm);
END;
2.8.3 获取异常的详细信息
declare
v_result NUMBER;
begin
v_result := 1/0;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(DBMS_UTILITY.format_error_backtrace);
END;
---------------------------------
declare
v_result NUMBER;
begin
P_EXCEPTION;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(DBMS_UTILITY.format_error_backtrace);
END;
2.8.4 如何调试PL/SQL
ALTER PROCEDURE p_default COMPILE DEBUG;
ALTER PROCEDURE p_default COMPILE;
演示:查看变量和在Debug窗口执行SQL语句
2.9 事务的ACID属性
- Atomicity
All tasks of a transaction are performed or none of them are. There are no partial transactions. For example, if a transaction starts updating 100 rows, but the system fails after 20 updates, then the database rolls back the changes to these 20 rows.
- Consistency
The transaction takes the database from one consistent state to another consistent state. For example, in a banking transaction that debits a savings account and credits a checking account, a failure must not cause the database to credit only one account, which would lead to inconsistent data.
- Isolation
he effect of a transaction is not visible to other transactions until the transaction is committed. For example, one user updating the hr.employees table does not see the uncommitted changes to employees made concurrently by another user. Thus, it appears to users as if transactions are executing serially.
- Durability
Changes made by committed transactions are permanent. After a transaction completes, the database ensures through its recovery mechanisms that changes from the transaction are not lost.