供自己查阅的SQL手册

将书中的示例,都跟着走了一遍之后,将一些SQL语句、概念性的东西,记在这里,使用的时候快速翻阅。

查询#

不加筛选的查询#

-- 最简单的查询  
select prod_id, prod_name, prod_price from Products;  
  
-- 查询去重,每一项只列举一次  
select distinct vend_id from Products;  
  
-- 查询结果个数限制,从哪里开始  
select distinct vend_id, prod_price from Products limit 2 offset 3;  

对结果排序#

-- order by可以对多个键排序,得放在最后面  
select prod_name,prod_price from Products order by prod_price, prod_name;  
  
-- 可以按照位置排序  
-- 优点:少打几个字  
-- 缺点有点多:可能指定错误,前面顺序变了后面忘了变,不能使用不在查询列表的列  
select prod_name,prod_price from Products order by 2, 1;  
  
-- desc降序、asc升序  
-- 如果要对多列进行降序升序选择,每一列分开指定  
select prod_price,prod_name from Products order by prod_price desc;  

条件筛选#

-- 能由数据库做的尽量都交给数据库做,有两个好处  
-- 提高应用程序效率,减少数据传输  
select prod_name, prod_price from Products where prod_price = 3.49;  
  
-- and 与 or  
select prod_name, prod_price from Products where vend_id = 'DLL01' or vend_id = 'BRS01' and prod_price >= 10;  
  
-- in,用in会有些好处  
-- 可读性、and和or同时存在,用in更好评估顺序、in的列表可以是查询的结果  
select prod_name, prod_price from Products where vend_id in ('DLL01','BRS01');  

模糊条件筛选#

-- 前面是Fish,后面什么无所谓  
select prod_id, prod_name from Products where prod_name like 'Fish%';  
  
-- 前后什么都无所谓,包含bean bag就好  
select prod_id, prod_name from Products where prod_name like '%bean bag%';  
  
-- 用_符号卡一个字符位置  
select prod_id, prod_name, prod_desc from Products where prod_desc like '____测试中文';  
  
-- []中的内容多选一,与正则中一样  
select cust_contact from Customers where cust_contact like '[JM]%';  

使用通配符会耗费更多的时间,作者给了注意事项:

  • 不要过度使用通配符,能用普通的搞就用普通的搞,

  • 用的时候,不要放在第一个条件,

  • 小心使用,用错了,不会返回结果的,

  • 得根据具体的DBMS文档来,有些可能不支持。

数据拼接#

-- 把多个数据拼在一起,不同DBMS使用的符号可能不同  
select vend_name || '(' || vend_country || ')' as vend_title from Vendors order by vend_name;  

函数调用#

一般的DBMS会提供的函数

  • 文本操作,截断、拓展、大小写转换,

  • 数字运算,绝对值、加减乘除,

  • 时间函数,

  • 系统函数,返回具体DBMS使用的信息。

    select vend_name, upper(vend_name) as up from Vendors order by vend_name;

聚合函数#

  • avg(), 列的平均值,

  • count(), 列的数量,

  • max(),列的最大值,

  • min(),列的最小值,

  • sum(),对列求和。

    select count(*), min(prod_price), max(prod_price), avg(prod_price) from Products;

数据分组#

-- 每个客户有多少个产品  
select vend_id, count(*) as num_prods from Products group by vend_id;  
  
-- where筛选rows,having筛选groups,having支持所有的where操作  
select vend_id, count(*) as num_prods from Products where prod_price >= 4 group by vend_id having count(*) >= 2;  

嵌套查询#

-- 还可以多层嵌套的  
select cust_id from Orders where order_num in (select order_num from OrderItems where prod_id = 'RGAN01');  

join#

把不同表的数据,同时查出来,比嵌套查询效率高。

select prod_name, vend_name, prod_price, quantity from OrderItems, Products, Vendors  
    where Products.vend_id = Vendors.vend_id and OrderItems.prod_id = Products.prod_id and order_num = 20007;  
      
-- 使用别名  
select cust_name, cust_contact from Customers as C, Orders as O, OrderItems as OI  
    where C.cust_id = O.cust_id  
    and OI.order_num = O.order_num  
    and prod_id = 'RGAN01';  

outer join和inner join的区别

-- inner join,都有数据的,才会返回  
select C.cust_id, O.order_num from Customers as C inner join Orders as O  
    on C.cust_id = O.cust_id;  
      
-- outer join,只要左边能找到,就列出来;右边找不到,列出空内容  
select C.cust_id, O.order_num  
    from Customers as C left outer join Orders as O  
    on C.cust_id = O.cust_id;  

总结一下join的关键点

  • 注意join的使用类型。inter和outer的区别,

  • DBMS的具体join语法,

  • 确保使用了正确的join条件,

  • 确保总是提供join条件,

  • 使用join之前,可以将各个条件分别使用一番。

union#

-- 直接把不同的查询一起输出  
select cust_name, cust_contact, cust_email  
    from Customers as C  
    where cust_state in ('IL', 'IN', 'MI')  
    union  
    select cust_name, cust_contact, cust_email  
    from Customers  
    where cust_name = 'Fun4All';  

增删改#

-- 基础插入  
insert into Customers  
    (cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)  
    values('1000000007', 'Toy Land1', '123 Anya Street', 'Newa York', 'NY', '11111', 'USDA', NULL, NULL);  
      
-- 从一个表搬到另一个表  
insert into CustNew(cust_id, cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)  
    select cust_id, cust_contact, cust_email, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country from Customers  
    where cust_id in ('1000000006', '1000000007');  

修改、删除行为准则:

  • 永远不要执行一个没有where的语句,除非你真的要操作所有,

  • 保证每个表都有主键,

  • 使用where之前,可以先用select测试是否正确,

  • 使用数据库的强制规则保证完整性(enforced referential integrity),

  • 有些DBMS是支持给delete、update加约束(比如必须有where)的,如果有,用上。

    – update
    update Customers set cust_contact = ‘Sam Roberts’, cust_email = ‘sam@toyland.com’ where cust_id = ‘1000000006’;

    delete from Customers where cust_id = ‘1000000006’;

创建、删除表#

作者建议创建可以使用图形化界面,相较于敲指令,会更方便一些。

-- 创建  
create table Test1  
    (name char(10) not null,  
    age decimal(8, 2) not null  
    );  
      
-- 修改  
alter table Test1 add phone char(11);  
  
-- 删除  
drop table Test2;  

高级内容#

view是虚拟表,不包含数据,只在SQL语句真正执行的时候才查询需要数据。使用原因:

  • 重用SQL语句,

  • 简化复杂的SQL操作,

  • 只暴露部分表格,

  • 数据保护,可以设定用户只访问指定数据,

  • 改变数据格式和表现。

    – 创建视图
    create view ProductCustomers as
    select cust_name, cust_contact, prod_id
    from Customers, Orders, OrderItems
    where Customers.cust_id = Orders.cust_id and OrderItems.order_num = Orders.order_num;

    – 使用视图
    select cust_name, cust_contact from ProductCustomers where prod_id = ‘RGAN01’;

Stored Procedures#

存储过程,代码重用,与DBMS强关联,基本上大佬写,小弟用。哈哈。

-- oracle下面创建  
CREATE PROCEDURE MailingListCount (  
    ListCount OUT INTEGER   
)  
IS  
v_rows INTEGER;  
BEGIN  
    SELECT COUNT(*) INTO v_rows  
    FROM Customers  
    WHERE NOT cust_email IS NULL;  
    ListCount := v_rows;  
END;  
  
-- oracle下面使用  
var ReturnValue NUMBER  
EXEC MailingListCount(:ReturnValue);  
SELECT ReturnValue;  

Transaction Processing#

事务处理,保证SQL批量操作能够完整(部分完整)执行。

Cursors#

游标,一坨从数据库查询出来的缓存数据。可以前后挪动查看结果。

Advanced SQL Features#

Constraints,主键、外键、数据唯一性、指定条件,都是约束。

Indexes,提升查找、排序的速度,类似书籍的页码。

Triggers,特殊的存储过程,某些情况发生的时候,触发执行一下。

Security,数据库的安全管理。 原文链接