为了以后查阅方便,对常用的sql语句进行一下总结。主要内容包括,增删改查(CURD),重点在查询(子查询,模糊查询,分组查询等)。
在开始之前,要注意:sql是不区分大小写的,但是为了代码容易阅读与调试,一般将Sql关键字大写,对所有的表名和列明使用小写。多条sql语句需要用 分号(;)分隔,单条可以不加,但为了不出现错误,一般都加上,使用mysql命令行必须加分号来结束。另外sql语句可以写在一行,但为了方便阅读与调试,一般会将sql语句分成多行来写。mysql作为是传统的关系型数据库,以表来组织数据。关于关系型数据库和非关系型数据库,可查看文章关系型数据库和非关系型数据库。
一些简单的查看语句:
# Windows 启动数据库
net start mysql;
# 查看数据库版本
mysql --version;
# 查看当前数据库支持的引擎和默认的数据库引擎
# 5.5.8之后 innodb为默认存储引擎
SHOW ENGINES;
# 创建数据库
CREATE DATABASE database_name;
# 查看数据库SHOW DATABASES;
# 查看表SHOW TABLES;
# 查看表状态SHOW CREATE TABLE table_name;
创建和操纵表
创建和修改表的操作,比如创建一个customers表。
# 创建表CREATE TABLE customers
(
cust_id INT NOT NULL AUTO_INCREMENT,
cust_name CHAR(50) NOT NULL,
cust_email CHAR(255) NULL,
PRIMARY KEY (cust_id), # 主建
INDEX name_key (cust_name)
# 建索引索引名和列名如果不指定索引名,默认列名
) ENGINE=InnoDB CHAR SET=utf8;
#存储引擎和编码
# 删除表DROP TABLE customers;
# 添加列 默认可为空null
ALTER TABLE customers
ADD cust_phone CHAR(20);
# 删除列ALTER TABLE customers
DROP COLUMN cust_phone;
# 重命名表RENAME
TABLE customers TO customers2;
创建索引的两种方式:
# 添加索引
# 普通索引ALTER TABLE table_name
ADD INDEX index_name (column_list);
# UNIQUE和PRIMARY KEY索引:规定索引不能包含重复值
ALTER TABLE table_name
ADD UNIQUE (column_list);
CREATE INDEX index_name
ON table_name (column_list);
CREATE UNIQUE INDEX index_name
ON table_name (column_list);
上边的都语句都很简单,我们也不一般不会自己写sql语句来创建指定表,最好利用MySql可视化管理工具如Navicat等,来创建表。注意在创建表时,存储引擎(默认InnoDB)的指定,如果没有事务要求可指定为MyISAM。编码指定为utf8。也可指定主键的: AUTO_INCREMENT=1000。表示从1000开始自增。
以及主键和索引的创建。在此过程:要注意字段是否为空的指定,如果指定某一字段不能为null时,则在插入数据时候,则必须为其指定值。另外,字段名创建的时候,不用单引号,而是反单引号或者不用。
插入数据
数据插入,是利用INSERT插入行到数据库表中,可有几种方式:插入完整的行,插入行的一部分,插入多行以及插入某些查询的结果。
INSERT INTO customers
VALUES ( ‘1‘, ‘Tom‘,NULL,NULL);
注意:这里必须为表中的每个列都提供一个值,没有值并且可以为null的也必须制定null。且值需要用单引号’ ’ 表示。这种方式不安全,应避免使用,因为当表结构变化时,这种方式将出错。
INSERT INTO customers(cust_id,
cust_name,
cust_email,
cust_phone)VALUES
( ‘1‘, ‘Tom‘, NULL,NULL);
上边这种方式更安全,它是前面的列与后边的值一一对应。所以,不一定要按照各个列在实际表中出现的顺序,而且后边为null的列,可以去掉,也就是:
INSERT INTO customers(cust_id,
cust_name)VALUES ( ‘1‘,‘Tom‘);
与上边的效果是一样的。但如果,列不允许为null,则必须给定一个非null值。
# 插入多行INSERT INTO
customers(cust_id, cust_name)VALUES (‘1‘, ‘Tom‘), ( ‘2‘,‘Kim‘);
cust_name)VALUES (‘1‘,‘Tom‘),
( ‘2‘,‘Kim‘);
插入多行与插入查询数据都比较简单,这里就不再详细解释了,只要确保,列名与后边的值一一对应即可。
更新和删除数据
更新操作
更新表中数据操作,用UPDATE 语句,可分为:更新表中特定行,更新表中所有行。要注意WHERE 子句的应用,防止一不小心就更新了表中所有数据。
UPDATE customers
SET cust_email = ‘[email protected]‘
WHERE cust_id = 1;
更新操作。分别是:要更新的表名,列名和要更新的值,确定要更新行的过滤条件。
如果要更新多个行,可以写成:
UPDATE customers
SET cust_email = ‘[email protected]‘,
cust_phone = ‘1231‘
WHERE cust_id = 1;
注意:如果用UPDATE 语句更新多行时,如果有一行出现错误,则整个UPDATE操作都被取消。如果,你想出现错误也要继续更新,可使用 IGNORE 关键字。即:UPDATE IGNORE。
删除操作
在一个表中删除数据,使用DELETE 语句,删除特定行,删除多有行。要注意WHERE 过滤条件的使用,安全性。
DELETE FROM customers
WHERE cust_name = 1;
注意: 前面的例子中,都用了WHERE子句。如果没有WHERE子句,则更新和删除操作将应用到所有的行。这要加倍小心。
检索数据
本篇文章的重点是检索查询数据,在实际开发中用的也是最多的。这里,将详细解释其应用。
简单检索:LIMIT、ORDER BY
# 检索多个列
SELECT cust_id, cust_name, cust_email
FROM customers;# 检索所有的列
SELECT cust_id, cust_name, cust_email, cust_phone
FROM customers;
SELECT *FROM customers;
注意:如果不是需要表中的每个列,不要使用SELECT * 通配符操作,会降低检索性能。
若某行的值由重复,则检索出不同的行的sql语句:
# 检索不同的行
SELECT DISTINCT cust_name
FROM customers;
限制结果,返回特定的行和行数:
# 检索限制结果
# LIMIT 第一个数为开始的行数,第二个数为要检索的行数
# 从第0行(代表第一行)开始
SELECT cust_name
FROM customers
LIMIT 5;
# 从第5行(实际表中的第六行)开始,显示5行
SELECT cust_name
FROM customers
LIMIT 5, 5;
注意:上边检索出来的数据是无需的,也并不与实际表中的顺序一一对应,我们可认为检索出来的数据的顺序是无意义的。
为了更好的说明应用,假设有一个products,有id,价格,名称字段。
# 默认ASC 升序
SELECT prod_name
FROM products
ORDER BY prod_price;
# DESC 降序
SELECT prod_name
FROM products
ORDER BY prod_price DESC;
# 按多个列排序 先按价格,再按名称
SELECT prod_name
FROM products
ORDER BY prod_price, prod_name;
# 按多个列排序 DESC只对它前面的列有作用,
即先按价格降序,再按名称升序
SELECT prod_name
FROM products
ORDER BY prod_price
DESC , prod_name;
# DESC 降序,然后再取第0行(0,1 0行开始取1行)
SELECT prod_name
FROM products
ORDER BY prod_price
DESCLIMIT 1;
注意:ORDER BY 子句,要保证它位于FROM子句之后,在WHERE之后,如果使用LIMIT,它必须位于ORDER BY之后。
数据过滤 条件/逻辑运算符
最简单的数据过滤就是使用WHERE 子句。WHERE 子句的条件操作符有:= 等于,<> != 不等于,< 小于,<= 小于等于, >大于,> 大于等于,BETWEEN AND,介于指定的两个值之间,IS NULL 空值检查。
# WHERE 子句
SELECT prod_name, prod_price
FROM products
WHERE prod_price BETWEEN 5
AND 10;
WHERE 的逻辑运算符有AND ,OR, NOT,IN。其具体用法为;
# 检索出由1003供应商生成且价格<=10的商品信息
SELECT prod_id, prod_price, prod_name
FROM products
WHERE vend_id = 1003
AND prod_price <= 10;
# 检索出由1003或1002供应商生成的商品
SELECT prod_id, prod_price, prod_name
FROM products
WHERE vend_id = 1003 OR vend_id = 1002;
注意:AND 的操作符优先级要高于OR,在AND 和 OR 同时出现时,会优先处理AND的逻辑,所以为了避免歧义,要尽量使用括号( )。
IN和NOT IN 的用法。
# 检索出由1003或1002供应商生成的商品并排序
SELECT prod_id, prod_price, prod_name
FROM products
WHERE vend_id IN (1002, 1003)
ORDER BY prod_name;
# 检索出除了1003或1002供应商生成的商品并排序
SELECT prod_id, prod_price, prod_name
FROM products
WHERE vend_id
NOT IN (1002, 1003)
ORDER BY prod_name;
利用通配符进行数据过滤
LIKE + 通配符来进行过滤。必须使用LIKE 操作符,否则就是直接相等匹配了。
# 通配符 % 表示匹配0个或任意个字符但不可以匹配null
# 匹配以jet为开头的任意字符
SELECT prod_id, prod_name
FROM products
WHERE prod_name
LIKE ‘jet%‘;
# 匹配包含jet的任意字符
SELECT prod_id, prod_name
FROM products
WHERE prod_name
LIKE ‘%jet%‘;
# 匹配以s开头e结尾的字符
SELECT prod_id, prod_name
FROM products
WHERE prod_name
LIKE ‘s%e‘;
# 通配符 _ 表示匹配单个字符
SELECT prod_id, prod_name
FROM products
WHERE prod_name
LIKE ‘_jet‘;
通配符来匹配时一般效率较低。
使用正则表达式进行匹配:
SELECT prod_id, prod_nam;
FROM products
WHERE prod_name REGEXP ‘.000‘;
具体的规则可以查看正则表达式表。
汇合数据
使用聚集函数来对数据进行汇总。MySQL提供了5种的聚集函数:
AVG( ) 返回某列的平均值
COUNT( ) 返回某列的行数
MAX( ) 返回某列的最大值
MIN( ) 返回某列的最小值
SUM( ) 返回某列值之和
# AVG()SELECT AVG(prod_price)
AS avg_price
FROM products;
# COUNT() 返回行数
# COUNT(*) 对所有的行计数
不管各列中有什么值 不忽略null
SELECT COUNT(*)
FROM products;
# COUNT(列名) 忽略null
SELECT COUNT(cust_email)
FROM customers;
AS起别名。其他的几个函数用法类似,不再举例。
数据分组
对数据进行分组的理解是:假设一个供应商A,它生产了很多产品,我们可以按照供应商来进行分组,并且使用聚集函数来统计分组信息。
# 按vend_id分组,并统计每组的行数
SELECT vend_id, count(*) FROM products
GROUP BY vend_id;
FROM products
GROUP BY vend_id;
过滤分组,利用HAVING
# 过滤分组,返回行数大于等于2的分组 并按行数排序
SELECT vend_id, count(*) AS odertotal FROM products GROUP BY vend_id HAVING count(*)
FROM products
GROUP BY vend_id
HAVING count(*) >= 2ORDER BY odertotal;
使用子查询
关系型数据库的核心就是表,假设有两个表,存储不同的信息,利用子查询。子查询就是把一条SELECT 语句返回的结果用于另一条SELECT的WHERE子句。
子查询一般是与IN操作符结合使用的。
# 子查询.从oderitems表中查询prod_id的订单号,
然后返回此订单号的客户号
SELECT cust_id
FROM orders
WHERE order_num
IN (SELECT order_num
FROM oderitems
WHERE prod_id = ‘TTT‘);
另外,子查询可填充计算列。
联结表
关系表的设计就是要保证把信息分解成多个表,一类数据一个表。主键:唯一标识,外键:外键为某个表中的某一列(是另一表的主键)。
# 联结
SELECT vend_name, prod_name, prod_price
FROM vendors, products
WHERE vendors.vend_id = products.prod_id
#用INNER JOIN 明确表示联结
SELECT vend_name, prod_name, prod_price
FROM vendors
INNER JOIN products
ON vendors.vend_id = products.prod_id
其实,这个联结可以用子查询来实现。
组合查询
利用UNION 操作符,将多条SELECT 语句组合成一个结果集。这里不详细解释了。
常见的Sql面试题
查询每门功课都大于80的同学的名字
思路是:利用NOT IN 排除所有小于80的同学。然后利用DISTINCT 关键字筛选出相应的不重复的名字。
SELECT DISTINCT name
FROM student
WHERE name
NOT IN(SELCT name
FROM student
WHERE score < 80);
删除除id不同其他别的列都相同的冗余数据
思路还是利用NOT IN,先找出唯一的数据,再根据id删除。、
DELETE FROM student
WHERE id NOT IN
(SELECT MIN(id)
FROM student
GROUP BY name,class,score);
在mysql中,这样写会报错:You can’t specify target table ‘student’ for update in FROM clause,就是说:MySQL不能指定更新的目标表在FROM子句。其他数据库不会出现此问题。
解决方法。先把要删除的目标放到一张临时表再把要删除的条件指定到这张临时表即可:
# 将中间结果放到临时表a中
DELETE FROM student WHERE id NOT IN
(SELECT * FROM
(SELECT MIN(id)
FROM student
GROUP BY name,class,score)AS a);
WHERE id NOT IN
(SELECT * FROM (SELECT MIN(id)
FROM student
GROUP BY name,class,score)
AS a);