SQL必知必会

#数据库
#数据库为一些表的集合,表的每列为某一类数据类型的数据,每行为一记录

#主键
#每个表都有一列唯一标识记录的数据,称为主键
#同一表中任意两行数据都有不相同的主键,主键值不允许为NULL
#主键值不允许修改和重用



#检索
#从表1中检索列1         select 列1 from 表1
#从表1中检索列1,列2    select 列1,列2 from 表1
#sql语句不区分大小写,但表名列名是区分的
#每条sql语句以英文  ;  结尾,sql忽略缩进


#去重
#distinct指示数据库只返回不同的值
E: select distinct vend_id from Products;
#distinct关键字作用于其后所有的列


#限制结果
#limit, select list from table limit m,n;或limit n
#上面m为检索开始的索引,n为需要检索的记录条数,limit后只有一个数默认从索引0开始
#表中第一个索引,即第一行记录为0


#排序结果
#为保证每次检索结果顺序的唯一性,一般需要进行排序,order by
#select ... from 表 order by 列
#可依据多列进行排序,order by列1,列2
#可依据位置排序,select 列1,列2 form 表1 order by 2,1;(先依据列2再依据列1)
#可降序排列,关键词desc
E: select 列1 form 表1 order by 列2desc;
#desc只作用于其前面的那一列


#过滤数据
#where子句位于from子句之后
#where子句的操作符 = 等于、!=不等于、is null 为NULL值、between在两值之间
#!=3不返回含NULL的观测
#between用法为  between m and n

#多条件过滤
#即where子句为一些条件的组合
#进行组合的关键字为 or and not in
#当有多个条件时用括号进行分隔
E: select prod_name,prod_price from Products where vend_id in ("DLL01',"BRS01');
E: select prod_name from Products where not vend_id="DLL01';


#含通配符的过滤
#在搜索子句中使用通配符时,必须使用like操作符
# % 表示任何自出出现任意次数
E: select prod_id,prod_name from Products where prod_name like 'Fish%';
# like '%' 不会匹配为NULL的行

# _ 用法同 % ,但其只匹配单个字符



#计算字段
#即对检索出来的数据进行转换、计算或格式化的过程

#拼接字段
#concat(内容1,内容2,内容3)
E: select Concat(vend_name,'(',vend_country,')') from Vendors order by vend_name;
#在进行拼接操作时,一般需去空格操作
E: select concat(rtrim(vend_name),'(',rtrim(vend_country),')') from Vendors;

#使用别名
#别名用as关键字赋予,新的别名不用加引号
E: select concat(rtrim(vend_name),'(',trim(vend_country),')') as vend_title from Vendors;





常用文本处理函数

left(str,length)
#从字符串左边开始截取一定长度的字符
E: select left('example',3)
#当length超过最大长度也可

right(str,length)
#从字符串右边开始截取一定长度的字符

lenth()
#返回字符串的长度

ltrim()
#去掉字符串左边的空格

rtrim()
#去掉字符串右边的空格

lower()
#将字符串转换为小写

upper()
#将字符串转换为大写

substring(str,length)
#从字符串一定位置开始截取到最后的字符

substring(str,length1,length2)
#从字符串一定位置开始截取一定长度的字符

soundex()
#将文本转换为描述性语音
E: select * from Table1 where soundex(tab1_name) = soundex('Y San')
#其可以将‘Y sam’检索出来


#数据类型的转换

convert(value,type)
#获取value数据后生成type类型的数据
E:select convert('3.35',signed);
#可以转换的数据类型
#二进制,binary
#字符型,char
#日期,date
#时间,time
#日期时间型,datetime
#浮点数,decimal
#整数,signed
#无符号整数,unsigned



#时间日期相关函数

now()
#生成年月日时间
E: select now()
2019-02-18 13:22:21

curdate()
#生成年月日

curtime()
#生成时间



#MySQL的数据类型

#文本
char       固定长度字符串(可包含字母、数字及特殊字符)最多255个字符
varchar    可变长度字符串(可包含字母、数字及特殊字符)最多255个字符
text       存放最大长度65535个字符的字符串
mediumtext 存放最大长度16777215个字符的字符串

#数字
int        -2147483648到2147483647
float      带有浮动小数点的小数字
double     带有浮点小数点的大数字
decimal    作为字符串储存的double类型

#日期
date        日期,格式YYYY-MM-DD
datetime    日期和时间的组合,格式YYYY-MM-DD HH:MM:SS
time        时间,格式HH:MM:SS
year        日期,格式YYYY


#常用数值处理函数

abs()         返回一个数的绝对值
cos()         返回一个数的余弦
sin()         返回一个数的正弦
tan()         返回一个数的正切
exp()         返回一个数的指数值
sqrt()        返回一个数的平方根
pi()          返回圆周率
ceil(x)       返回大于x的最大整数值
floor(x)      返回小于x的最大整数值
mod(x,y)      同x%y,返回x/y的模,即作整除然后取余,被除数和除数都可为小数
round(x[,d])  将数字x四舍五入到指定小数位d
truncate(x,d) 将数字x截断到指定的小数位数d
rand()        返回0到1的随机数,可以设定随机数种子,rand(4)


#常用聚集函数
#对某些行运行的函数

avg()     返回某列的平均值,只用于单列
E: sleect avg(prod_price) as avg_price from Products where vend_id = "DLL01"
count()   返回某列的行数
max()     返回某列的最大值或最大日期,忽略为NULL的行
min()     返回某列的最小值或最小日期,忽略为NULL的行
sum()     返回某列值之和,忽略列值为NULL的行
E:select sum(item_price*quantity) as total_price from OrderItems where order_num = 2005
#聚集参数
一般默认为所有行执行,当需对只包含不同的值执行时用到distinct
E:select avg(distinct prod_price) as avg_price from Products where vend_id = "DLL01"


#分组数据
#使用分组可以将数据分为多个逻辑组,对每个组进行聚集计算,即便于聚集函数的汇总数据
#分组使用select语句的group by子句建立

E: select vend_id,count(*) as num_prods from Products group by vend_id;
即  select 分组依据列1,聚集函数操作 from Table group by 分组依据列1

#group by后可接任意数目的分组列,构成嵌套分组
E: select Dept,Edlevel,max(salary) as Maximum from Staff group by Dept,Edlevel
#分组依据中含NULL时,NULL作为一个分组标准
#select语句中,除去聚集函数操作,不能包含分组依据列名外的列名
#一般不允许分组列包含长度可变的数据类型(如文本或备注型字段)
#group by子句必须出现在where子句之后,order by子句之前


#过滤分组
#即过滤掉一些分组依据得到的分组
#过滤分组用having,其用法同where,但where只是选择符合条件的行,并不能过滤分组
E: select cust_id,count(*) as orders from orders group by cust_id having count(*)>=2;

#where和having可在分组中连用,先行过滤where,再分组group by,再分组过滤having
E: select vend_id,count(*) as num_prods from Products where prod_price >=4 group by vend_id
having count(*) >=2
#以上分析:首先,where子句过滤出prod——price至少为4的行,其次,按vend_id分组数据,最后,having
子句过滤出计数至少为2的分组




#分组排序
E: select vend_id,count(*) as num_prods fro Produts group by vend_id order by vend_id;
#注意,依靠group by得到的分组并不总是以分组顺序给出的
#一般在使用group by子句时,为确保排序的结果唯一,同时给出order by子句
#同group by,order by也可分组嵌套,order by 在子句最后
E: select order_num,count(*) as items from OrderItems group by order_num having count(*)
>=3 order by itemsorder_num;


#子查询
#即嵌套在其他查询中的查询,包括where子句中的子查询和计算字段中的子查询

#子查询用于where子句
E: select cust_id from Orders
          where order_num in (select order_num from OrderItems where prod_id='RGAN01');
#select语句中子查询总是从内向处理,使用子查询利用好缩进
#子查询可以嵌套
E: select cust_name,cust_contact from Customers
           where cust_id in (select cust_id from Orders
                                   where order_num in (select order_num for OrderItems
                                                            where prod_id='RGAN01'));



#计算字段使用子查询
#即对检索出的每个记录(行数据)使用一次子查询
E: select cust_name,cust_state,
          (select count(*) from Orders where Orders.cust_id = Customers.cust_id) as orders
                 form customers order by cust_name;
                                               
#计算字段中子查询可以使用子查询中from表的列,也可使用最外面form表的列
#计算字段中子查询使用最外面from表的列时要使用完全限定列名,即外表名.外表列名
#完全限定列名,即表名.列名,select操作多个表时,应使用完全限定列名来避免歧义




#关系表与关系数据库的设计
#关系表的设计即把信息分解成多个表,一类数据一个表,各表通过某些共同的值相互关联。



#联结
#当信息储存在多个表,可使用联结在一个select语句中检索出全部所需数据
#联结原理,select  ...  form表1,表2
                        where 表名1.列名a = 表名2.列名b;
#当要多联结时,select ... form表1,表2,表3
                        where 表名1.列名a=表名2.列名b and 表名2.列名c=表名3.列名d
E: select vend_name,prod_name,prod_price from Vendors,Produts
                                where Vendors.vend_id=Prodects.vend_id;
#上面vend_name,prod_name是Vendors中的列,prod_price为Produts中的列
#当无联结条件即无where子句,称为笛卡尔积,检索出的行数为第一个表的行数乘第二个表的行数


#内联结
#inner join on
E: select vend_name,prod_name,prod_price
          from Vendors inner join Products on Vendors.ven_id=Products.vend_id;
#即inner join 两端为需要联结的表,on 后面为具体两表要联结的列,效果与上面相同


#表别名
#使用表别名缩短了sql语句,允许在一个select语句中多次使用相同的表
#表别名可用于where子句、完全限定列名、order by子句等
E: 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';

#自联结
#即联结操作中两个表是同一个表
E: 选出与 jim Jones同一公司的所有顾客
E: select c1.cust_id,c1.cust_name,c1.cust_contact from Customers as c1,Customers as c2
          where c1.cust_name =c2.cust_name and c2.cust_contact = 'Jim Jones';

#自然联结
#无论何种联结,应该至少有一列不止出现在一个表中
#自然联结针对某表,使该表所含的需要与其他表联结的相同列,结果中只出现一次
#对某表进行自然联结使用 表.*
E: select c.*,o.order_num,o.order_date, from customers as c, orders as o
          where c.cust_id = o.cust_id and prod_id ='GCAN01';
#上面 c.* 作用,当c表含有order_num列和order_date列,限定这两次在结果中只出现一次

#一般所有的所有的内联结都是自然联结,一般用不到不是自然联结的内联结



#外联结
#对外联结,联结包含了那些在相关表中没有关联行的行
#用法,from 表1 left outer join 表2 on 表1.列1 = 表2.列1
#表1.列1与表2.列1联结,只要表1.列1出现的,无论表2.列1有无与其对应,都会检索出来
E: select table1.price,table2.id,table1.state
           from table2 left outer join table1
                on table2.id = table1.id
#left outer join检索出左表所有,right outer join检索出右表所有


#联结中使用聚合函数
E: select Customers.cust_id,count(Orders.order_num) as num_ord
            from Customers inner join Orders
                 on  Customers.cust_id = Orders.cust_id
                      group by Customers.cust_id;




#组合查询
#一般一条sql语句返回一个结果,组合查询即执行多个查询并返回一个结果
#用union组合多条select语句
E: select cust_name,cust_contact,cust_email from Customers
           where cust_state in ('IL','IN','MI')
   union
   select cust_name,cust_contact,cust_email from Customers
           where cust_name = 'Fun4All';
#对于复杂顾虑条件,或从多个表中检索,用union会更简单
#union中的每个查询必须含相同的列、表达式或聚集函数
#union对结果自动去除重复的行,同where or,union all 不去重
#union中只能使用一条order by,放在最后




#插入数据
E: insert into table values('a',11,NULL)
#上面操作并不安全,表结构发生变化时,不再适用
E: insert into Customers(cust_id,cust_name,cust_address)
              values('1000006','Toy Land','123 any Street');
#insert中可以省略列,省略的列使用默认值


#插入检索出的数据
#insert select
#insert into Customers(cust_id,cust_contact,cust_email)
             select cust_id,cust_contact,cust_email) from CustNew;

#复制到新表
E: create talbe CustoCopy as select * from Customers;





#更新数据
#更新(修改)表中数据,使用update
E: update Customers set cust_email='hello@ss.com'
                   where cust_id = '1000034';
#更新多个列,update talbe set list1 = ... ,list = ... ,
                    where ...
#where 条件中 空字符 不等于 NULL

#删除数据
E: delete from Customers where cust_id = '100032';

#主键与外键
#主键是每行数据的唯一标识,外键能保证表与表之间的数据的完整性和准确性
#外键可以防止数据的误删




#创建表
E: create table NowProducts(
          prod_id   char(10)   not null,
          vend_id   char(10)   not null,
          prod_num  int(4)     nul     );
#上面括号中为列名,数据类型及解释,是否允许为空
#一般null为默认,即默认允许为空
 

#默认值
E: create talbe OrderItems(
          order_num    char(10)  not null default 1);
#默认值常用于日期或时间,如使用now() 函数



#更新表

#删除列
#用法, alter table 表名 drop column 列名

#添加列
#用法,alter table 表名 add column 列名 数据类型及解释
E: alter table Person add column birthday char(20);

#删除表
#用法,drop table 表名

#修改表名
#rename table 原表名 to 新表名



#视图
视图是虚拟的表,即是查询的结果
E: select cust_name,cust_contact from ProductCustomers
          where prod_id = 'RGAN01';
#上面ProductCustomers为一个视图,其包含一个查询
#视图可以简化sql操作,可以嵌套,但会降低性能
#使用视图时,禁止使用order by

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




#存储过程
#一组为了完成特定功能的sql语句集,静态编译后存储在数据库中
#对sql语句执行时需要先编译再执行,存储过程提高了性能,简化了操作

#存储过程的执行
#: call Procedurename(value1,value2,...)
#存储过程不返回值,只是修改值


#存储过程的创建

E:
  drop procedure if exists 'myproc';
  delimiter ;;
  create procedure myproc(in value_a int,in value_b int,out value_sum int)
  begin
     declare c int;
     if value_a is null then set a = 0;
     end if;

     if value_b is null then set b = 0;
     end if;

     set sum = a + b;
   end
   ;;
   delimiter ;

#存储过程的关键字
#存储过程有关键字 in out inout
#in 表示后面的变量为只读的,即只读入存储过程中
#out 表后后面的变量


posted @ 2019-05-28 14:35  林远  阅读(573)  评论(0)    收藏  举报