Skip to content

Latest commit

 

History

History
898 lines (619 loc) · 28.2 KB

sql.md

File metadata and controls

898 lines (619 loc) · 28.2 KB

数据操纵语言(DML)命令包括:SELECT(查询)、INSERT(添加)、UPDATE(修改)、DELETE(删除);用于检索、插入和修改数据。

数据定义语言(DDL)命令包括:CREATE、ALTER、DROP、TRUNCATE、RENAME等;用于改变数据库结构。

==TRUNCATE TABLE== 删除表中的所有行,但表结构及其列、约束、索引等保持不变。

数据控制语言(DCL)命令是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句

数据库对象主要包含:触发器(Trigger)、表(Table)、视图(View)、存储过程(StoredProcedure)、索引(Index)、缺省值(Default)、图表(Diagram)、用户(User)、规则(Rule)等几类。

数据操纵语言(DML)

查询SELECT

检索数据

  • 大小写

SQL 语句关键字、函数名等对大小写不敏感。SELECT 等效于 select,但在通配符匹配时区分。建议关键字都大写,列和表名小写

  • 不同行

关键词 DISTINCT 用于返回唯一不同的值,且应用于其后的所有列。

  • 限制结果
SELECT column_name(s) FROM table_name LIMIT number

number指示返回不多于number行;还可制定检索的开始行和行数:

SELECT column_name(s) FROM table_name LIMIT 11

检索出第2行(检索出来第一行为行0)

排序数据

order by 子句中的列不一定为检索列;

默认排序方式为升序;降序需要DESC关键字,即:

SELECT xx FROM xx ORDER BY xx DESC;

order by 和 limit 组合找出列中最高/低值:

SELECT xx FROM xx ORDER BY xx DESC LIMIT 1;

过滤数据

在有order by 时,order by 一定位于 where 后。

在一般执行匹配时,默认不区分大小写(通配符匹配要)

  • 范围匹配:

    注意:between...and...是闭区间;日期字符串可以用between...and...比较

SELECT xx FROM xx WHERE xx BETWEEN xx AND xx;
  • 空值匹配:
SELECT xx FROM xx WHERE xx IS NULL (IS NOT NULL);
1. 组合where子句

通过AND 和 OR关键字组合 WHERE 子句;AND优先级高于OR,故注意使用括号.

2. IN操作符

IN 和 WHERE搭配使用,指定要匹配值的清单;

3. NOT操作符

通常用 NOT BETWEEN, NOT IN, NOT EXISTS

4. 通配符过滤

==LIKE:LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式==。

%还能匹配0个字符,但不能匹配 NULL;

SELECT column_name(s) FROM table_name WHERE column_name LIKE 'N%';
SELECT column_name(s) FROM table_name WHERE column_name NOT LIKE 'N%';

此时区分大小写匹配。

计算字段

1.拼接字段
SELECT Concat(RTrim(vend_name),'(',vend_country,')') FROM vendors ORDER BY vend_name;

结合RTrim和LTrim进行拼接。

2.表别名
SELECT Concat(RTrim(vend_name),'(',vend_country,')') AS vend_title FROM vendors ORDER BY vend_name;
3.算数操作符

+、-、*、/,均可用于select之后

sql函数

1.字符函数

CONCAT(X,Y) 连接字符串X和Y

LENGTH(X) 返回X的长度

LOWER(X) X转换成小写

UPPER(X) X转换成大写

LTRIM(X[,TRIM_STR]) 把X的左边截去trim_str字符串,缺省截去空格

RTRIM(X[,TRIM_STR]) 把X的右边截去trim_str字符串,缺省截去空格

TRIM([TRIM_STR FROM]X) 把X的两边截去trim_str字符串,缺省截去空格

REPLACE(X,old,new) 在X中查找old,并替换成new

SUBSTR(X,start,length) 返回X的子串,从start处开始,截取length个字符;缺省length,默认到结尾。字符串用单引号括起来

2.日期函数

日期转换函数:

MySQL 日期、时间转换函数date_format:date_format(date,format), time_format(time,format) 能够把一个日期/时间转换成各种各样的字符串格式。它是 str_to_date(str,format) 函数的一个逆转换。

select date_format('2008-08-08 22:23:01', '%Y%m%d%H%i%s');

+----------------------------------------------------+
| date_format('2008-08-08 22:23:01', '%Y%m%d%H%i%s') |
+----------------------------------------------------+
| 20080808222301 |
+----------------------------------------------------+
select str_to_date('08/09/2008', '%m/%d/%Y'); -- 2008-08-09
select str_to_date('08/09/08' , '%m/%d/%y'); -- 2008-08-09
select str_to_date('08.09.2008', '%m.%d.%Y'); -- 2008-08-09
select str_to_date('08:09:30', '%h:%i:%s'); -- 08:09:30
select str_to_date('08.09.2008 08:09:30', '%m.%d.%Y %h:%i:%s'); -- 2008-08-09 08:09:30

MySQL 拼凑日期、时间函数:makdedate(year,dayofyear), maketime(hour,minute,second)

select makedate(2001,31); -- '2001-01-31'
select makedate(2001,32); -- '2001-02-01'
select maketime(12,15,30); -- '12:15:30'

日期计算函数:

MySQL 日期、时间相减函数datediff:datediff(date1,date2), timediff(time1,time2)

MySQL datediff(date1,date2):两个日期相减 date1 - date2,返回天数。
select datediff('2008-08-08', '2008-08-01'); -- 7
select datediff('2008-08-01', '2008-08-08'); -- -7

MySQL timediff(time1,time2):两个日期相减 time1 - time2,返回 time 差值。

select timediff('2008-08-08 08:08:08', '2008-08-08 00:00:00'); -- 08:08:08
select timediff('08:08:08', '00:00:00'); -- 08:08:08

注意:timediff(time1,time2) 函数的两个参数类型必须相同。mysql中变量不用事前申明。

set @dt = '2008-09-10 07:15:30.123456';

select date(@dt); -- 2008-09-10
select time(@dt); -- 07:15:30.123456
select year(@dt); -- 2008
select quarter(@dt); -- 3
select month(@dt); -- 9
select week(@dt); -- 36 返回一年对应的周数
select day(@dt); -- 10
select hour(@dt); -- 7
select minute(@dt); -- 15
select second(@dt); -- 30
select microsecond(@dt); -- 123456

last_day() 函数:返回月份中的最后一天。

select last_day('2008-02-01'); -- 2008-02-29

select last_day('2008-08-08'); -- 2008-08-31

MySQL last_day() 函数非常有用,比如我想得到当前月份中有多少天,可以这样来计算:

Copy select now(), day(last_day(now())) as days;

+---------------------+------+
| now() | days |
+---------------------+------+
| 2008-08-09 11:45:45 | 31 |
+---------------------+------+

TO_DAYS函数:

SELECT TO_DAYS('1997-10-07');   

结果 729669 就是从0年开始到1997年10月7号之间的天数。

查询某一天数据:

--今天
select * from 表名 where to_days(时间字段名) = to_days(now());
--昨天
SELECT * FROM 表名 WHERE TO_DAYS(NOW( )) - TO_DAYS( 时间字段名) <= 1

date_add()和adddate()是同义词.

与 DATE_SUB() 相反

参数说明:

  date:起始日期或者起始时间

  expr:指定的是一个间隔值,在起始时间中增加或者减少,注意:expr是一个字符串.对于负值间隔,可以以"-"开头

  unit:表示的是一个单位,比如,加上的是1天还是一个小时.

1.对某个日期加上n天的操作

select date_add('2018-06-26',INTERVAL 5 day);
+-----------------------------------------+
| date_add('2018-06-26',INTERVAL 5 day) |
+-----------------------------------------+
| 2018-07-01                              |
+-----------------------------------------+
row in set (0.00 sec)

mysql> select date_add('2018-06-26',INTERVAL -5 day);
+------------------------------------------+
| date_add('2018-06-26',INTERVAL -5 day) |
+------------------------------------------+
| 2018-06-21                               |
+------------------------------------------+
row in set (0.01 sec)

近7SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(时间字段名)

近30SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(时间字段名)

img

日期between用法:

查询2016-10-17到2016-10-18的数据【闭区间】:

WHERE Date BETWEEN '2016-10-17' AND '2016-10-18'
等价于
WHERE [Date] >= '2016-10-17 00:00:00:000' AND [Date] <= '2016-10-18 00:00:00:000'

2.

查询本季度数据
select * from `ht_invoice_information` where QUARTER(create_date)=QUARTER(now());
查询上季度数据
select * from `ht_invoice_information` where QUARTER(create_date)=QUARTER(DATE_SUB(now(),interval 1 QUARTER));
查询本年数据
select * from `ht_invoice_information` where YEAR(create_date)=YEAR(NOW());
查询上年数据
select * from `ht_invoice_information` where year(create_date)=year(date_sub(now(),interval 1 year));
3.聚集函数

avg():忽略列值为null的行

SELECT Customer FROM Orders WHERE OrderPrice>(SELECT AVG(OrderPrice) FROM Orders)   

select avg(distinct XX) AS XX from XX where XX=  ;

count():

SELECT COUNT(DISTINCT Customer) AS NumberOfCustomers FROM Order   

count(*) 包含null,count(列名)忽略null

max():MAX 函数返回一列中的最大值。忽略列值为null的行 。 MIN 和 MAX 也可用于文本列,以获得按字母顺序排列的最高或最低值。

sum():忽略列值为null的行。

SELECT SUM(OrderPrice) AS OrderTotal FROM Orders 

输出结果以别名显示

4.高级函数

case/ case when

--简单Case函数
CASE sex
WHEN '1' THEN ''
WHEN '2' THEN ''
ELSE '其他' END 
--搜索函数 
CASE WHEN sex = '1' THEN '' 
WHEN sex = '2' THEN '' 
ELSE '其他' END  

示例:

select 
sum(HTZJE) as ysje,--预算金额
sum(yfje) as ljfse,--累计发生额
sum(jyje) as jyje,--结余金额
(sum(jyje) / sum(HTZJE)) as jezb, --结余占比
(sum(yfje) / sum(HTZJE)) as fyzb,--费用占比
case htlb
when '1' then 'cblb1'
when '2' then 'cblb2'
when '3' then 'cblb3'
ELSE '其他' END bieMing
from tb_table
group by bieMing

用到 case when 的字段作为别名的时候一定不要加“as” 否则会报错。直接在END 后加上想用的别名即可。如:文中 bieMing

窗口函数:函数名(列)over(选项)

普通聚合函数每组只能返回一个值,而开窗函数可以每组返回多个值。

​ 比如我们想查询每个工资小于5000元的员工信息(城市以及年龄),并且在每行中都显示所有工资小于5000元的员工个数,执行下面的SQL语句:

select t.fcity,t.fage,count(*) from person t where t.fsalary<5000

​ 这个语句显然是错误的,因为count()是聚合函数,然后fname和fage字段没有包含在分组里面。

select t.fcity,t.fage,count(*) from person t where t.fsalary<5000 group by t.fcity,t.fage

​ 这与我们每行中都显示所有工资小于5000元的员工个数这个条件是不符合的(这是分组统计)。

select t.fcity,
       t.fage,
       (select count(*) from person f where f.fsalary < 5000)
  from person t
 where t.fsalary < 5000	

​ 这次的查询结果和我们想要的结果一样了,但是这样写多了一个子查询,非常麻烦。使用开窗函数可以大大简化实现.

select t.fcity, t.fage, count(*) over()
   from person t
  where t.fsalary < 5000

​ over关键字表示把函数当成开窗函数而不是聚合函数,SQL标准允许将所有聚合函数用做开窗函数,使用over关键字来区分这两种用法。

​ 在上面的例子中,开窗函数count(*) over()对于查询结果的每一行都返回所有符合条件的行的条数,如果over关键字后的括号中选项为空,则开窗函数会对结果集中的所有行进行聚合运算。

partition by 子句

​ 开窗函数的over关键字后括号中可以使用 Partition by 子句来定义行的分区,进行聚合运算。与group by 字句不同,partition by子句创建的分区是独立于结果集的,创建的分区只是提供聚合计算的,而且不同的开窗函数所创建的分区也不相互影响。

  1. 下面的sql语句用于显示每一个人员的信息以及所属城市的人员数:
select t.fname,
         t.fcity,
         t.fage,
         count(*) over(partition by t.fcity)
    from person t

​ count(*)over(partition by t.fcity) 表示对结果集按照 fcity 进行分区,并且计算当前行所属区的聚合计算结果。

  1. 在同一个SELECT语句中可以同时使用多个开窗函数,而且这些开窗函数不会相互影响。比如,显示每一个人员的信息、所属城市的人员数以及同龄人的人数:
select t.fname,
         t.fcity,
         t.fage,
         count(*) over(partition by t.fcity) as "城市分组",
         count(*) over(partition by t.fage) as "年龄分组"
    from person t

partition by用于给结果集分组,如果没有指定那么它把整个结果集作为一个分组。

Rank 是在每个分组内部进行排名的。

rank() 排序相同时会重复,总数不会变

dense_rank() 排序相同时会重复,总数会减少

row_number() 会根据顺序计算

5.窗口分析函数

SUM,AVG,MIN,MAX

sum(...) over( ),对所有行求和

sum(...) over( order by ... ),第一行到与当前行同序号相同的所有行的所有值求和

with aa as
( 
SELECT 1 a,1 b, 3 c FROM dual union
SELECT 2 a,2 b, 3 c FROM dual union
SELECT 3 a,3 b, 3 c FROM dual union
SELECT 4 a,4 b, 3 c FROM dual union
SELECT 5 a,5 b, 3 c FROM dual union
SELECT 6 a,5 b, 3 c FROM dual union
SELECT 7 a,2 b, 3 c FROM dual union
SELECT 8 a,2 b, 8 c FROM dual union
SELECT 9 a,3 b, 3 c FROM dual
)
SELECT a,b,c,
sum(c) over(order by b) sum1,--有排序,求和当前行所在顺序号的C列所有值
sum(c) over() sum2--无排序,求和 C列所有值
from aa;

img

sum(...) over( partition by... ),同组内所行求和

sum(...) over( partition by... order by ... ),同第1点中的排序求和原理,只是范围限制在组内

with aa as
( 
SELECT 1 a,1 b, 3 c FROM dual union
SELECT 2 a,2 b, 3 c FROM dual union
SELECT 3 a,3 b, 3 c FROM dual union
SELECT 4 a,4 b, 3 c FROM dual union
SELECT 5 a,5 b, 3 c FROM dual union
SELECT 6 a,5 b, 3 c FROM dual union
SELECT 7 a,2 b, 3 c FROM dual union
SELECT 7 a,2 b, 8 c FROM dual union
SELECT 9 a,3 b, 3 c FROM dual
)
SELECT a,b,c,sum(c) over( partition by b ) partition_sum,
sum(c) over( partition by b order by a desc) partition_order_sum
  FROM aa;

img

WINDOW子句:rows between ... preceding and ... following

    SELECT cookieid,
    createtime,
    pv,
    SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime) AS pv1, -- 默认为从起点到当前行
    SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS pv2, --从起点到当前行,结果同pv1
    SUM(pv) OVER(PARTITION BY cookieid) AS pv3,        --分组内所有行
    SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) AS pv4, --当前行+往前3行
    SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) AS pv5, --当前行+往前3行+往后1行
    SUM(pv) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS pv6 ---当前行+往后所有行
    FROM lxw1234;
     
    cookieid createtime pv pv1 pv2 pv3 pv4 pv5 pv6
    -----------------------------------------------------------------------------
    cookie1 2015-04-10 1 1 1 26 1 6 26
    cookie1 2015-04-11 5 6 6 26 6 13 25
    cookie1 2015-04-12 7 13 13 26 13 16 20
    cookie1 2015-04-13 3 16 16 26 16 18 13
    cookie1 2015-04-14 2 18 18 26 17 21 10
    cookie1 2015-04-15 4 22 22 26 16 20 8
    cookie1 2015-04-16 4 26 26 26 13 13 4

如果不指定ROWS BETWEEN,默认为从起点到当前行;

如果不指定ORDER BY,则将分组内所有值累加;

关键是理解ROWS BETWEEN含义,也叫做WINDOW子句:

PRECEDING:往前

FOLLOWING:往后

CURRENT ROW:当前行

UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING:表示到后面的终点

lag,lead函数类似于preceding和following子句

LAG(col,n,DEFAULT) 用于统计窗口内往上第n行值

第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往上第n行为NULL时候,取默认值,如不指定,则为NULL)

与LAG相反,LEAD(col,n,DEFAULT) 用于统计窗口内往下第n行值

第一个参数为列名,第二个参数为往下第n行(可选,默认为1),第三个参数为默认值(当往下第n行为NULL时候,取默认值,如不指定,则为NULL)

Ntile函数

​ 它把有序的数据集合 **平均分配 **到 指定的数量(num)个桶中, 将桶号分配给每一行。如果不能平均分配,则优先分配较小编号的桶,并且各个桶中能放的行数最多相差1。

first_value

取分组内排序后,截止到当前行,第一个值。

SELECT cookieid,
createtime,
url,
ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn,
FIRST_VALUE(url) OVER(PARTITION BY cookieid ORDER BY createtime) AS first1 
FROM lxw1234;
 
cookieid  createtime            url     rn      first1
---------------------------------------------------------
cookie1 2015-04-10 10:00:00     url1    1       url1
cookie1 2015-04-10 10:00:02     url2    2       url1
cookie1 2015-04-10 10:03:04     1url3   3       url1
cookie1 2015-04-10 10:10:00     url4    4       url1
cookie1 2015-04-10 10:50:01     url5    5       url1
cookie1 2015-04-10 10:50:05     url6    6       url1
cookie1 2015-04-10 11:00:00     url7    7       url1
cookie2 2015-04-10 10:00:00     url11   1       url11
cookie2 2015-04-10 10:00:02     url22   2       url11
cookie2 2015-04-10 10:03:04     1url33  3       url11
cookie2 2015-04-10 10:10:00     url44   4       url11
cookie2 2015-04-10 10:50:01     url55   5       url11
cookie2 2015-04-10 10:50:05     url66   6       url11
cookie2 2015-04-10 11:00:00     url77   7       url11

last_value

取分组内排序后,截止到当前行,最后一个值

SELECT cookieid,
createtime,
url,
ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn,
LAST_VALUE(url) OVER(PARTITION BY cookieid ORDER BY createtime) AS last1 
FROM lxw1234;
 
 
cookieid  createtime            url    rn       last1  
-----------------------------------------------------------------
cookie1 2015-04-10 10:00:00     url1    1       url1
cookie1 2015-04-10 10:00:02     url2    2       url2
cookie1 2015-04-10 10:03:04     1url3   3       1url3
cookie1 2015-04-10 10:10:00     url4    4       url4
cookie1 2015-04-10 10:50:01     url5    5       url5
cookie1 2015-04-10 10:50:05     url6    6       url6
cookie1 2015-04-10 11:00:00     url7    7       url7
cookie2 2015-04-10 10:00:00     url11   1       url11
cookie2 2015-04-10 10:00:02     url22   2       url22
cookie2 2015-04-10 10:03:04     1url33  3       1url33
cookie2 2015-04-10 10:10:00     url44   4       url44
cookie2 2015-04-10 10:50:01     url55   5       url55
cookie2 2015-04-10 10:50:05     url66   6       url66
cookie2 2015-04-10 11:00:00     url77   7       url77

如果想要取分组内排序后最后一个值,则

FIRST_VALUE(url) OVER(PARTITION BY cookieid ORDER BY createtime DESC) AS first1

行列互换

--统计数据
select year as ""
       , sum(case season when 1 then sale else 0 end) as "一季度"
       , sum(case season when 2 then sale else 0 end) as "二季度"
       , sum(case season when 3 then sale else 0 end) as "三季度"
       , sum(case season when 4 then sale else 0 end) as "四季度"
  from tb_sales t
 group by t.year;
 
年    一季度    二季度    三季度    四季度
2018    21        22        23    24
2017    11        12        13    14
hive百分位函数

percentile_approx(col, p);其中percentile要求输入的字段必须是int类型的,而percentile_approx则是数值类似型的都可以

其实percentile_approx还有一个参数B:percentile_approx(col, p,B),参数B控制内存消耗的近似精度,B越大,结果的准确度越高。默认为10,000。当col字段中的distinct值的个数小于B时,结果为准确的百分位数。 $$ percentile_approx(col,array(0.05,0.5,0.95),9999) $$

分组数据

GROUP BY语句

语句用于结合聚集函数,根据一个或多个列对结果集进行分组

  • group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列必须出现在 group by 后面

  • group by 与having搭配使用,可通过AND,OR,NOT将多个条件组合在一起;但在group by前可以用where

  • WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。

  • ==where 后不能跟聚合函数,因为where执行顺序大于聚合函数==。

  • 可以在不使用group by的语句后面使用having,也可在from 表名之后使用,就像 select * from emp having empno>1,这样写是没有错的,前提是having后的字段出现在select字段中

  • having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚合函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组

sql执行顺序

(1) from (3) join (2) on (4) where (5) group by (开始使用select中的别名,后面的语句中都可以使用) (6) avg, sum.... (7) having (8) select (9) distinct (10) order by

子查询

作为过滤手段

结合IN操作符。(代替表连接)

查询id最大的一件商品:

SELECT goods_id,goods_name,shop_price FROM goods WHERE goods_id = (SELECT MAX(goods_id) FROM goods);

查询每个类别下id最大的商品:

SELECT goods_id,goods_name,cat_id,shop_price FROM goods WHERE goods_id IN (SELECT MAX(goods_id) FROM goods GROUP BY cat_id);
作为计算字段

即在SELECT之后FROM之前

表连接

根据两个或多个表中的列之间的关系,从这些表中查询数据

主键(Primary Key)是一个列,在表中,每个主键的值都是唯一的。这样做的目的是在不重复每个表中的所有数据的情况下,把表间的数据交叉捆绑在一起

注意查询多个列和多个表,要用逗号隔开

inner join

在表中存在至少一个匹配时,INNER JOIN 关键字返回行。 从数学的角度讲就是求两个表的交集.与where同

SELECT * FROM XXX1 INNER JOIN XXX2 ON XXX1.Id=XXX2.id; # 注意是ON而不是where

INNER JOIN 与 JOIN 是相同的。

注意:对于inner join,满足on后面的条件表的数据才能查出,可以起到过滤作用。也可以把条件放到where后面。

left join

==LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。==

SELECT * FROM XXX1 left JOIN XXX2 ON XXX1.Id=XXX2.id;

注意如果左表中某个属性对应右表多个取值,则记录显示有多行.

注意:对于left join,不管on后面跟什么条件,左表的数据全部查出来,因此要想过滤需把条件放到where后面

right join

RIGHT JOIN 关键字会右表 (table_name2) 那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行.

SELECT * FROM XXX1 right JOIN XXX2 ON XXX1.Id=XXX2.id;
full join(外连接)

只要其中某个表存在匹配,FULL JOIN 关键字就会返回行。等价于select 左连接 union select 右连接

SELECT * FROM XXX1 full JOIN XXX2 ON XXX1.Id=XXX2.id;
自联结

通常用于替代自查询,查询速度更快

组合查询

union/union all

  • UNION 操作符用于==合并两个或多个 SELECT 语句的结果集==。
  • 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同,但列名则不一定需要相同。
  • SELECT column_name(s) FROM table_name1 union SELECT column_name(s) FROM table_name2
  • 默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL
  • UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名

插入INSERT

INSERT INTO 表名称 VALUES (值1, 值2,....)

INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值2,....)

INSERT INTO table_name (列1, 列2,...) SELECT1, 列2,... FROM table_name1  # 插入检索出的数据

更新UPDATE

UPDATE table_name SET 列名称 = 新值 WHERE 列名称 = 某值
 
# Update 语句用于修改表中的数据。set后可同时修改多列

UPDATE Person SET Address = 'Zhongshan 23', City = 'Nanjing' WHERE LastName = 'Wilson'

UPDATE table_name SET 列名称 = NULL WHERE 列名称 = 某值    # 删除某列值

删除DELETE

DELETE 语句用于删除表中的行。

DELETE FROM 表名称 WHERE 列名称 =

可以在不删除表的情况下删除所有的行,这意味着表的结构、属性和索引都是完整的

DELETE (*) FROM table_name

删除所有行。

数据定义语言(DDL)

创建CREATE

CREATE DATABASE database_name;name不用引号

CREATE TABLE 表名称    
(    
 列名称1 数据类型 约束,
 列名称2 数据类型 约束,
 列名称3 数据类型 约束,
 ....    
)

更新ALTER

添加约束

当表已被创建时,如需在 "Id_P" 列创建 UNIQUE 约束:

ALTER TABLE Persons ADD UNIQUE (Id_P);
ALTER TABLE Persons ADD CONSTRAINT uc_PersonID UNIQUE (Id_P,LastName)
ALTER TABLE Persons DROP CONSTRAINT uc_PersonID

当表已被创建时,如需在 "Id_P" 列创建 PRIMARY KEY约束:

ALTER TABLE Persons ADD PRIMARY KEY(Id_P); 
ALTER TABLE Persons ADD CONSTRAINT pk_PersonID PRIMARY KEY (Id_P,LastName)
ALTER TABLE Persons DROP CONSTRAINT pk_PersonID

如果在 "Orders" 表已存在的情况下为 "Id_P" 列创建 FOREIGN KEY 约束,

ALTER TABLE Orders ADD FOREIGN KEY (Id_P) REFERENCES Persons(Id_P)
ALTER TABLE Orders add CONSTRAINT fk_PerOrders FOREIGN KEY (Id_P,...) REFERENCES Persons(Id_P,...)
ALTER TABLE Orders DROP CONSTRAINT fk_PerOrders

如果在表已存在的情况下为 "Id_P" 列创建 CHECK 约束

ALTER TABLE Persons ADD CHECK (Id_P>0);
ALTER TABLE Persons ADD CONSTRAINT chk_Person CHECK (Id_P>0 AND City='Sandnes')
ALTER TABLE Persons DROP CONSTRAINT chk_Person

在表已存在的情况下为 "City" 列创建 DEFAULT 约束,

ALTER TABLE Persons ALTER COLUMN City SET DEFAULT 'SANDNES'
ALTER TABLE Persons ALTER COLUMN City DROP DEFAULT

在已有的表中添加、修改或删除列

添加字段的语法:

alter table table_name add (字段名 number(2) not null);

删除字段的语法:

alter table table_name drop column 字段名;

修改字段的名:

alter table 表名 rename column 原子段 to 新字段;

修改字段的语法:

ALTER TABLE  表名  MODIFY (列名 数据类型); 

删除表DROP

使用 DROP 语句,可以轻松地删除索引、表和数据库删除索引:DROP INDEX index_name;

删除表 (表的结构、属性以及索引也会被删除):DROP TABLE 表名称;

删除数据库:DROP DATABASE 数据库名称;

删除表内数据而不删除表本身:TRUNCATE TABLE 表名称

注意delete from后面可以写条件,truncate不可以。