SQL复习

学习来源:  http://www.cnblogs.com/shenxiaolin/p/5549343.html

 

1. 聚合函数

-- 1. AVG():返回列的平均值
SELECT AVG(product_price) AS avg_price
FROM products
WHERE vend_id = 1003;
-- 注意事项:函数会自动过滤掉所检索列中包含NULL值的行
-- 2. COUNT():返回列的行数。 SELECT COUNT(*) AS num_customer_1 , COUNT(customer_email) AS num_customer_2 FROM products; -- 注意事项:COUNT(*)会统计所有的行,而COUNT(具体的列)则会忽略NULL值所在行 -- 3. SUM():返回列的值汇总。 SELECT SUM(quantity) AS items_ordered FROM orderitems WHERE order_num = 2005; -- 4. MAX():返回列的最大值。 SELECT MAX(product_price) AS max_price FROM products; -- 注意事项:MAX()必须指定列。 --5. MIN():返回列的最小值。 -- 注意事项:MAX和MIN都可应用于文本类型,当数据是按照该列排序,使用MAX会返回最后一行,而MIN则返回第一行。

 

2. 表的连接

-- 1. 等值连接/内连接
SELECT vend_name, product_name, product_price
FROM vendors, products
WHERE vendors.vend_id = products.vend_id
ORDER BY vend_name, product_name;

-- 2. 交叉连接
SELECT vend_name, product_name, product_price
FROM vendors, products
ORDER BY vend_name, products_name;
-- 注意:返回笛卡儿积的连接类型,即为交叉连接

-- Oracle写法:
SELECT vend_name, product_name, product_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;

自连接:如字面意思,是对一个表的连接。

自然连接:能连接的两个表,至少有一列是相同的属性,自然连接会去除重复的列(由程序员实现)。

-- 3. 自连接
SELECT p1.product_id, p2.product_name
FROM products p1, products p2
WHERE p1.vend_id = p2.vend_id
    AND p2.product_id = 'DTNTR';

-- Oracle写法
SELECT p1.product_id, p1.product_name
FROM products p1 INNER JOIN p2
ON p1.vend_id = p2.vend_id
WHERE p2.product_id = 'DTNTR';

-- 4. 自然连接
SELECT c.*, o.order_num, o.order_date, oi.product_id
FROM customers c, orders o, orderitems oi
WHERE c.customer_id = o.customer_id
    AND oi.order_num = o.order_num
    AND product_id = 'FB';
-- 注意:去重是由程序员在SELECT语句中,通过指定所需列,来实现的。

外连接:如果在将两个表融合成一个表时(A+B=C),C中的出现这样的 行 :A或者B的特有属性全为0。而且功能需要包含这些行,那么就涉及到了外连接。

    外连接具体表现为:左外连接和有外连接。

-- 5. 右外连接
SELECT customers.customer_id, orders.order_num
FROM customers RIGHT OUTER JOIN orders 
ON orders.customer_id = customer.customer_id;
-- 注意:
-- 1. 左右是相对的。
-- 2. Oracle不支持 *=或者=*的写法
-- 3. 右外连接就是以左表为基准,可使左表的属性出现空值

具体地,连接可分四种:内连接,左外连接,有外连接,完全连接

完全连接:即交叉连接。

 

3. 组合查询

-- 关键字 UNION
SELECT vend_id, product_id, product_price
FROM products
WHERE product_price<=5
UNION
SELECT vend_id, product_id, product_price
FROM products
WHERE vend_id IN (1001, 1002);
-- 注意:
-- 1. 只有最后一条SQL需要写分号
-- 2. UNION的作用在于将多条SQL的结果集组合到单个查询结果集中。
-- 3. 用UNION连接的各个查询必须包含相同的列、表达式或者聚合函数(顺序可以不同)。
-- 4. 可对查询结果进行排序,但只允许在最后一个SQL中写ORDER BY。

UNION可以实现WHERE的功能,但 WHERE 无法实现 UNION ALL 的功能:

使用UNION无非就是想让结果集满足“条件一”或者“条件二”,这个功能使用WHERE能实现。

当存在某一条记录同时满足两个条件时,WHERE 无论如何都做不到让该记录在结果集中出现两次。

但是使用 UNION ALL 则能做到,事实上,也只有 UNION ALL 能做到。

 

4. 存储过程(Stored Procedure)

 Oracle中用于编写存储过程的语言是PL/SQL,其中 PL 是过程语言,提供了从 if 语句到循环等一切功能。

-- 1. 简单示例
CREATE OR REPLACE PROCEDURE Hello 
IS BEGIN DBMS_OUTPUT.PUT_LINE('Hello World'); END; -- 注意: -- 1. 初次创建:使用Create Procedure -- 2. 更新:当不确定是否已存在该存储过程时,要使用Create OR Replace来创建或者更新存储过程 -- 3. 存储过程体:位于 Begin 和 End 之间的部分 -- 4. 执行:存储过程的执行,使用 Execute Hello
-- 2. 创建存储过程
CREATE OR REPLACE PROCEDURE Greeting
IS
h number;
g char(20);
BEGIN
SELECT EXTRACT(HOUR FROM CURRENT_TIMESTAMP) INTO h FROM dual;
IF h >= 20 OR h <= 5 THEN
    g:='Good night!';
ELSIF h > 5 AND h <= 12 THEN
    g:='Good morning!';
ELSIF h > 12 AND h<= 17 THEN
    g:='Good afternoon!';
ELSE
    g:='Good evening';
END IF;
DBMS_OUTPUT.PUT_LINE(g);
END;
-- 执行:Execute Greeting
-- 3.1 添加客户
CREATE OR REPLACE PROCEDURE CustomerAdd(
    v_cust_name IN customers.cust_name%TYPE,  
    v_cust_address IN customers.cust_address%TYPE,  
    v_cust_city IN customers.cust_city%TYPE,
    v_cust_state IN customers.cust_state%TYPE,
    v_cust_sex IN customers.cust_sex%TYPE,
    v_cust_email IN customers.cust_email%TYPE)
IS
-- 声明客户ID变量
v_cust_id number;
BEGIN
-- 获取当前最大的客户ID:
SELECT MAX(cust_id) INTO v_cust_id
FROM customers;
-- 最大ID+1
v_cust_id := v_cust_id+1;
-- 插入新客户信息:
INSERT INTO customers(cust_id,
    cust_name,
    cust_address,
    cust_city,
    cust_state,
    cust_sex,
    cust_email)
VALUES(v_cust_id,
    v_cust_name,
    v_cust_address,
    v_cust_city,
    v_cust_state,
    v_cust_sex,
    v_cust_email);
 COMMIT;
END
-- 3.2 执行 “添加客户”
EXECUTE Customers('Pep E. LaPew',
    '100 Main Street',
    'Los Angels',
    'CA',
    'Man',
    NULL)
-- 注意:插入的值允许手动设为NULL
-- 3.3 删除存储过程
DROP PROCEDURE CustomerAdd;

 

5. 游标 

-- 游标的使用:

-- 定义变量
DECLARE
    v_vend_id vendors.vend_id%TYPE;
    v_vend_name vendors.vend_name%TYPE;
    v_vend_address vendors.vend_address%TYPE;
    v_vend_country vendors.vend_country%TYPE;
    v_vend_state vendors.vend_state%TYPE;
-- 定义游标(游标中属性的顺序由定义他的SELECT决定)
    CURSOR c_vendors
IS
    SELECT vend_id, vend_name, vend_address, vend_country, vend_state
    FROM vendors;
BEGIN
    -- 开启游标
    OPEN c_vendors;
    -- 对游标进行循环
    LOOP
        -- 获取一行并赋值给一变量(顺序要手动和游标中属性的顺序一致)
        FETCH c_vendors INTO v_vend_id, v_vend_name, v_vend_address, v_vend_country, v_vend_state;
        -- 对该变量进行处理
        IF Trim(v_vend_country) = 'USA' THEN
            v_vend_state := Upper(v_vend_state);
            UPDATE vendors
            SET vend_state = v_vend_state
            WHERE vend_id = v_vend_id;
        END IF;
        -- 循环终止条件
        EXIT WHEN c_vendors%notfound;
    END LOOP;
    -- 关闭游标
    CLOSE c_vendors;
END;

游标的作用:使用简单的SQL无法针对性地对结果集中的某些行进行获取和处理,有了游标,就可以在结果集中对记录进行滚动。

游标的分类:显示游标(手动创建),隐式游标(每次执行SQL时Oracle都会自动在内部创建)。

 

6. 管理事务处理

-- 6.1 保存点
insert into scott.emp(empno)  values(1011);
SAVEPOINT aa;
insert into scott.emp(empno)  values(1012);
ROLLBACK TO aa;
insert into scott.emp(empno)  values(1013);
commit;
-- 从保存点的创建位置起,到回滚位置间的操作均会被撤销,也就是说,‘1012’没有插入scott.emp中
-- 6.3 回滚
SELECT * FROM orders_log;
DELETE  FROM orders_log;
SELECT * FROM orders_log;
ROLLBACK;
-- 注意:Oracle中的事务无需显式开启,ROLLBACK默认对他上面的所有SQL操作进行回滚
-- 6.4 提交
DELETE FROM orderitems WHERE order_num = 20010;
DELETE FROM orders WHERE order_num = 20010;
COMMIT;
-- 注意:只有COMMIT上面的所有SQL均执行成功时,数据库相应表中的数据才会更新,只要一个出错,则所有SQL都无法影响到数据库。

注意:Oracle不需要启动事务,他的事务是隐式的(这一点不同于其他大多数DBMS)。

语句级原子性:每一条语句都具有的原子性,一条语句:要么执行成功;要么执行失败,且不会影响其他语句。

过程级原子性:Begin 和 End 之间的过程块,过程块中的代码:要么全部执行成功;要么都执行失败(哪怕只有一处失败),且不会影响过程之外的其他语句。

事务级原子性:Rollback或者Commit上面的所有语句。

笔试题:

1. 事务的ACID特性包括(原子性)、(一致性)、(隔离性)、(持久性)。

2. 在设置事务隔离层时,需要使用关键字(SET TRANSACTION)。

3. 在众多的事务控制语句中,用来撤销事务操作的语句是(ROLLBACK),用来持久化事务对数据库操作的语句是(COMMIT)。

4. 对表执行INSERT命令时系统自动加(RX)锁,执行CREATE命令时系统自动加(S)锁,执行ALTER命令时系统自动加(X)锁。

5. 哪些情况发生后事务将终止?

答:Oracle中的事务终止会发生在:

(1)用户使用COMMIT命令显示提交事务。

(2)用户使用ROLLBACK命令回滚整个事务。

(3)用户执行了一条DDL语句。(如create\drop\alter)

(4)用户正常断开了与Oracle的连接,这时用户当前的事务将被自动提交。

(5)用户进程意外被终止,这时用户当前的事务被回滚。

(6)用户关闭SQL*PLUS会话时,默认使用ROLLBACK回滚事务。

6. 数据库的并发操作会带来哪些问题?

答:数据库的并发操作会带来以下问题:
(1)丢失更新。

(2)错读(脏读)。

(3)不一致的分析(不可重复读)。

(4)幻读。

posted @ 2017-08-02 10:43  zhengmengen  阅读(301)  评论(0)    收藏  举报