基本命令

查看数据库:show databases;

选择数据库:use mysql_crash;

连接数据库:需要:主机名,端口,合法用户名,用户口令

mysql -u ben -p -h localhost -P 3306

查看选定数据库中的表:show tables;

查看给定表中的列:show columns from customers;

也可以用简单一点的方式:describe customers;

或者更简单:desc customers;

查看服务器的状态信息:show status; (会展示出300来条信息)

查看建库语句:show create database mysql_crash;  (后面要加上库名)

查看建表语句:show create table customers\G; (加上\G是为了输出更好看)

显示授予用户的安全权限:show grants;

显示服务器错误或者警告:show errors;   show warnings;   (最近产生的错误或者警告)

取消命令的执行:在正在编辑的行尾加上\c然后回车就行

关于show的命令

mysql> help show
Name: 'SHOW'
Description:
SHOW has many forms that provide information about databases, tables,
columns, or status information about the server. This section describes
those following:

然后就会有很多关于SHOW的命令,根据需要选择合适的。

检索语句(也就是select)

为了使用SQL检索数据库信息,需要提供至少两个条件:选择哪些信息以及从哪些地方选。

select prod_name from products;

SQL语句:多条语句以";"分隔,不区分大消息,忽略空格。

检索多个列:SELECT prod_id, prod_name, prod_price FROM products;

一般来说SQL查询语句返回的是原始的、无格式的数据。

检索所有列:SELECT * FROM products;  (*是通配符,这里表示返回所有列)

去除重复的列:SELECT DISTINCT vend_id FROM products;

DISTINCT关键字必须直接放在列名的前面:SELECT DISTINCT vend_id, prod_id FROM products;

DISTINCT关键字应用与所有列而不仅是前置它的列。

限制结果数量(LIMIT关键字)

SELECT prod_name FROM products LIMIT 5; (选择前5行)

SELECT prod_name FROM products LIMIT 5, 5;  (跳过前面的5行,然后选择后5行)

带一个值的LIMIT总是从第一行开始,给出的数为返回的行数。带两个值的LIMIT可以指定从行号为第一个值的位置开始。

如果行数不够时,只会返回数据库有的那么多。

另外一种limit的用法:SELECT prod_name FROM products LIMIT 4 OFFSET 3;

使用完全限定的表名:SELECT products.prod_name FROM products;

排序检索数据

利用ORDER BY子句,根据需要排序检索出的数据:SELECT prod_name FROM products ORDER BY prod_name;

按多个列排序:SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC, prod_name ASC;

在按多个列排序时,排序完全按所规定的顺序进行。

排序方向默认的是ASC,如果想要降序排序需要明确指明为DESC。

在多个列上进行降序排列时,必须对每个列指定DESC关键字。

使用ORDER BY和LIMIT的组合,能够找出一个列中最高或最低的值:

SELECT prod_price FROM products ORDER BY prod_price DESC LIMIT 1;

ORDER BY子句的位置:在给出ORDER BY子句时,应该保证它位于FROM子句之后。

如果使用LIMIT,则它必须位于ORDER BY之后,使用子句的次序不对将产生错误消息。

过滤数据

只检索所需数据需要指定搜索条件(search criteria),搜索条件也称为过滤条件(filter condition)。

SELECT语句中,数据根据WHERE子句中指定的搜索条件进行过滤。WHERE子句在表名(FROM子句)之后给出。

SELECT prod_name, prod_price FROM products WHERE prod_price = 2.50;

数据既可以在应用层进行过滤也可以通过在数据库中进行过滤,但是在数据库进行过滤是已经优化了的,而且客户机上过滤,服务器不得不通过网络发送多余的数据,浪费带宽。

WHERE子句的位置:在同时使用ORDER BY和WHERE子句时,应该让ORDER BY位于WHERE之后,否则将产生错误。

WHERE子句操作符

=   等于

<> 不等于

!= 不等于

< 小于

> 大于

<= 小于等于

>= 大于等于

BETWEEN 在指定的两个值之间

SELECT prod_name FROM products WHERE prod_name = 'SAFE';

MySQL在对字符串进行这种比较的时候居然不区分大小写!

在MySQL中,使用BETWEEN时,必须指定两个值:低端值和高端值。这个两个值必须使用AND关键字分隔。BETWEEN匹配范围中所有的值,包括指定的开始值和结束值。

空值检查:SELECT prod_name FROM products WHERE prod_price IS NULL;

判断为空IS NULL;判断非空IS NOT NULL

数据过滤

组合WHERE子句

MySQL允许给出多个WHERE子句,这些子句中可以有AND子句或OR子句。

为了对不止一个列进行过滤可以使用AND操作符。

SELECT prod_id, prod_name, prod_price FROM products WHERE vend_id = 1003 AND
prod_price <= 10;

SELECT prod_name, prod_price FROM products WHERE vend_id=1003 OR vend_id=1005;

MySQL关于OR和AND的计算次序,AND比OR优先级要高,然后是从右到左的顺序筛选。

SELECT prod_name, prod_price, vend_id
FROM products
WHERE vend_id=1002 OR vend_id=1003 AND prod_price>=10;

从结果可以看出来执行顺序是先对(vend_id=1003 AND prod_price>=10)进行一次筛选,

然后是对(vend_id=1002)进行一次筛选,最后对二者求并集。

结论:为了确保计算次序以及组合,最好是为有争议的地方加上()。

IN操作符

SELECT prod_name, prod_price, vend_id
FROM products
WHERE vend_id IN ( 1002, 1003 );

为什么要使用IN操作符:

在使用长的合法选项清单时,IN操作符的语法更加清楚直观;

使用IN的时候计算次序更容易管理;

IN操作符一般比OR操作符清单执行得快;

IN的最大优点是可以包含其他SELECT语句,使得能够动态建立WHERE子句。

NOT操作符

SELECT prod_name, prod_price, vend_id
FROM products
WHERE vend_id NOT IN (1002, 1003)
ORDER BY prod_name;

NOT是否定跟在它之后的条件。

为什么使用NOT:

在更复杂的子句中,NOT是非常有用的。比如,在与IN操作符联合使用时,NOT使找出与条件列表不匹配的行非常简单。

MySQL中允许NOT对IN、BETWEEN和EXISTS子句取反。

使用通配符进行过滤

LIKE操作符

百分号(%)通配符

%表示任何字符出现任意次数。

SELECT prod_name
FROM products
WHERE prod_name LIKE 'jet%';

根据MySQL配置的方式,搜索可以是区分大小写的。

通配符可以在搜索模式中任意位置使用,并且可以使用多个通配符。

SELECT prod_id, prod_name
FROM products
WHERE prod_name LIKE '%anvil%';

通配符也可以出现在搜索模式的中间。

SELECT prod_name
FROM products
WHERE prod_name LIKE 's%e';

除了能够匹配一个字符外,%还能匹配0个字符。%代表搜索模式中给定位置的0个,1个或者多个字符。

匹配的时候要注意收尾的空格,此时可以用相关的函数去掉空格。

%不能匹配NULL。如果一个字段为NULL,那么LIKE '%'也不能匹配到NULL。

下划线(_)通配符

下划线的用途与%一样,但下划线只匹配单个字符而不是多个字符。

SELECT prod_id, prod_name
FROM products
WHERE prod_name LIKE '_ ton anvil';

不要过度使用通配符。如果其他操作符可以达到相同的目的,应该使用其他的操作符。

尽量不要把通配符用在搜索模式的开始处,在开始出搜索最慢。

拼接字段

拼接是将值连接到一起构成单个值。

MySQL的SELECT语句中使用Concat()函数来拼接两个列。而其他的DBMS则使用+或者||来实现拼接。

SELECT Concat(vend_name, ' (', vend_country, ')')
FROM vendors
ORDER BY vend_name;

Concat()串可以把多个串连接起来形成一个较长的串。Concat()需要一个或者多个指定的串,各个串之间用逗号分隔。

Concat的大小写可以忽略。

RTrim():去掉有右边的所有空格。

Trim():去掉两边的空格。

LTrim():去掉左边的空格。

使用别名

新计算的列实际上没有名字,它只是一个值。为了引用这个值,我们可以为它加别名。

SELECT Concat(RTrim(vend_name), ' (', RTrim(vend_country), ')') AS vend_title
FROM vendors
ORDER BY vend_name;

别名的其他用途:如果表列名包含不符合规定的字符(比如空格)时可以对其重新命名,或者在引起误解的时候扩充它。

执行算术计算

SELECT prod_id,
       quantity,
       item_price,
       quantity*item_price AS expanded_price
FROM orderitems
WHERE order_num=20005;

MySQL的算术操作符

+ 加

- 减

* 乘

/ 除

Now()返回当前日期和时间。

SELECT Now();

使用数据处理函数

函数的可移植性没有SQL强。

处理文本串的文本函数(删除或填充,转换值为大写或小写)

用于数值数据上进行算术操作(如返回绝对值,进行代数运算)

用于处理日期和时间值并从这些值中提取特定成分(例如,返回两个日期只差,检查日期有效性等)的日期和时间函数

返回DBMS正在使用的特殊信息(如返回用户登录信息,检查版本细节)的系统函数

文本处理函数

汇总数据

聚集函数

确定表中的行数

获取表中行组的和

找出列表

五个常用的MySQL聚集函数

AVG():返回选定列的平均值,AVG()函数忽略列值为NULL的行。

COUNT():返回选定列的行数,COUNT(*)对表中的行的数目进行计数,不管表列中是空值(NULL)还是非空值;COUNT(column)对特定列中具有值的行进行计数,忽略NULL值。

MAX():返回选定列的最大值,MAX()函数忽略值为NULL的行。

MIN():返回选定列的最小值,MIN()函数忽略列值为NULL的行。

SUM():返回选定列之和,SUM()函数忽略值为NULL的行。

分组数据

主要是学习GROUP BY和HAVING子句。

分组数据允许把数据分为多个逻辑组,以便能对每个组进行聚集计算。

SELECT vend_id, COUNT(*) AS num_prods
FROM products
GROUP BY vend_id;

使用GROUP BY之前要注意的地方

GROUP BY子句可以包含任意数目的列

如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总。

GROUP BY子句中列出的每个列必须是检索列或有效的表达式(但不能是聚集函数)。如果在SELECT中使用表达式,则必须在GROUP子句中指定相同的表达式,不能使用别名。

除了聚集计算语句之外,SELECT语句中的每个列必须在GROUP BY子句中给出。

如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组。

GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。

过滤分组

除了可以使用GROUP BY分组数据外,MySQL还允许过滤分组。

WHERE过滤的是行而不是分组,事实上WHERE没有分组的概念。

HAVING非常类似于WHERE。目前所有的WHERE子句都可以用HAVING代替,唯一的差别是WHERE过滤行,而HAVING过滤分组。

感觉在HAVING里面可以使用别名啊。

WHERE和HAVING的另一种理解:WHERE在数据分组前进行过滤,而HAVING则是在数据分组后进行过滤。

SELECT vend_id, COUNT(*) AS num_prods
FROM products
WHERE prod_price >= 10
GROUP BY vend_id
HAVING COUNT(*) >= 2;

一般在使用GROUP BY的时候,也应该给出ORDER BY子句,这时保证数据正确排序的唯一方法,千万不要仅仅依赖GROUP BY排序数据。

SELECT order_num, SUM(quantity * item_price) AS total
FROM orderitems
GROUP BY order_num
HAVING total >= 50;

SELECT子句的顺序

SELECT 要返回的列或表达式

FROM 从中检索数据的表

WHERE 行级过滤

GROUP BY 分组说明

HAVING 组级过滤

ORDER BY 输出排序顺序

LIMIT 要检索的行数

使用子查询

子查询:嵌套在其他查询中的查询。

利用子查询进行过滤

在SQL语句中,子查询总是从内向外处理。

SELECT cust_name, cust_contact
FROM customers
WHERE cust_id IN (SELECT cust_id
                  FROM orders WHERE order_num IN (SELECT order_num
                                                  FROM orderitems
                                                  WHERE prod_id = 'TNT2'));

WHERE子句中使用子查询能够编写出功能很强并且很灵活的SQL语句。SQL语句对能嵌套的子查询的数目没有限制,不过在实际使用时由于性能限制,不能嵌套太多的子查询。

子查询列匹配:在WHERE子句中使用子查询,应该保证SELECT语句具有与WHERE子句中相同数目的列。通常子查询将返回单个列并且与单个列匹配。

子查询一般和IN操作符结合使用,但也可用=和<>。

SELECT cust_name,
       cust_state,
       (SELECT COUNT(*)
        FROM orders
        WHERE orders.cust_id = customers.cust_id) AS orders
FROM customers
ORDER BY cust_name;

这......子查询还可以出现在检索列的位置上,而且这里使用了完全限定的列名

相关子查询:涉及到外部查询的子查询。

联结表

SQL最强大的功能之一就是能在数据库检索查询的执行中联结(join)表。

表中唯一标识一行的就是主键(primary key)。

外键(foreign key):外键为表中的某一个列,它包含了另一个表的主键值,定义了两个表之间的关系。

联结是一种机制,用来在一条SELECT语句中关联表。

SELECT vend_name, prod_name, prod_price FROM vendors, products
WHERE vendors.vend_id = products.vend_id
ORDER BY vend_name, prod_name;

完全限定类名:在引用的列可能出现二义性时,必须使用完全限定列名。

在联结两个表时,实际上做的是将第一个表中的每一行与第二个表中的每一行配对。

如果没有WHERE子句的条件的话就有prod(n,m)条记录。没有WHERE子句的话,第一个表中的每个行将会与第二个表中的每个行配对,而不管它们逻辑上是否可以配对。

笛卡尔积:由于没有联结条件的表关系返回的结果为笛卡尔积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。

应该保证所有联结都有WHERE子句,否则MySQL将返回比预期多得多的数据。

等值联结也称为内部联结,是基于两个表之间的相等测试,是最经常使用的一种联结形式。另外一种写法是:

SELECT vend_name, prod_name, prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;

使用这种语法时,联结条件用特定的ON子句而不是WHERE子句给出。

联结多个表

SQL对一条SELECT语句可以联结的表的数目没有限制。联结多个表时,先列出所有表,然后定义表之间的关系。

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 = 20005;

性能考虑:MySQL在运行是关联指定的每个表以处理联结,这种处理非常消耗资源,不要联结不必要的表;联结越多性能下降越厉害。

创建高级联结

使用表别名:

缩短SQL语句;

允许在单条SELECT语句中多次使用相同的表。

使用不同的联结

自联结

SELECT prod_id, prod_name
FROM products
WHERE vend_id IN (SELECT vend_id
                  FROM products
                  WHERE prod_id = 'DTNTR');

SELECT a.prod_name, a.prod_id
FROM products a, products b
WHERE a.vend_id = b.vend_id
AND b.prod_id = 'DTNTR';

使用自联结而不是用子查询。

自然联结

标准的联结(内部联结)返回所有的数据,甚至相同的列出现多次。自然联结排除多次出现,使每个列只返回一次。

外部联结

有时候需要包含那些没有关联行的行,这种联结叫做外连接。

SELECT customers.cust_id, orders.order_num
FROM customers INNER JOIN orders
ON customers.cust_id = orders.cust_id;

SELECT customers.cust_id, orders.order_num
FROM customers LEFT OUTER JOIN orders
ON customers. cust_id = orders.cust_id;

SELECT customers.cust_id, orders.order_num
FROM customers RIGHT OUTER JOIN orders
ON orders.cust_id = customers.cust_id;

比较下面的两个查询:

SELECT cust_name, cust_id, a.total
FROM customers LEFT OUTER JOIN (SELECT cust_id cid, count(*) total
                                FROM orders GROUP BY cid) a
ON customers.cust_id = a.cid;

SELECT customers.cust_name,
       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;

使用联结和联结条件

注意所使用的联结类型,一般使用内部联结,但外部联结也有用;

保证使用正确的联结条件,否则得不到正确的数据;

应该总是提供联结条件,避免的出笛卡尔积;

在一个联结中可以包含多个表,每个联结可以采用不同的类型,但是应该分别测试每个联结。

组合查询

MySQL允许执行多个查询(多条SQL语句),并将结果作为单个查询的结果返回。

有两种基本情况使用组合查询:

在单个查询中从不同的表返回类似结构的数据;

对单个表执行多个查询,按单个查询返回数据。

SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
UNION
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001, 1002);

对于更复杂的过滤条件,或者从多个表中检索数据,使用UNION可能处理更简单。

UNION从查询结果中自动取出了重复的行,如果想返回所有匹配的行,可以使用UNION ALL而不是UNION。

在用UNION组合查询时,只能使用一条ORDER BY子句,而且必须出现在最后一条SELECT语句之后。

插入数据

插入方式:

插入完整的行:如果没有给出数据,应该用NULL填充;列出现的次序应该与定义的相同;

插入行的一部分:

插入多行:VALUES (), (), ();这样可以提高数据库处理性能。

插入某些查询结果:INSERT SELECT ...... FROM ......;不一定要列名匹配,INSERT关心的是次序。

可以使用安全机制禁止使用insert语句。

INSERT LOW_PRIORITY INTO......

更新和删除数据

更新数据

更新表中特定行、更新表中所有行。如果使用UPDATE时忽略了WHERE子句,那么所有的行都会更新。

在更新之前可以先使用SELECT语句查看一下待更新的行。

SELECT cust_email FROM customers WHERE cust_id = 10005;

mysql> UPDATE FROM customers SET cust_email = 'elmer@fudd.com' WHERE cust_id = 10005;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near 'FROM customers SET cust_email = 'elmer@fudd.c
om' WHERE cust_id = 10005' at line 1

里UPDATE不能加FROM

更新一行上的多个值,只需要使用单个SET命令,每个“列=值”之间使用逗号分隔,最后一个不用逗号。

使用UPDATE IGNORE customers可以忽略掉更新有误的行,而对已经更新的行则保留更改,而且继续更新。

为了删除某个列的值,可以将其置空。

删除数据:DELETE FROM tableXXX WHERE ......

TRUNCATE TABLE语句删除整个表,然后重建整个表。

创建表

CREATE TABLE customers (
    cust_id int NOT NULL AUTO_INCREMENT,
    cust_name char(50) NOT NULL,
    cust_address char(50) NULL,
    cust_city char(50) NULL,
    cust_state char(5) NULL,
    cust_zip char(50) NULL,
    cust_country char(50) NULL,
    cust_contact char(50) NULL,
    cust_email char(255) NULL,
    PRIMARY KEY (cust_id)
) ENGINE=InnoDB;

如果仅仅想在一个表不存在时创建它,应该在表名后给出IF NOT EXISTS。

NOT NULL 不允许为空

NULL 可以为空

PRIMARY KEY(order_num, order_item)

AUTO_INCREMENT

SELECT last_insert_id() 返回最后一个AUTO_INCREMENT值。

指定默认值:DEFAULT 1

需要知道的几个引擎:

InnoDB:一个可靠的事务处理引擎,不支持全文搜索

MEMORY:功能等同于MyISAM,但由于数据存储在内存,速度很快,特别适合于临时表

MyISAM:性能极高的引擎,支持全文搜索,但不支持事务

外键不能跨引擎。

更新表

ALTER TABLE更新表结构

增加列:ALTER TABLE vendors ADD vend_phone CHAR(20);

删除列:ALTER TABLE vendors DROP COLUMN vend_phone;

增加外键:

ALTER TABLE orderitems

ADD CONTRAINT fk_orderitems_orders

FOREIGN KEY (order_num) REFERENCES orders (order_num);

ALTER TABLE orders

ADD CONSTRAINT fk_orders_customers FOREIGN KEY (cust_id)

REFERENCES customers (cust_id);

ALTER TABLE products

ADD CONSTRAINT fk_products_vendors

FOREIGN KEY (vend_id) REFERENCES vendors (vend_id);

复杂表的修改一般需要手动创建删除过程,涉及一下步骤:

使用新的列布局创建一个新表

使用INSERT SELECT语句从旧表恢复到新表,如有必要可以使用转换函数和计算字段

检验包含所需数据的新表

重命名旧表(如果确定可以删除它)

用旧表原来的名字命名新表

根据需要重新创建触发器、存储过程、索引和外键

小心使用ALTER TABLE,在改动之前有一个完整的备份,数据库表的更改不能撤销。

删除表:DROP TABLE customer2;

重命名表:RENAME TABLE customer2 TO customer;

对多个表进行重命名:RENAME TABLE backup_customers TO customers,

    backup_vendors TO vendors,

    backup_products TO products;

视图

为什么使用视图:

重用SQL语句

简化复杂的SQL操作

使用表的组成部分而不是整张表

保护数据,通过授予表的特定部分而不是整个表的访问权限

更改数据格式和表示,视图可以返回与底层表的表示和格式不同的数据

视图的规则和限制

与表一样,视图必须唯一命名;

对于可以创建的视图数目没有限制

为了创建视图要有足够的权限

视图可以嵌套

ORDER BY可以用在视图中

视图不能索引

视图可以和表一起用,比如联结查询

使用视图

视图使用CREATE VIEW viewname AS SELECT ...... 语句来创建

使用SHOW CREATE VIEW viewname; 查看创建视图语句

使用DROP删除视图,DROP VIEW viewname;

更新视图时,可以先DROP在CREATE,也可以CREATE OR REPLACE VIEW

其他知识

存储过程、触发器、游标、事务管理、安全管理

数据库维护:

备份数据

最新文章

  1. mathlab之floor,ceil,round,int以及fix函数
  2. MVC中路由
  3. android 给空白包签名
  4. uva 10755 - Garbage Heap
  5. 前端构建工具grunt
  6. windows MySQL 5+ 服务手动安装
  7. Ambiguous mapping found. Cannot map &#39;xxxxController&#39; bean method
  8. 在objc项目中使用常量的最佳实践
  9. Windows下Redis的安装
  10. LPC1788的LCD接口驱动真彩屏
  11. 泛型(CSDN转载)
  12. 关联规则—频繁项集Apriori算法
  13. Mongoose &#39;static&#39; methods vs. &#39;instance&#39; methods
  14. idea环境下js、css中文乱码
  15. 【设计模式】—— 状态模式State
  16. Caffe Blob针对图像数据在内存中的组织方式
  17. WIN 10环境下JDK的安装和环境配置
  18. 推荐9款使用CSS3实现的超酷动画效果
  19. distributed lock manager (DLM)(分布式管理锁)
  20. Maven - error in opening zip file

热门文章

  1. IO流--File--properties
  2. MFC出现 error RC2108: expected numerical dialog constant错误解决办法
  3. 规约模式Specification Pattern
  4. LNMP第二部分nginx、php配置
  5. iOS:Xcode7下创建 .a静态库 和 .framework静态库
  6. openstack 动态加载usb,需要修改kvm虚拟机的xml文件
  7. 通过http协议发送json格式请求并解析
  8. 淘宝分布式配置管理服务Diamond
  9. org.hibernate.exception.ConstraintViolationException: could not delete:
  10. 设置客户端连接PostgreSQL不需要密码