导图社区 SQL标准入门
历时十天 相关书记《SQL基础教程第二版》MICK 适用人群:零基础初学者,学习过用此图作为笔记复习。 涵盖范围:以通用的SQL为主,部分地方对不同DBMS做了额外的笔记,还带着一点用于介绍的理论基础。 分量足:纯手打,虽精简但字数也应该过万了。 如果您喜欢请关注我,和期待我的操作系统笔记。
编辑于2019-10-28 19:41:55SQL语法
事务
概述
概述:再一个处理单元中执行的一串更新处理的集合。可以包含INSERT、DELETE、UPDATE三种语句(也就是DML语句,WHERE语句也可以包含有其中)。事务并没有具体的开始起点。单句语句可以看作是另一种事务。 个人认为:与单句相比仅多一个可以取消(回滚)/确认的功能罢了。
语法
SQL_Server/PostgreSQL BEGIN TRANSACTION; DML语句1; DML语句2; DML语句3; COMMIT; MySQL START TRANSACTION; DML语句1; DML语句2; DML语句3; COMMIT; Oracle/DB2 //并没有事务 //COMMIT是确认提交的意思没若是DML语句输入错误则可以用ROLLBACK关键词来替换COMMIT,ROLLBACK是取消事务(回滚)的意思。
关于DBMS四大特性(ACID特性)
事务关于DBMS四大特性(ACID特性) 1.原子性:事务要么全部执行要么全部取消,即当作一条语句来看待。 2.一致性:事务的DML语句的写入也受列约束的限制,超出限制将会被禁止写入。 3.隔离性;多事务之间不会相互影响,并且相互不可感知。 4.持久性:事务无论是提交还是回滚,DBMS都将保证数据状态的保存持久性,即使是系统故障也能回复过来。
概述
SQL(Structured_Query_Language)是数据库查询和程序设计语言。可以用于高效的查询、修改、删除数据库中的数据。虽然ISO制定了关于SQL语言的标准,但不同的RDBMS使用的SQL语言大同小异,使用不同的RDBMS时要注意。
视图
视图 是对某一个表使用SELECT查询后的结果保存的一个临时表。 1.作为视图储存,而不用像表一样占用空间。 2.视图有自己的名字,内容是对<某一个表>查询的结果,当需要使用这一结果时,直接调用<视图>的名字即可,不再需要再次使用复杂的语句查询<某一个表> 3.可以以视图为基础,在此之上再创建一个视图,不过不推荐这样做因为会降低SQL的效率。 4.对原表(<某一个表>)的更新,视图也会自动跟着更新。 视图的限制 定义视图时不能使用(可以使用时也尽量别用)ORDER语句。 不能对以下视图更新: 1.含统计函数的视图(如DISTINCT等)。 2.含有GROUP BY/HAVING、DISTINCT、UNION的视图。 3.各个表结合的视图(FROM选择多个)。 4.定义有子查询的视图。 对视图的更新也会反应到原表的。
创建
创建视图 CREATE VIEW <视图名称> (<视图列名1>,<视图列名2>...) AS <SELECT语句> //SELECT语句需要写在AS之后,SELECT语句的查询结果中列的排列顺序会对应<视图的排名>的顺序。
删除
删除视图列 DROP VIEW <视图名称> (<视图列名1>,<视图列名2>...) 删除整个视图 DROP VIEW <视图名称>;
子查询
子查询 子查询实际就是直接将创建视图的语句直接嵌套在FROM语句中。是一次性的视图。 在可以放<表>作为参数的地方就可以使用子查询。 子查询甚至可以嵌套,并且没有规定层数的上限。 SQL_Server/DB2/PostgreSQL/MySQL SELECT <视图列名1> FROM(SELECT <源表列名1> AS <视图列名1> //将<源表列名1>复制到<视图列名1> FROM <源表名1>) AS <视图名1>; Oracle SELECT <视图列名1> FROM(SELECT <源表列名1> AS <视图列名1> //将<源表列名1>复制到<视图列名1> FROM <源表名1>)<视图名1>; //这个例子并没有太大意义,只是介绍语法。与普通视图视图不同的是由AS左边复制到AS右边。普通视图则是反过来的。
标量查询
标量查询 是一次只返回一列一行(一个单元格)的子查询。 标量查询的意义是用返回值配合"="或"<>"进行运算。 原则上在语句可以放单一值的位置都可以使用标量查询。
关联查询
关联子查询 子查询(括号内)与外查询(括号外)在WHERE语句上有所联系。关联子查询一次只返回一个数值,可能返回多次。 需要注意的是含有内外关联的WHERE语句(括号外也可以有其他的WHERE语句不要混淆)必须要在子查询内(括号内),因为关联名称是有作用域的,并且范围在子查询内(括号内)。 关联子查询实例 SELECT type,name,price //查找type,name,price这三列。 FROM produce AS P1 //选择produce表,并起别名为P1。 WHERE price > (SELECT AVG(price) //查找条件为price列的值大于子查询返回的值(查找price的平均值。 FROM produce AS p2 //选择produce表,并起别名为P2。 WHERE P1.type = p2.type); //查找条件为type列的相等的值 //外查询意思是查找price列的值大于子查询返回值的值。 //内查询意思是返回(查找)与外查询type列的值相同的price列(关于type)的平均值。 //若是Oracle则要将AS去掉直接写P1和P2。
谓词
是在条件比较时使用的关键字或符号,如"="、"<"、">"、"<>"等。由于是条件比较(配合WHERE)所以返回的是真值或是假值,这是和函数最大的区别。
部分一致
LIKE部分一致: WHERE <列名1> LIKE '<匹配字符串>%';//(这里只记录WHERE一行省略了SELECT和FROM下同),将筛选出<列名1>中<匹配字符串>在开头后续字符任意的数据。 WHERE <列名1> LIKE '%<匹配字符串>';将筛选出<列名1>中<匹配字符串>在结尾前面字符任意的数据。 WHERE <列名1> LIKE '%<匹配字符串>%';将筛选出<列名1>中含有<匹配字符串>的所有数据,无论<匹配字符串>在开头还是结尾或是在其中。 可以用"_"来代替"%",不同的是"%"是任意内容长度不限,而"_"是一个字符串,所以可以使用多个"_"来筛选。
范围查找
BETWEEN范围查找:用于数值数据和日期数据。 WHERE <列名1> BETWEEN <范围下限> AND <范围上限>;//(这里只记录WHERE一行省略了SELECT和FROM下同),将筛选出<列名1>中<范围下限>到<范围上限>之间的数据。包含<范围下限>和<范围上限>。 WHERE <列名1> > <范围下限> AND <列名1> < <范围上限>;//这里没有使用BETWEEN,但不同的是筛选出的数据不包含<范围下限>和<范围上限>。
非NULL/是NULL
IS NULL是NULL/IS NOT NULL非NULL: WHERE <列名1> IS NULL; //(这里只记录WHERE一行省略了SELECT和FROM下同),将筛选出<列名1>中数据是NULL的行。 WHERE <列名1> IS NOT NULL; //将筛选出<列名1>中数据不是NULL的行。
是/不是
IN是/NOT IN不是: WHERE <列名1> IN (<数据1>,<数据2>,<数据3>); //(这里只记录WHERE一行省略了SELECT和FROM下同),将筛选出<列名1>中数据是<数据1>或<数据2>或<数据3>的行。 WHERE <列名1> NOT IN (<数据1>,<数据2>,<数据3>); //将筛选出<列名1>中数据不是<数据1>或<数据2>或<数据3>的行。 IN/NOT IN可以把子查询的结果(视图)作为参数。 WHERE <列名1> IN (<子查询语句>); //只要子查询返回的数据是一列数据即可,执行完子查询后剩下则按WHERE <列名1> IN (<子查询结果1>,<子查询结果2>,<子查询结果3>...);来处理。
存在于/不存在于
EXISTS存在于/NOT EXISTS不存在:与IN/NOT IN很类似,很多地方IN/NOT IN都可以代替EXISTS/NOT EXISTS而且IN/NOT IN更容易理解。 IN/NOT IN的逻辑为在<列名>中的这些数据(IN/NOT IN参数)被选出。而EXISTS/NOT EXISTS则是存在与这些数据(EXISTS/NOT EXISTS参数)中将被选出。 EXISTS/NOT EXISTS也是可以在以把子查询的结果(视图)作为参数。 WHERE EXISTS (<子查询语句>); //不需要像IN/NOT IN需要加<列名>,若使用<子查询语句>不成功则需要尝试下关联子查询。
集合运算
不同的表中列与列之间的运算查询
UNION并集
UNION并集:对两列的数据合成一列(并集)显示出来 SELECT <列名1> FROM <表名1> UNION SELECT <列名2> FROM <表名2> //两个SELECT后面跟的<列>应该一样多不然会报错。并且数据类型应该一样(虽然现在的DBMS中支持隐式更换类型方便运算)。 //可以使用ORDER BY来排序,但只能使用一次并且放在最后。 //UNION会去掉重复的数据,多个重复的数据只会显示一次。使用UNION ALL代替UNION则可以显示全部的数据,包括重复的数据。
INTERSECT交集
INTERSECT交集:对两列的数据合成一列(交集)显示出来 //MySQL不支持INTERSECT SELECT <列名1> FROM <表名1> INTERSECT SELECT <列名2> FROM <表名2> //两个SELECT后面跟的<列>应该一样多不然会报错。并且数据类型应该一样(虽然现在的DBMS中支持隐式更换类型方便运算)。 //可以使用ORDER BY来排序,但只能使用一次并且放在最后。 //UNION会去掉重复的数据,多个重复的数据只会显示一次。使用INTERSECT ALL代替INTERSECT则可以显示全部的数据,包括重复的数据。
EXCEPT减法
EXCEPT减法: DB2/PostgreSQL/MySQL SELECT <列名1> FROM <表名1> EXCEPT SELECT <列名2> FROM <表名2> Oracle SELECT <列名1> FROM <表名1> MINUS SELECT <列名2> FROM <表名2> //结果为<列名1>去掉和<列名2>中相同的数据后的结果,注意<列名1>和<列名2>的位置对结果的影响。 //两个SELECT后面跟的<列>应该一样多不然会报错。并且数据类型应该一样(虽然现在的DBMS中支持隐式更换类型方便运算)。 //可以使用ORDER BY来排序,但只能使用一次并且放在最后。 //UNION会去掉重复的数据,多个重复的数据只会显示一次。
创建
创建时候库名、表名、列名只能用字母、数字、下划线(少数RDBMS允许其他符号,但是兼容性差),名称要以字母开头。同一库中不能有名称相同的表,同一表中不能有名称相同的列。
创建库
CREATE DATABASE <数据库名称>;
创建表
CREATE TABLE <表名> (<列名1> <数据类型> <列1约束>, <列名2> <数据类型> <列2约束>, <列名3> <数据类型> <列3约束>, ... );
列名创建别名
SELECT <原列名1> AS <别名1>, <原列名2> AS <别名2>, ... FROM <表1>; //可以用中文作为别名但是要用""框起来。
删除
删除表
DROP TABLE <表名1> //删除后难以恢复,请君三思
删除列
删除列 MySQL / DB2 / PostgreSQL/SQL Server: ALTER TABLE <表名1> DROP COLUMN <列名1> Oracle ALTER TABLE <表名1> DROP <列名1> //删除多列时可以用(<列名1>,<列名2>...)
删除行
删除行 DELETE FROM <表名1> WHERE <列名1>=<数据1> AND <列名2>=<数据2>; //删除<表名1>中符合<列名1>=<数据1>和<列名2>=<数据2>条件的行。注意<数据>要用''框起来。 删除所有行 DELETE FROM <表名1>; 或 DELETE * FROM <表名1>;
插入/添加
插入列
添加列 DB2/PostgreSQL/MySQL ALTER TABLE <表名1> ADD COLUMN <列名> <数据类型> <约束> Oracle/SQL Server ALTER TABLE <表名1> ADD <列名> <数据类型> <约束> //Oracle中还可以用( <列名1> <数据类型1> <约束1>,<列名2> <数据类型2> <约束2>...)的形式 //具体实例 DB2/PostgreSQL/MySQL/PostgreSQL ALTER TABLE biao1 ADD COLUMN lie1 VARCHAR(100) NOT NULL Oracle/SQL Server ALTER TABLE biao1 ADD lie1 VARCHAR(100) NOT NULL
插入行
添加一行 INSERT INTO <表名1>(<列名1>,<列名2>,...)VALUES('<数据1>','<数据2>',..) //输入数据注意要用''框起来。若是要插入整行的数据,则可以省略(<列名1>,<列名2>,...)的部分则数据按左至右顺序填入。 INSERT INTO <表名1>(<列名1>,<列名2>,...)VALUES ('<数据1>','<数据2>',..), ('<数据3>','<数据4>',..), ('<数据5>','<数据6>',..); 或 INSERT INTO <表名1>(<列名1>,<列名2>,...)VALUES('<数据1>','<数据2>',..); INSERT INTO <表名1>(<列名1>,<列名2>,...)VALUES('<数据3>','<数据4>',..); ... //这里的(<列名1>,<列名2>,...)同样可以省略,但也是要求一次插入整行的数据。 显式/隐式的插入数据 显式 INSERT INTO <表名1>(<列名1>,<列名2>,<列名3>...)VALUES('<数据1>',DEFAULT,'<数据3>'..); //前提是<列名2>设置DEFAULT默认值约束,插入数据直接使用了DEFAULT关键字,则插入的数据为约束设置的默认值。 隐式 INSERT INTO <表名1>(<列名1>,<列名3>...)VALUES('<数据1>','<数据3>'..); //这里直接省略了<列名2>和'<数据2>',则<列名2>的数据为默认值。
更新/更改
改表名
Oracle/PostgreSQL ALTER TABLE <原表名> RENAME TO <新表名>; DB2 RENAME TABLE <原表名> TO <新表名>; SQL_Server sp_rename '<原表名>' , '<新表名>'; MySQL RENAME TABLE <原表名> TO <新表名>;
更新列
17.更新(修改)列中的数据 UPDATE <表名1> SET <列名1>=<表达式>; //如 SET <列名1>=100;把<列名1>中全部的数据改为100。 //如 SET <列名1>=<列名1>*10;把<列名1>中全部的数据改为原来的10倍。 配合WHERE更新行 UPDATE <表名1> SET <列名1>=<表达式> WHERE <条件筛选>; 可以一次更新多列数据 UPDATE <表名1> SET <列名1>=<表达式1>, <列名2>=<表达式2>, ... WHERE <条件筛选>; 或 UPDATE <表名1> SET (<列名1>,<列名2>,...)=(<表达式1>,<表达式2>...) WHERE <条件筛选>; //第二种一般在PostgreSQL和DB2中才可以使用,其他DBMS不一定支持。
联结
表和表通过添加列的形式合成一个表
内联结
内联结 DB2/PostgreSQL/MySQL/SQL Server SELECT <别名1>.<列名1>,<别名2>.<列名2>,... FROM <表名1> AS <别名1> INNER JOIN <表名2> AS <别名2> ON <别名1>.<列名1>=<别名2>.<列名2>; Oracle SELECT <别名1>.<列名1>,<别名2>.<列名2>,... FROM <表名1> <别名1> INNER JOIN <表名2> <别名2> ON <别名1>.<列名1>=<别名2>.<列名2>; //在SELECT后面使用<别名1>.<列名1>命名的形式是防止混淆,实际情况下会有很多列。若不使用<别名>也没有问题只是易读性不高。 //NO后面是两个表联结的关键,称为联结键。将<列名1>和<列名2>合成一列(实际两列应该是同一列),与此列关于"<别名1>.<列名1>,<别名2>.<列名2>,..."的数据就是结果。 //在NO之后可配合WHERE进一步对结果进行筛选。 三个以上表的联结 DB2/PostgreSQL/MySQL/SQL Server SELECT <别名1>.<列名1>,<别名2>.<列名2>,... FROM <表名1> AS <别名1> INNER JOIN <表名2> AS <别名2> ON <别名1>.<列名1>=<别名2>.<列名2> INNER JOIN <表名3> AS <别名3> //<表名1>和<表名2>联结后再与<表名3>联结 Oracle SELECT <别名1>.<列名1>,<别名2>.<列名2>,... FROM <表名1> <别名1> INNER JOIN <表名2> <别名2> ON <别名1>.<列名1>=<别名2>.<列名2> INNER JOIN <表名3> AS <别名3> //<表名1>和<表名2>联结后再与<表名3>联结
外联结
外联结 DB2/PostgreSQL/MySQL/SQL Server SELECT <别名1>.<列名1>,<别名2>.<列名2>,... FROM <表名1> AS <别名1> RIGHT OUTER JOIN <表名2> AS <别名2> ON <别名1>.<列名1>=<别名2>.<列名2>; Oracle SELECT <别名1>.<列名1>,<别名2>.<列名2>,... FROM <表名1> <别名1> RIGHT OUTER JOIN <表名2> <别名2> ON <别名1>.<列名1>=<别名2>.<列名2>; //在SELECT后面使用<别名1>.<列名1>命名的形式是防止混淆,实际情况下会有很多列。若不使用<别名>也没有问题只是易读性不高。 //可以用"LEFT"关键字来代替"RIGHT"关键字,用"LEFT"关键字时左侧是主表,用"RIGHT"关键字时右侧是主表,除了这个会影响结果之外,"LEFT"和"RIGHT"没有其他的不同。 //NO后面是两个表联结的关键,称为联结键。将<列名1>和<列名2>合成一列(实际两列应该是同一列),与此列关于"<别名1>.<列名1>,<别名2>.<列名2>,..."的数据就是结果。会显示主表关于联结键和"<别名1>.<列名1>,<别名2>.<列名2>,..."的所有数据即使副表没有对应的数据,这是外联结和内联结的区别。 //在NO之后可配合WHERE进一步对结果进行筛选。 三个以上表的联结 DB2/PostgreSQL/MySQL/SQL Server SELECT <别名1>.<列名1>,<别名2>.<列名2>,... FROM <表名1> AS <别名1> RIGHT OUTER JOIN <表名2> AS <别名2> ON <别名1>.<列名1>=<别名2>.<列名2> RIGHT OUTER JOIN <表名3> AS <别名3> //<表名1>和<表名2>联结后再与<表名3>联结,主副表在此行重新定义。 Oracle SELECT <别名1>.<列名1>,<别名2>.<列名2>,... FROM <表名1> <别名1> RIGHT OUTER JOIN <表名2> <别名2> ON <别名1>.<列名1>=<别名2>.<列名2> RIGHT OUTER JOIN <表名3> AS <别名3> //<表名1>和<表名2>联结后再与<表名3>联结,主副表在此行重新定义。
交叉联结
交叉联结 由于无法使用IN指定联结键,所以结果往往是<表名1>的行数*<表名2>行数,实际运用中会非常庞大且不实用,浪费机器性能。 DB2/PostgreSQL/MySQL/SQL Server SELECT <别名1>.<列名1>,<别名2>.<列名2>,... FROM <表名1> AS <别名1> CROSS JOIN <表名2> AS <别名2> Oracle SELECT <别名1>.<列名1>,<别名2>.<列名2>,... FROM <表名1> <别名1> CROSS JOIN <表名2> <别名2>
数据类型
数据类型实际有很多,不同的RDBMS数据类型也有所差异,这里只介绍一些常用基本类型。
INTEGER数字整数型
指定列的数据类型为数字,不能存储小数。
CHAR定长字符型
可以在CHAR后加"(数字)"来决定此列字符数据的长度,若超出最大长度则无法输入,若小于最大长度则会自动用空格字符填补。不同的RDBMS的CHAR长度单位不一样,可以是字符个数或是字节数。
VARCHAR可变字符型
与CHAR类似,不同的是VARCHAR的数据输入小于最大长度时并不会用空格字符填补。(在Oracle中应使用VARCHAR2型,原VARCHAR型不推荐)
DATE日期型
用于存储日期。(在Oracle中还用到时分秒)
NUMERIC小数数值型
大部分的DBMS都支持的一种类型,NUMERIC(<位数总数>,<小数位数>)
SQL的格式
1.关键字尽量大写(即使小写也可以)其他看习惯。 2.每句指令结尾要加";"。 3.输入的数据除了纯数字数据其他的都要用单引号' '围起来。 4.只能使用半角的空格作为分隔,使用全角的空格可能会出现错误。 5.--为一行的注释,/* <内容> */为一段的注释。 //6.在以一个;为结尾的一串SQL语句中,并不是一定是按由上至下的顺寻执行语句。
种类和基本介绍
数据定义DDL
数据定义DDL(Data_Definition_Language)用于创建/删除数据库以及数据库中的对象。包含以下: CREATE:创建数据库和表等对象。 DROP:删除数据库和表等对象。 ALTER:修改数据库和表等对象的结构。
操纵数据DML
操纵数据DML(Data_Manipulation_Language)查询过着变更表中数据。包含如下: SELECT:查询表中的数据。 INSERT:向表中插入新数据。 UPDATE:更新表中的数据。 DELETE:删除表中的数据。
数据控制DCL
数据控制DCL(Data_Control_Language)用来确认\取消对数据库的变更,给用户授权。 COMMIT:确认对数据进行的变更。 ROLLBACK:取消对数据进行的变更。 GRANT:赋予用户操作权限。 REVOKE:取消用户操作权限。
列约束
对输入的数据进行约束,若是输入不符合约束的数据,写入将会失败。 给约束命名:目的是撤销约束的时候比较方便,不需要去查找默认约束名。 有无KEY的区别: 如UNIQUE KEY和UNIQUE的区别 可以理解为"非空键"和"非空","键"可以理解为索引(未拓展)
NOT NULL非空
非空约束,规定某列如果不给该字段添加值,就无法插入新纪录或者更新记录。表列默认情况下接受 NULL 值。
创建
CREATE TABLE <表名> ( <列名1> int NOT NULL, //规定<列名1>输入的数据类型为int,并且不接受NULL值。 <列名2> varchar(255) //其他列 ... )
修改
添加约束 MySQL / SQL Server / Oracle / MS Access ALTER TABLE<表1> ADD NOT NULL (<列名1>,<列名2>...) 约束+命名 MySQL / SQL Server / Oracle / MS Access ALTER TABLE<表1> ADD CONSTRAINT <自定义约束名1> NOT NULL (<列名1>,<列名2>...)
撤销
ALTER TABLE <表1> DROP CONSTRAINT <自定义约束名1>;
UNIQUE唯一
唯一约束,保证某列的值具有唯一性。与PRIMARY KEY不同的是UNIQUE可以指定多个列,并且可以输入NULL值。
创建
MySQL: CREATE TABLE <表1> ( <列名1> int NOT NULL, UNIQUE (<列名1>) ) SQL Server / Oracle / MS Access: CREATE TABLE <表1> ( <列名1> int NOT NULL UNIQUE, .... ) 创建+命名+约束 MySQL / SQL Server / Oracle / MS Access CREATE TABLE <表1> ( <列名1> int NOT NULL, CONSTRAINT <自定义约束名1> UNIQUE (<列名1>) )
修改
添加约束 MySQL / SQL Server / Oracle / MS Access ALTER TABLE<表1> ADD UNIQUE (<列名1>,<列名2>...) 约束+命名 MySQL / SQL Server / Oracle / MS Access ALTER TABLE<表1> ADD CONSTRAINT <自定义约束名1> UNIQUE (<列名1>,<列名2>...)
撤销
MySQL: ALTER TABLE <表1> DROP INDEX <自定义约束名1> SQL Server / Oracle / MS Access: ALTER TABLE <表1> DROP CONSTRAINT <自定义约束名1>
CHECK条件
条件检查约束,指定一个值的布尔搜索条件,拒绝不符合的值,可以给列/列组设置多个条件。
创建
MySQL: CREATE TABLE <表1> ( <列名1> int NOT NULL, CHECK (<<列名1>+布尔条件>) //如CHECK (<列名1> >0) ) SQL Server / Oracle / MS Access: CREATE TABLE <表1> ( <列名1> int NOT NULL CHECK (<<列名1>+布尔条件>) , .... ) 创建+命名+约束 MySQL / SQL Server / Oracle / MS Access CREATE TABLE <表1> ( <列名1> int NOT NULL, <列名2> int NOT NULL, .... CONSTRAINT <自定义约束名1> CHECK (<<列名1>+布尔条件> AND <<列名2>+布尔条件> AND...) )
修改
添加约束 ALTER TABLE <表1> ADD CHECK (<<列名1>+布尔条件>) 约束+命名 ALTER TABLE <表1> ADD CONSTRAINT <自定义约束名1> CHECK (<<列名1>+布尔条件> AND <<列名2>+布尔条件> AND...)
撤销
MySQL: ALTER TABLE <表1> DROP CHECK <自定义约束名1> SQL Server / Oracle / MS Access: ALTER TABLE <表1> DROP CONSTRAINT <自定义约束名1>
DEFAULT默认
默认值约束,规定一个默认值,当没有给列一个值时,则将默认值填入新纪录。
创建
MySQL / SQL Server / Oracle / MS Access: CREATE TABLE <表1> ( <列名1> int DEFAULT '<默认值>' )
修改
当 <表1>已创建时 MySQL: ALTER TABLE <表1> ALTER <列名1> SET DEFAULT '<默认值>' SQL Server / MS Access: ALTER TABLE <表1> ADD CONSTRAINT <自定义约束名1> DEFAULT '<默认值>' for <列名1> Oracle: ALTER TABLE <表1> MODIFY <列名1> DEFAULT '<默认值>'
撤销
MySQL: ALTER TABLE <表1> ALTER <列名1>DROP DEFAULT SQL Server / Oracle / MS Access: ALTER TABLE <表1> ALTER COLUMN <列名1> DROP DEFAULT
PRIMARY KEY主键
主键约束,指定列内字段不能重复,不能有空值,每个表都应该有一个主键,并且每个表只能有一个主键(简单的说,FOREIGN KEY = UNIQUE KEY + NOT NULL )
创建
MySQL: CREATE TABLE <表1> ( <列名1> int NOT NULL, PRIMARY KEY (<列名1>) ) SQL Server / Oracle / MS Access: CREATE TABLE <表1> ( <列名1> int NOT NULL PRIMARY KEY, .... ) 创建+命名+约束 MySQL / SQL Server / Oracle / MS Access CREATE TABLE <表1> ( <列名1> int NOT NULL, CONSTRAINT <自定义约束名1> PRIMARY KEY (<列名1>) )
修改
添加约束 MySQL / SQL Server / Oracle / MS Access ALTER TABLE<表1> ADD PRIMARY KEY (<列名1>,<列名2>...) 约束+命名 MySQL / SQL Server / Oracle / MS Access ALTER TABLE<表1> ADD CONSTRAINT <自定义约束名1> PRIMARY KEY (<列名1>,<列名2>...)
撤销
MySQL: ALTER TABLE <表1> DROP PRIMARY KEY SQL Server / Oracle / MS Access: ALTER TABLE <表1> DROP CONSTRAINT <自定义约束名1>
FOREIGN KEY外键
外键约束,对关系合理性判断
创建
MySQL: CREATE TABLE <表2> ( <列名1> int NOT NULL, <列名2> int, PRIMARY KEY (<列名1>), FOREIGN KEY (<列名2>) REFERENCES <表1>(<列名2>) ) SQL Server / Oracle / MS Access: CREATE TABLE <表2> ( <列名1> int NOT NULL PRIMARY KEY, <列名2> int FOREIGN KEY REFERENCES <表1>(<列名2>) ) 创建+命名+约束 MySQL / SQL Server / Oracle / MS Access CREATE TABLE <表2> ( <列名1> int NOT NULL, <列名2> int, PRIMARY KEY (<列名1>), CONSTRAINT <自定义约束名1> FOREIGN KEY (<列名2>) REFERENCES <表1>(<列名2>) )
修改
添加约束 MySQL / SQL Server / Oracle / MS Access: ALTER TABLE <表2> ADD FOREIGN KEY (<列名2>) REFERENCES <表1>(<列名2>) 约束+命名 MySQL / SQL Server / Oracle / MS Access: ALTER TABLE <表2> ADD CONSTRAINT <自定义约束名1> FOREIGN KEY (<列名2>) REFERENCES <表1>(<列名2>)
撤销
MySQL: ALTER TABLE <表2> DROP FOREIGN KEY <约束名> SQL Server / Oracle / MS Access: ALTER TABLE <表2> DROP CONSTRAINT <约束名>
查询
查询单表的列
查询若干列 SELECT <列名1>,<列名2>,<列名3>... FROM <表名1>; //显示结果顺序会和输入的列名顺序一样 查询所有列 SELECT * FROM <表名1>
查找单表的行
按条件查找行 SELECT '数据1' AS <列名1>,'数据2' AS <列名2>, <列名3>,<列名4> FROM <表名1>; //寻找在<列名1>中含'数据1'同时符合在<列名2>中含'数据2'的行,显示结果时连同<列名3>和<列名4>中关于这些行的数据一起显示出来。
查询列数据种类数
SELECT DISTINCT <列名1> FROM <表名>; // 查询<列名1>中出现过的数据数量,隐藏重复的数据数量,相同的数据只会被计数一次,,NULL也会被视为一种数据。 SELECT DISTINCT <列名1>,<列名2>... FROM <表名>; //也可以多列一起使用,这样多列构成的数据中两行数据完全相同时才会被隐藏。
分组查找
按分组查询分组列的种类数量 SELECT <列名1>,COUNT(*) //(/<聚合函数>) FROM <表名1> GROUP BY <列名1>; //在GROUP BY后的<列名1>叫做聚合键。 //结果会显示<列名1>种每个数据重复出现了多少次,并且包含NULL数据出现的次数。 //SELECT后面只能跟聚合键(对应的GROUP BY后的<列名1>)和聚合函数。(只有MySQL认同这种语法) //GROUP BY后面不能跟列的别名(列的自定义名)。 按筛选分组查询分组列的种类数量 SELECT <列名1>,COUNT(*) //(/<聚合函数>) FROM <表名1> WHERE <搜索条件> GROUP BY <列名1>; //会先进行筛选再分组显示。 //WHERE后面不能出现聚合函数。 按组筛选分组查询分组列的种类数量 SELECT <列名1>,COUNT(*) //(/<聚合函数>) FROM <表名1> GROUP BY <列名1> HAVING <组筛选条件>; //WHERE和HAVING的想过很相似, //SELECT后面只能跟常数聚合键(对应的GROUP BY后的<列名1>)和聚合函数。 //相同的结果下,WHERE比HAVING的执行速度更快。
GROUPING运算符
GROUPING运算符包含ROLLUP关键字、CUBE关键字、GROUPING SETS关键字。PostgreSQL并不支持GROUPING运算符,MySQL仅支持ROLLUP关键字。
ROLLUP小计/总合
ROLLUP小计/总合 在使用GROUP BY时可以配合ROLLUP使用可以计算出GROUP BY结果的总合(小计/总合)。 DB2/PostgreSQL/SQL Server SELECT <列名1>,SUM(<列名2>) AS <结果列> FROM <表名1> GROUP BY ROLLUP(<列名1>); MySQL SELECT <列名1>,SUM(<列名2>) AS <结果列> FROM <表名1> GROUP BY <列名1> WITH ROLLUP; Oracle SELECT <列名1>,SUM(<列名2>) <结果列> FROM <表名1> GROUP BY ROLLUP(<列名1>); //结果会出现GROUP BY关于<列名1>分组数据(<列名2>)的合计和ROLLUP(<列名1>)对分组后的数据合计相加(总和)的结果。 需要注意的是当 GROUP BY ROLLUP()指定多个列时,结果从理解的角度来说将会复杂一些。 DB2/PostgreSQL/MySQL/SQL Server SELECT <列名1>,<列名2>,<列名3>,SUM(<列名4>) AS <结果列> FROM <表名1> GROUP BY ROLLUP(<列名1>,<列名2>); //结果会出现GROUP BY<列名1>,<列名2>分组数据(<列名4>)的合计。 //以及ROLLUP(<列名1>)、ROLLUP(<列名1>,<列名2>)对分组后的数据合计相加(总和)的结果。 //ROLLUP的合计可以理解为层级的合计,对各分组中的的数据分别合计,在对各个分组的合计过数据再进行一次总的合计。 //指定更多列时ROLLUP结果为(忽略GROUP BY本身的一个返回结果。 两列时:1、(1、2)。 三列时:1、(1、2)、(1、2、3) 四列时:1、(1、2)、(1、2、3)、(1、2、3、4)。 ...
GROUPING区分NULL
GROUPING区分NULL 在ROLLUP的合计行(ROLLUP的结果)中,只有对数的合计结果,而在此行的其他数据则为NULL。此时若有其他行也只有合计结果同列的数据,其他数据也为NULL的话就会很容易把ROLLUP的合计行和其他行混淆。可以使用GROUPING来区分这两种行。 GROUPING对ROLLUP的合计行的列会返回1对其他的则会返回0,注意是对合计行的列,在分层的ROLLUP结果中并不是整个行的每列都会返回1的,这也可以区分ROLLUP的分层。 所以GROUPING指定的对象则为列,而不是行。 GROUPING可以巧妙的配合WHEN可以给ROLLUP合计行插入字符串,一般用于说明合计行的值(如:"食品合计总量"、"合计距离")。
CUBE关键字
CUBE关键字 语法和ROLLUP相同,关键字替换即可。 CUBE和ROLLUP不同的地方是当CUBE指定多个列时返回的结果回比ROLLUP多。 GROUP BY ROLLUP(<列名1>,<列名2>); //返回ROLLUP(<列名1>)、ROLLUP(<列名1>,<列名2>)对分组后的数据合计相加(总和)的结果。 GROUP BY CUBE(<列名1>,<列名2>); //返回CUBE(<列名1>)、CUBE(<列名1>,<列名2>)、CUBE(<列名2>)对分组后的数据合计相加(总和)的结果。 //指定更多列时ROLLUP结果为(忽略GROUP BY本身的一个返回结果。) 两列时:1、(1、2)。 三列时:1、(1、2)、(1、2、3) 四列时:1、(1、2)、(1、2、3)、(1、2、3、4)。 ... //指定更多列时CUBE结果为(忽略GROUP BY本身的一个返回结果。) 两列时:1、(1、2)、(2)。 三列时:1、(1、2)、(1、2、3)、(2、3)、2 ... 可以看到CUBE更为全面。
GROUPING SETS关键字
GROUPING SETS关键字 GROUPING SETS与CUBE不同的是GROUPING SETS会忽略GROUP BY本身的返回结果和指定列作为聚合键返回的结果 如 GROUP BY CUBE(<列名1>,<列名2>,<列名3>); 只会返回(<列名2>,<列名3>)、(<列名1>,<列名2>)的结果。忽略了(<列名1>)、(<列名2>)、GROUP BY本身的返回结果。 这个关键字使用起来会比较少。
排序查询
SELECT <列名1>,<列名2>...//SELECT包含的列名会出现在结果中 FROM <表名1> ORDER BY <列名A>...;//以<列名A>为排列依据,<列名A>也较为排序键。 //书写顺序1.SELECT 2.FROM 3.WHERE 4.GPOUP BY 5.HAVING 6.ORDER BY //默认的ORDER BY排序顺序为升序。 降序 SELECT <列名1>,<列名2>... FROM <表名1> ORDER BY <列名A> DESC;//仅添加DESC就可以变为降序。 //若排序键中包含NULL值,则包含NULL值的行会全部出现在开头或结尾。 //ORDER BY可以识别别名(列的自定义名)。 //ORDER BY可以使用SELECT包含之外的列名来作为排列键。 //当排列键中有相同的数据时,这些行的排列是随机的,可以指定多个排列键,进行次级排序。 SELECT <列名1>,<列名2>... FROM <表名1> ORDER BY <列名A>,<列名B>...; //优先级为左边最高向右递减,可以设置多个副排序键,副排序键只会在上一级排序数据相同时候才会起作用。 实际上ORDER BY可以使用编号的形式设置排序键, SELECT <列名a>,<列名b>,<列名c>.. FROM <表名1> ORDER BY 1 DESC,3;//将<列名a>设置为主排序键并为倒叙,将<列名c>设置为副排序列。 //SELECT后跟的<列名a>,<列名b>,<列名c>..对应的编号由左至右为1,2,3。 //ORDER BY可以直接使用编号代替列名。 //但是这种做法不推荐使用,不仅阅读困难而且困难,而且在新的SQL标准中逐渐去掉这一方法,此处列出来仅为涨见识而已。
条件查询
SELECT <列名1> //可以以<列名1>,<列名2>..的形式加入多个列名,其他列会的相关单元格和结果一起显示出来(注意才能形成一行)。 FROM <表名1> WHERE <搜索条件>; //例如:WHERE name='abc'; 就是显示name列中数据为abc的单元格。 //WHERE后面不能使用聚合函数。
算数运算符
常用于条件查询。 =等于、<>不等于、>=大于等于、>大于、<=小于等于、<小于。 1.NULL值的任何计算结果都是NULL。 2.大于等于小于都可以比较日期数据。小于为在这个日期之前,反之亦然。 3.多了一个<>不等于符号可以使用,但是不能使用在NULL上。 4.字符型的数字如'2'和'11',因为是字符型则判定'2'大于'11'只判断首字。 5.作为查询条件,算术符可以对列与列之间的可以计算数据进行计算 如 SELECT NAME,JINHUO,CHUSHOU FROM biao1 WHERE CHUSHOU-JINHUO >= 500; //会显示出售价-进货价>=500的列数据(CHUSHOU列和JINHUO列)连带NAME列对于的数据。 6.若是需要判断关于NULL的条件,只能使用IS NULL(~是NULL)或IS NOT NULL(~不是NULL)。
逻辑运算符
NOT:和运算符<>是同一个意思,但NOT和<>的书写位置不一样。NOT一般紧跟在查询语句WHERE的后面,在条件之前,以为此条件之外。 如WHERE NOT AGE>100;//意为非AGE列中大于100的数据,即AGE列中小于100的数据。 OR和AND:逻辑或和逻辑与,条件全真则AND返回真,带假则AND返回假。条件一个或以上为真则OR返回真,全部条件都假则OR返回假。当OR和AND配合使用时应用()把条件隔离开,不然容易出现逻辑上的错误,导致系统误读。 UNKNOWN:不确定值,当条件判断遇到NULL时除了IS或IS_NOT其他的都会变为不确定,在真假之间有一个值为不确定,AND的条件假则为假,全真带一个不确定则为不确定,全不确定则为不确定。OR的条件有真则为真,全假带不确定则为不确定,全不确定则为不确定。 条件查询条件结果为真才会显示,假和不确定则不会显示。
函数
聚合函数
并非聚合,实际上输入列为参数,输出一行计算结果。由多变一所以才叫为聚合函数。
行数
COUNT计算行数 SELECT COUNT (<列参数>) FROM <表名1>; //结果会显示<列参数>的行数,数据是NULL的一行不计数。 //若参数为*,则为这个表的所有行,带NULL的数据也可以计算在内。
最大值/最小值
MAX计算最大值 SELECT MAX (<列参数>) FROM <表名1>; //结果会显示<列参数>中数值最大的数据。 MIN计算最小值 SELECT MIN (<列参数>) FROM <表名1>; //结果会显示<列参数>中数值最小的数据。
平均值
AVG计算平均值 只能对数值数据的列使用。 SELECT AVG (<列参数>) FROM <表名1>; //结果为<列参数>所有数值数据的平均值。
总合
SUM计算和值 //只能对数值数据的列使用。 SELECT SUM (<列参数>) FROM <表名1>; //结果会显示<列参数>所有数值数据的总和值。
列中元素种类
计算列中数据种类 //在一列中去掉重复数据后的数据个数。即出现了多少个不一样的数据。 SELECT COUNT(DISTINCT <列名1>) FROM <表名1>;
算数函数
四则运算(略)
ABS绝对值
ABS绝对值: SELECT <列名1>, ABS(<列名1>) AS <列名a> FROM <表名1>; //将返回<列名1>所有数值的绝对值。
MOD求余数
MOD求余数: SELECT <列名1>,<列名2>, MOD(<列名1>,<列名2>) AS <列名a> FROM <表名1>; //将返回每行<列名1>/<列名2>的所有余数。仅SQL Server不支持此函数,SQL可以用"<列名1>%<列名2>"来代替"MOD(<列名1>,<列名2>)"。
ROUND小数舍去
ROUND小数舍去: SELECT <列名1>, ROUND(<列名1>,<保留位数>) AS <列名a> FROM <表名1>; //将返回保留<保留位数>位小数的<列名1>所有数值,<保留位数>后的小数相会被四舍五入。
字符串函数
拼接函数
||拼接函数: SELECT <列名1>,<列名2>, <列名1>||<列名2> AS <列名a> FROM <表名1>; //将返回<列名1>每行和<列名2>对应每行拼接后的字符串<列名1>在前<列名2>在后,也可以三列四列拼接。MySQL和SQL Server无法使用"||"符号。MySQL和SQL Server(2012版+)是用"CONCAT(<列名1>,<列名2>)"来代替"<列名1>||<列名2>"。
字符串长度
LENGTH字符串长度: SELECT <列名1>, LENGTH(<列名1>) AS <列名a> FROM <表名1>; //将返回<列名1>每行字符串长度的数字。SQL Server的字符串长度是LEN,即"LEN(<列名1>)"代替"LENGTH(<列名1>)"。
字符串替换
REPLACE字符串替换: SELECT <列名1>,<列名2>,<列名3>, REPLACE(<列名1><列名2>,<列名3>) AS <列名a> FROM <表名1> //;在<列名1>数据中含有<列名2>数据的替换成<列名3>的数据,若在<列名1>数据没有含有<列名2>的数据则返回<列名1>本身数据。
字符串截取
SUBSTRING字符串截取: (PostgreSQL/MySQL) SELECT <列名1>, SUBSTRING(<列名1>FROM <截取起点位数> FOR <截取位数>) AS <列名a> FROM <表名1>; (SQL Server) SELECT <列名1>, SUBSTRING(<列名1>,<截取起点位数>,<截取位数>) AS <列名a> FROM <表名1>; (Oracle/DB2) SELECT <列名1>, SUBSTR(<列名1>,<截取起点位数>,<截取位数>) AS <列名a> FROM <表名1>; //<列名1>每行的数据中从<截取起点位数>位开始截取<截取位数>位的数据。
大小写转换
UPPER/LOWER大小写转换: SELECT <列名1>, UPPER(<列名1>) AS <列名a> FROM <表名1>; //数据中本来是大写的则不会受影响,小写会被转换成大写,小写转换也同理。若是由大写向小写转换把"UPPER"换成"LOWER"就可以了。
日期函数
当前时间
CURRENT_TIMESTAMP当前时间: (SQL Server/PostgreSQL/MySQL) SELECT CURRENT_TIMESTAMP;//查看当前时间。 (Oracle) SELECT CURRENT_TIMESTAMP FROM dual;// (DB2) SELECT CURRENT TIMESTAMP FROM SYSIGM.SYSDUMMYI;
截取日期元素
EXTRACT截取日期元素: //截取的是年份,返回的是数值类型的数据。可以把"YEAR"替换成"MONIH"、"DAY"、"HOUR"、"MINUTE"、"SECOND"将分别返回月份、号、小时、分钟、秒(下同)。 (PostgreSQL/MySQL) SELECT CURRENT_TIMESTAMP, EXTRACT(YEAR FROM CURRENT_TIMESTAMP) AS <列名a>; (SQL Server) SELECT CURRENT_TIMESTAMP, EXTRACT(YEAR , CURRENT_TIMESTAMP) AS <列名a>; (Oracle) SELECT CURRENT_TIMESTAMP, EXTRACT(YEAR FROM CURRENT_TIMESTAMP) AS <列名a> FROM DUAL; (DB2) SELECT CURRENT_TIMESTAMP, EXTRACT(YEAR FROM CURRENT_TIMESTAMP) AS <列名a> FROM SYSIGM.SYSDUMMYI;
转换函数
类型转换
(SQL Server/PostgreSQL) SELECT CAST(<列名1> AS <类型名称>) AS <列名a>; (MySQL) SELECT CAST(<列名1> AS SIGNED <类型名称>) AS <列名a>; (Oracle) SELECT CAST(<列名1> AS <类型名称>) AS <列名a> FROM DUAL; (DB2) SELECT CAST(<列名1> AS <类型名称>) AS <列名a> FROM SYSIGM.SYSDUMMYI;
将NULL转换成其他值
SELECT COALESCE(<列名1>,<替换NULL的值>) FROM <表名1>; //将<列名1>数据中NULL换成<替换NULL的值>。
分支(字典)
分支函数 分支函数CASE会根据判断条件执行不同的语句。 CASE <表达式1> WHEN <值1> THEN <执行语句1> WHEN <值2> THEN <执行语句2> WHEN <值3> THEN <执行语句3> ... ELSE <表达式a> END // <表达式1> 的结果等于<值1>时执行<执行语句1>,执行后跳出整个CASE,返回<执行语句1>结果。若不等于<值1>则执行第二个WHEN语句以此类推。 //若都不等于<值>,则执行ELSE后的<表达式a>,返回<表达式a>结果。 也可以用更复杂一点的CASE语句 CASE //注意这里不再由表达式 WHEN <判断表达式1> THEN <执行语句1> WHEN <判断表达式2> THEN <执行语句2> WHEN <判断表达式3> THEN <执行语句3> ... ELSE <表达式a> END //<判断表达式1>中可以添加谓词符号等,可以对参数进行判断,若为真则执行<执行语句1>,若为假则执行第二个WHEN语句以此类推。 //若都不等于<值>,则执行ELSE后的<表达式a>,返回<表达式a>结果。
窗口函数(分析函数、OLAP函数)
在一些老版本的DBMS还不支持OLAP,直到2016年MySQL也没有支持。 <窗口函数> OVER (PARTITION BY <列名1>,<列名2>.. ORDER BY <列名a>,<列名b>...) 除了专有的窗口函数(RANK、DENSE_RANK、ROW_NUMBER...)之外,所有聚合函数(SUM、AVG、COUNT、MAX、MIN)都可以作为窗口函数。 窗口函数的位置应该在SELECT语句中,不应该在WHERE语句或GROUP BY语句中。
专用窗口函数
以RANK函数为例 RANK函数能把数据划分成一个个模块(相同的数据靠拢),并对相关联其他数据进行排序。 DB2/PostgreSQL/MySQL/SQL Sever SELECT <列名1>,<列名2>,<列名a>... RANK () OVER (PARTITION BY <列名1> ORDER BY <列名a>) AS <结果列> FROM <表名1> Oralce SELECT <列名1>,<列名2>,<列名a>... RANK () OVER (PARTITION BY <列名1> ORDER BY <列名a>) <结果列> FROM <表名1> //PARTITION BY的作用是将<列名1>中的数据按种类排列(相同的数据靠拢)。这和GROUP BY的功能类似。 //ORDER BY则将<列名a>中的数据按升序(默认,DESC为降序)排序。 //最后结果为按<列名1>为主排列,按<列名a>为升序排列的数据。 //PARTITION BY非必要,若去掉PARTITION BY和<列名1>(<列名1>是他的参数)则结果为只按<列名a>排序的数据 专有窗口函数一般不带有参数直接"RANK ()"带个空的括号即可。 RANK、DENSE_RANK、ROW_NUMBER之间的不同也仅为排序的不同。RANK允许并列的序号而不允许最大序号因为并列减少(如:1.2.2.4.5),DENSE_RANK的排序允许并列也允许因为并列而最大序号的减少(如:1.2.2.3.4),ROW_NUMBER不允许任何并列,自然也不会因为并列而最大序号减少(如:1.2.3.4.5)。 实际仍有更多专用的窗口函数,并且不同的DBMS由不同的专用窗口函数。
聚合窗口函数
聚合窗口函数 <聚合函数>(<列名1>) OVER(ORDER BY <列名2>) //好像聚合窗口函数并不会用到PARTITION BY //<列名2>作为排序依据。 和专用窗口函数不同,聚合窗口函数一般都拥有参数。 //若想对聚合窗口函数的结果进行排序则需要在外层的SELECT语句中(也就是最后一行)再添加一个ORDER BY语句,共两个。OVER中的ORDER BY是对算数进行排序,也就是先排序后计算。而外层的RDER BY才是给结果排序。 可以加入一些关键字来影响聚合窗口函数的结果。 ROWS:行 PRECEDING:向前 FOLLOWING:向后 例: AVG(<列名1>) OVER(ORDER BY <列名2> ) //没加关键词 //累加数据并除以当前行数来求每行的平均值AVG。 AVG(<列名1>) OVER(ORDER BY <列名2> ROWS 2 PRECEDING) //只累加前两行,包括本行(共三行)并除以3来求平均值AVG。 AVG(<列名1>) OVER(ORDER BY <列名2> ROWS 1 PRECEDING AND 1 FOLLOWING) //只累加前一行和后一行,包括本行(共三行)并除以3来求平均值AVG。