Mysql必知必会-笔记

order by 排序

如果不排序,
数据一般将以它在底层表中出现的顺序显示。这可以是数据最初添加
到表中的顺序。但是,如果数据后来进行过更新或删除,则此顺序将
会受到MySQL重用回收存储空间的影响。因此,如果不明确控制的话,
不能(也不应该)依赖该排序顺序。关系数据库设计理论认为,如果
不明确规定排序顺序,则不应该假定检索出的数据的顺序有意义。

SELECT prod_id, prod_price, prod_name
FROM products
ORDER BY prod_price, prod_name;

+---------+------------+----------------+
| prod_id | prod_price | prod_name |
+---------+------------+----------------+
| FC      | 2.50       | Carrots |
| TNT1    | 2.50       | TNT (1 stick) |
| FU1     | 3.42       | Fuses |
| SLING   | 4.49       | Sling |
| ANV01   | 5.99       | .5 ton anvil |
| OL1     | 8.99       | Oil can |
| ANV02   | 9.99       | 1 ton anvil |
| FB      | 10.00      | Bird seed |
| TNT2    | 10.00      | TNT (5 sticks) |
| DTNTR   | 13.00      | Detonator |
+---------+------------+----------------+

理解在按多个列排序时,排序完全按所规定的顺序进行。换
句话说,对于上述例子中的输出,仅在多个行具有相同的prod_price
值时才对产品按prod_name 进行排序。如果prod_price 列中所有的
值都是唯一的,则不会按prod_name 排序。

排序关键字
DESC: 降序排序
ASC: 默认排序,升序排序 (A--Z)

区分大小写和排序顺序 在对文本性的数据进行排序时,A与a相
同吗?a位于B之前还是位于Z之后?这些问题不是理论问题,其答案
取决于数据库如何设置。
在字典(dictionary)排序顺序中,A被视为与a相同,这是
MySQL(和大多数数据库管理系统)的默认行为。但是,许多数据库
管理员能够在需要时改变这种行为(如果你的数据库包含大量外语
字符,可能必须这样做)。
这里,关键的问题是,如果确实需要改变这种排序顺序,用简单的
ORDER BY 子句做不到。你必须请求数据库管理员的帮助。

ORDER BY 子句的位置 在给出ORDER BY 子句时,应该保证它
位于FROM 子句之后。如果使用LIMIT ,它必须位于ORDER BY
后。使用子句的次序不对将产生错误消息。

where 子句操作符

操 作 符 说 明
= 等于
<> 不等于
!= 不等于
< 小于
<= 小于等于
> 大于
>= 大于等于
BETWEEN 在指定的两个值之间
IS NULL 表示某个值为NULL

使用BETWEEN 时,必须指定两个值——所需范围的低端值和高端值。这两个值必须用AND 关键字分隔。
BETWEEN 匹配范围中所有的值,包括指定的开始值和结束值
NULL无值 (novalue) 与不匹配
在过滤数据时,因为未知NULL具有特殊的含义,数据库不知道它们是否匹配,所以在匹配过滤或不匹配过滤时不返回它们。

通配符 like % _

  • 不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
  • 在确实需要使用通配符时,除非绝对有必要,否则不要把它们用在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起来是最慢的。
  • 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据。

使用Mysql 正则表达式

SELECT prod_name FROM products WHERE prod_name REGEXP '.000' ORDER BY prod_name;
. 是正则表达式语言中一个特殊的字符。它表示匹配任意一个字符
即匹配任何已000结尾的均会被返回出来

为了匹配特殊字符,必须用\ 为前导。\- 表示查找- ,\. 表示查找.
SELECT vend_name FROM vendors WHERE vend_name REGEXP '\\.' ORDER BY vend_name;
查找已 . 开头的数据,进行返回

\ 或 \\ ?
多数正则表达式实现使用单个反斜杠转义特殊字符,以便能使用这些字符本身。但MySQL要求两个反斜杠(MySQL自己解释一个,正则表达式库解释另一个)
SELECT * FROM bms_billing WHERE BE_DELETE REGEXP '[:alnum:]'
匹配任意字母和数字 同[a-zA-Z0-9] 这是正则表达式的字符类

字符类

image

重复元字符

image

SELECT prod_name FROM products WHERE prod_name REGEXP '\\([0-9] sticks?\\)' ORDER BY prod_name;

+----------------+
| prod_name |
+----------------+
| TNT (1 stick) |
| TNT (5 sticks) |
+----------------+

正则表达式\([0-9]sticks?\) 需要解说一下。\( 匹配(,[0-9] 匹配任意数字(这个例子中为1和5),sticks? 匹配stick 和sticks(s 后的? 使s 可选,因为? 匹配它前面的任何字符的0次或1次出现),\) 匹配) 。没有? ,匹配stick 和sticks 会非常困难。

SELECT prod_name FROM products WHERE prod_name REGEXP '[[:digit:]]{4}' ORDER BY prod_name;

+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+

如前所述,[:digit:] 匹配任意数字,因而它为数字的一个集合。{4} 确切地要求它前面的字符(任意数字)出现4次,所以[[:digit:]]{4} 匹配连在一起的任意4位数字。

正则表达式定位符

元字符 说明
^ 文本的开始
$ 文本的结尾
[[: 词的开始
[[:>:]] 词的结尾
例如,如果你想找出以一个数(包括以小数点开始的数)开始的所有产品,怎么办?简单搜索[0-9\.] (或[[:digit:]\. ])不行,因为它将在文本内任意位置查找匹配。解决办法是使用^定位符,
如下所示:
SELECT prod_name FROM products WHERE prod_name REGEXP '^[0-9\\.]' ORDER BY prod_name;

+--------------+
| prod_name |
+--------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
+--------------+

^ 匹配串的开始。因此,^[0-9\\.] 只在.或任意数字为串中第一个字符时才匹配它们。没有^ ,则还要多检索出4个别的行(那些中间有数字的行)。

^ 的双重用途 ^ 有两种用法。在集合中(用[和]定义),用它来否定该集合,否则,用来指串的开始处。

使REGEXP 起类似LIKE 的作用 本章前面说过,LIKE 和REGEXP 的不同在于,LIKE 匹配整个串而REGEXP 匹配子串。利用定位符,通过用^ 开始每个表达式,用$ 结束每个表达式,可以使REGEXP 的作用与LIKE 一样。

简单的正则表达式测试 可以在不使用数据库表的情况下用SELECT 来测试正则表达式。REGEXP 检查总是返回0 (没有匹配)或1 (匹配)。可以用带文字串的REGEXP 来测试表达式,并试验它们。
相应的语法如下:
SELECT 'hello' REGEXP '[0-9]';
这个例子显然将返回0 (因为文本hello 中没有数字)。

MYSQL函数的建单应用

concat() 字段拼接函数

SELECT Concat(RTrim(vend_name), ' (', RTrim(vend_country), ')') AS end_title ROM vendors RDER BY vend_name;

常用日期和时间处理函数

函 数 说 明
AddDate() 增加一个日期(天、周等)
AddTime() 增加一个时间(时、分等)
CurDate() 返回当前日期
CurTime() 返回当前时间
Date() 返回日期时间的日期部分
DateDiff() 计算两个日期之差
Date_Add() 高度灵活的日期运算函数
Date_Format() 返回一个格式化的日期或时间串
Day() 返回一个日期的天数部分
DayOfWeek() 对于一个日期,返回对应的星期几
Hour() 返回一个时间的小时部分
Minute() 返回一个时间的分钟部分
Month() 返回一个日期的月份部分
Now() 返回当前日期和时间
Second() 返回一个时间的秒部分
Time() 返回一个日期时间的时间部分
Year() 返回一个日期的年份部分

常用的数值处理函数

函 数 说 明
Abs() 返回一个数的绝对值
Cos() 返回一个角度的余弦
Exp() 返回一个数的指数值
Mod() 返回除操作的余数
Pi() 返回圆周率
Rand() 返回一个随机数
Sin() 返回一个角度的正弦
Sqrt() 返回一个数的平方根
Tan() 返回一个角度的正切

SQL聚集函数

image

NULL值 AVG() 函数忽略列值为NULL 的行。

COUNT() 函数有两种使用方式

  • 使用COUNT(*) 对表中行的数目进行计数,不管表列中包含的是空值(NULL )还是非空值。
  • 使用COUNT(column) 对特定列中具有值的行进行计数,忽略NULL 值。

NULL 值 如果指定列名,则指定列的值为空的行被COUNT() 函数忽略,但如果COUNT() 函数中用的是星号(* ),则不忽略。
对非数值数据使用MAX() 虽然MAX() 一般用来找出最大的数值或日期值,但MySQL允许将它用来返回任意列中的最大值,包括返回文本列中的最大值。在用于文本数据时,如果数据按相应的列排序,则MAX() 返回最后一行。
NULL 值 MAX() 函数忽略列值为NULL 的行。
MIN()函数与MAX()结果相反,属性含义一致

GROUP BY语法

  • GROUP BY 子句可以包含任意数目的列。这使得能对分组进行嵌套,为数据分组提供更细致的控制。
  • 如果在GROUP BY 子句中嵌套了分组,数据将在最后规定的分组上进行汇总。换句话说,在建立分组时,指定的所有列都一起计算(所以不能从个别的列取回数据)。
  • GROUP BY 子句中列出的每个列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在SELECT 中使用表达式,则必须在GROUP BY 子句中指定相同的表达式。不能使用别名。
  • 除聚集计算语句外,SELECT 语句中的每个列都必须在GROUP BY子句中给出。(通过配置config,my.cnf sql_mode='ONLY_FULL_GROUP_BY' 可以忽略SELECT中的列必须都在GROUP BY 子句中)
  • 如果分组列中具有NULL 值,则NULL 将作为一个分组返回。如果列中有多行NULL 值,它们将分为一组。
  • GROUP BY 子句必须出现在WHERE 子句之后,ORDER BY 子句之前。

使用ROLLUP

使用WITH ROLLUP 关键字,可以得到每个分组以及每个分组汇总级别(针对每个分组)的值
SELECT COUNT(*),LEADINGSTS FROM shipment_header WHERE WAREHOUSECODE='01' GROUP BY LEADINGSTS  WITH ROLLUP
-- 会得到一行总数据的汇总信息

HAVING

目前为止所学过的所有类型的WHERE 子句都可以用HAVING 来替代。唯一的差别是WHERE 过滤行,而HAVING 过滤分组
HAVING 支持所有WHERE 操作符,它们的句法是相同的,只是关键字有差别。

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

GROUP BY 与ORDER BY

我们经常发现用GROUP BY 分组的数据确实是以分组顺序输出的。但情况并不总是这样,它并不是SQL规范所要求的。此外,用户也可能会要求以不同于分组的顺序排序。仅因为你以某种方式分组数据(获得特定的分组聚集值),并不表示你需要以相同的方式排序输出。应该提供明确的ORDER BY 子句,即使其效果等同于GROUP BY 子句也是如此。

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

SELECT order_num, SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity*item_price) >= 50 ORDER BY ordertotal;
-- 在这个例子中,GROUP BY 子句用来按订单号(order_num 列)分组数据,以便SUM(*) 函数能够返回总计订单价格。HAVING 子句过滤数据,使得只返回总计订单价格大于等于50 的订单。最后,用ORDERBY 子句排序输出。

小结

image

子查询

在SELECT 语句中,子查询总是从内向外处理
子查询放在SELECT之后,WHERE之前,作为字段显示,则最终数据结果是多少条数据,则该子查询就被执行多少次

联接查询

select * from tableA,tableB where A.ID=B.ID 使用的是INNER JOIN 内联接查询
select * from tableA inner join tableB on A.ID=B.ID

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

此语句中的SELECT 与前面的SELECT 语句相同,但FROM 子句不同。这里,两个表之间的关系是FROM 子句的组成部分,以INNER JOIN指定。在使用这种语法时,联结条件用特定的ON 子句而不是WHERE子句给出。传递给ON 的实际条件与传递给WHERE 的相同。

性能考虑 MySQL在运行时关联指定的每个表以处理联结。这种处理可能是非常耗费资源的,因此应该仔细,不要联结不必要的表。联结的表越多,性能下降越厉害。

用自联结而不用子查询 自联结通常作为外部语句用来替代从相同表中检索数据时使用的子查询语句。虽然最终的结果是相同的,但有时候处理联结远比处理子查询快得多。应该试一下两种方法,以确定哪一种的性能更好

UNION 规则

  • UNION 必须由两条或两条以上的SELECT 语句组成,语句之间用关键字UNION 分隔(因此,如果组合4条SELECT 语句,将要使用3个UNION 关键字)。
  • UNION 中的每个查询必须包含相同的列、表达式或聚集函数(不过各个列不需要以相同的次序列出)。
  • 列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含地转换的类型(例如,不同的数值类型或不同的日期类型)。

UNION 从查询结果集中自动去除了重复的行(换句话说,它的行为与单条SELECT 语句中使用多个WHERE 子句条件一样)。因为供应商1002 生产的一种物品的价格也低于5 ,所以两条SELECT 语句都返回该行。在使用UNION 时,重复的行被自动取消。
这是UNION 的默认行为,但是如果需要,可以改变它。事实上,如果想返回所有匹配行,可使用UNION ALL 而不是UNION

对组合结果进行排序

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) ORDER BY vend_id, prod_price;
SELECT 语句的输出用ORDER BY 子句排序。在用UNION 组合查询时,只能使用一条ORDER BY 子句,它必须出现在最后一条SELECT语句之后。对于结果集,不存在用一种方式排序一部分,而又用另一种方式排序另一部分的情况,因此不允许使用多条ORDER BY 子句,虽然ORDER BY 子句似乎只是最后一条SELECT 语句的组成部分,但实际上MySQL将用它来排序所有SELECT 语句返回的所有结果。

启用全文本搜索支持 FULLTEXT

CREATE TABLE productnotes
(
 note_id int NOT NULL AUTO_INCREMENT,
 prod_id char(10) NOT NULL,
 note_date datetime NOT NULL,
 note_text text NULL ,
 PRIMARY KEY(note_id),
 FULLTEXT(note_text)
) ENGINE=MyISAM;

这条CREATE TABLE 语句的列中有一个名为note_text 的列,为了进行全文本搜索,MySQL根据子句FULLTEXT(note_text) 的指示对它进行索引。这里的FULLTEXT索引单个列,如果需要也可以指定多个列。
在定义之后,MySQL自动维护该索引。在增加、更新或删除行时,索引随之自动更新。
可以在创建表时指定FULLTEXT ,或者在稍后指定(在这种情况下所有已有数据必须立即索引)。

不要在导入数据时使用FULLTEXT 更新索引要花时间,虽然不是很多,但毕竟要花时间。如果正在导入数据到一个新表,此时不应该启用FULLTEXT 索引。应该首先导入所有数据,然后再修改表,定义FULLTEXT 。这样有助于更快地导入数据(而且使索引数据的总时间小于在导入每行时分别进行索引所需的总时间)。

进行全文本搜索的语句
使用两个函数Match() 和Against() 执行全文本搜索,其中Match() 指定被搜索的列,Against() 指定要使用的搜索表达式。
SELECT note_text FROM productnotes WHERE Match(note_text) Against('rabbit');
由于WHERE 子句,一个全文本搜索被执行。Match(note_text) 指示MySQL针对指定的列进行搜索,Against('rabbit') 指定词rabbit 作为搜索文本。
使用完整的Match() 说明 传递给Match() 的值必须与FULLTEXT() 定义中的相同。如果指定多个列,则必须列出它们(而且次序正确)。
搜索不区分大小写 除非使用BINARY 方式(本章中没有介绍),否则全文本搜索不区分大小写。
全文搜索是走索引的,搜索效率比like快
全文搜索-查询扩展
如果你想找到所有包含rabbit的行,但还想找出可能与你的搜索有关的所有其他行,即使他们不含有rabbit

SELECT note_text FROM productnotes WHERE Match(note_text) Against('rabbit' WITH QUERY EXPANSION);

INSERT

表名,字段,值

-- EX ① 单条INSERT
INSERT INTO customers(cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
VALUES('Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA');
-- EX ② 多条INSERT 用分号隔开,分号,表示当前SQL代码的结束
INSERT INTO customers(cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
VALUES('Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA');
INSERT INTO customers(cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
VALUES('M. Martian', '42 Galaxy Way', 'New York', 'NY', '11213', 'USA');
-- EX ③ 一个INSERT 多个值
INSERT INTO customers(cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
VALUES( 'Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA', '90046', 'USA' ), ( 'M. Martian', '42 Galaxy Way', 'New York', 'NY', '11213', 'USA' );

EX ③ 比EX ② 效率要高
INSERT INTO SELECT
通过查询语句,给出INSERT 的值
insert into table1 (cloum1,cloum2,cloum3) select cloum1,cloum2,cloum3 from table2 where 1=1
table1 和table2 的字段名可以不一样,但是位置要是匹配的,它使用的是列的位置,因此SELECT 中的第一列(不管其列名)将用来填充表列中指定的第一个列,第二列将用来填充表列中指定的第二个列,如此等等。
UPDATE 语句
UPDATE customers SET cust_name = 'The Fudds', cust_email = 'elmer@fudd.com' WHERE cust_id = 10005;
使用UPDATE语句时,一定要确保where条件是对的
可以先使用select查询语句,得到的结果,确保是需要被更新的数据后,可以将select语句,转换为update语句
UPDATE语句中也可以使用子查询
IGNORE 关键字
如果用UPDATE 语句更新多行,并且在更新这些行中的一行或多行时出一个现错误,则整个UPDATE 操作被取消(错误发生前更新的所有行被恢复到它们原来的值)。为即使是发生错误,也继续进行更新
UPDATE IGNORE customers SET cust_name = 'The Fudds', cust_email = 'elmer@fudd.com' WHERE cust_id = 10005;
DELETE 语句
使用DELETE语句时,一定要确保where条件是对的
如果要删除整个表的所有行,可以使用TRUNCATE TABLE table1 语句,(TRUNCATE 实际是删除原来的表并重新创建一个表,而不是逐行删除表中的数据)表的行记录id会被重置,重新开始计数
使用UPDATE 或DELETE 时所遵循的习惯

  • 除非确实打算更新和删除每一行,否则绝对不要使用不带WHERE子句的UPDATE 或DELETE 语句。
  • 保证每个表都有主键(如果忘记这个内容,请参阅第15章),尽可能像WHERE 子句那样使用它(可以指定各主键、多个值或值的范围)。
  • 在对UPDATE 或DELETE 语句使用WHERE 子句前,应该先用SELECT 进行测试,保证它过滤的是正确的记录,以防编写的WHERE 子句不正确。

理解NULL 不要把NULL 值与空串相混淆。NULL 值是没有值,它不是空串。如果指定''(两个单引号,其间没有字符),这在NOT NULL 列中是允许的。空串是一个有效的值,它不是无值。NULL 值用关键字NULL 而不是空串指定。
主键字段不允许为NULL
创建表 CREATE TABLE 样例



SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for shipment_header
-- ----------------------------
DROP TABLE IF EXISTS `shipment_header`;
CREATE TABLE `shipment_header`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '出库单内部号',
  `warehouseCode` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '仓库',
  `companyCode` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '货主',
  `loadId` int(11) NULL DEFAULT 0 COMMENT '装载号',
  `code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '出库单号',
  `erpOrderCode` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT 'erp订单号',
  `erpOrderType` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT 'erp订单类型',
  `erpOrderId` int(11) NULL DEFAULT NULL COMMENT 'erp订单内部号',
  `leadingSts` int(11) NOT NULL DEFAULT 100 COMMENT '主状态',
  `trailingSts` int(11) NOT NULL DEFAULT 100 COMMENT '拖状态',
  `shipmentType` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '出库单类型',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `idx1`(`code`, `warehouseCode`, `companyCode`) USING BTREE,
  INDEX `idx2`(`waveId`) USING BTREE,
  INDEX `idx3`(`loadId`) USING BTREE,
  INDEX `idx4`(`erpOrderCode`, `warehouseCode`) USING BTREE,
  INDEX `idx5`(`leadingSts`, `warehouseCode`) USING BTREE,
  INDEX `idx6`(`primaryWaybillCode`, `warehouseCode`) USING BTREE,
  INDEX `idx7`(`created`, `warehouseCode`) USING BTREE,
  INDEX `idx8`(`stamp`, `warehouseCode`) USING BTREE,
  INDEX `idx9`(`trailingSts`, `warehouseCode`) USING BTREE,
  INDEX `idx10`(`warehouseTransferId`) USING BTREE,
  INDEX `idx11`(`warehouseTransferCode`, `warehouseCode`, `companyCode`) USING BTREE,
  INDEX `idx12`(`originalBusinessOrderCode`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5497855 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '头信息' ROW_FORMAT = DYNAMIC;

SET FOREIGN_KEY_CHECKS = 1;

数据库引擎

  • InnoDB 是一个可靠的事务处理引擎(参见第26章),它不支持全文本搜索;
  • MEMORY 在功能等同于MyISAM ,但由于数据存储在内存(不是磁盘)中,速度很快(特别适合于临时表);
  • MyISAM 是一个性能极高的引擎,它支持全文本搜索,但不支持事务处理。

外键不能跨引擎 混用引擎类型有一个大缺陷。外键(用于强制实施引用完整性,如第1章所述)不能跨引擎,即使用一个引擎的表不能引用具有使用不同引擎的表的外键。

ALTER TABLE 更新表结构
定义外键
ALTER TABLE orders ADD CONSTRAINT fk_orders_customers FOREIGN KEY (cust_id) REFERENCES customers (cust_id);
ALTER TABLE table1 ADD column_name varchar(50) DEFAULT '0' NOT NULL COMMENT '注释内容'
ALTER TABLE table Drop column_name
ALTER TABLE table MODIFY column_name varchar(500) DEFAULT '1' NOT NULL
ALTER TABLE table add column column_name1 int(11) DEFAULT 1 COMMENT '注释1', ADD column_name2 int(11) DEFAULT 1 COMMENT '注释2';
alter table test_alter add user_name char(5), modify address varchar(15);
重命名表
RENAME TABLE customers2 TO customers;
批量重命名
RENAME TABLE backup_customers TO customers,backup_vendors TO vendors,backup_products TO products;
视图
因为视图不包含数据,所以每次使用视图时,都必须处理查询执行时所需的任一个检索。如果你用多个联结和过滤创建了复杂的视图或者嵌套了视图,可能会发现性能下降得很厉害。因此,在部署使用了大量视图的应用前,应该进行测试。
试图最常见的规则和限制

  • 与表一样,视图必须唯一命名(不能给视图取与别的视图或表相同的名字)。
  • 对于可以创建的视图数目没有限制。
  • 为了创建视图,必须具有足够的访问权限。这些限制通常由数据库管理人员授予。
  • 视图可以嵌套,即可以利用从其他视图中检索数据的查询来构造一个视图。
  • ORDER BY 可以用在视图中,但如果从该视图检索数据SELECT中也含有ORDER BY ,那么该视图中的ORDER BY 将被覆盖。
  • 视图不能索引,也不能有关联的触发器或默认值。
  • 视图可以和表一起使用。例如,编写一条联结表和视图的SELECT语句。
    使用视图
  • 视图用CREATE VIEW 语句来创建。
  • 使用SHOW CREATE VIEW viewname; 来查看创建视图的语句。
  • 用DROP 删除视图,其语法为DROP VIEW viewname; 。
  • 更新视图时,可以先用DROP 再用CREATE ,也可以直接用
  • CREATE OR REPLACE VIEW 。如果要更新的视图不存在,则第2条更新语句会创建一个视图;如果要更新的视图存在,则第2条更新语句会替换原有视图。
    创建语句
CREATE VIEW productcustomers AS
SELECT cust_name, cust_contact, prod_id FROM customers, orders, orderitems
WHERE customers.cust_id = orders.cust_id  AND orderitems.order_num = orders.order_num;

-- 查看
SELECT * FROM productcustomers
posted @ 2021-10-03 23:28  darling331  阅读(108)  评论(0编辑  收藏  举报