主键:
主键能唯一标识表中某行,类似人的身份证号,一个名字可以对应多个人,但一个身份证号只能唯一对应一个人
注意
- 主键在任意两行都不相同(主键唯一)
- 每行都需要有个主键值,主键不能为空。(该行能被唯一找到)
- 主键值不能被修改和更新
- 主键不能被重用,哪怕该行被删除,该主键也不该赋予新的行。
Select从一个表或者多个表中检索信息。
SQL的语句不区分大小写,但为了区分语法关键字,语法的关键字全部用大写
SELECT 列名1,列名2,---列名N FROM table1;
SELECT * FROM table1; - 从table1中打印所有行
Order by 列名1,列名2,,,, 按照列名从前往后排序
SELECT 列名1,列名2 FROM table1 Order by 2,3,4,,,,按照列名2,3,4(相对位置)来进行排序 (不建议使用)
Order by 为升序排序 a-z
Order by ---- DESC 为降序排序 z-a (DESC只对他前面的一个列名有效。用,划开区分)
Order by 最好是最后一条语句,这样会方便调试出想要的顺序结果。
where过滤。
SELECT 列名1,列名2 FROM table1 WHERE 列名X=Y; 从table1中,挑选出列名X=Y的列名1,2的行。
常用where的方式:
等于 =
不等于 != <>
大于 >
小于 <
大于等于 >= !<
小于等于<= !>
两个值之间 between
IS NULL 为NULL值 可以判断是否为空值
between 低的值 and 高的值;(包含边界)
原则:先筛选过滤在排序
高级排序,Where组合操作符 AND OR
And:
where 条件1 and 条件2 and-----;匹配满足条件1,2---n的行
or与and语法类似,满足任意一条条件都可以被匹配出来。
注意:OR和AND一起位于条件时;
例如:条件1 OR 条件2 AND 条件3;
也许你期望的是(满足条件3的(条件1或者条件2))
但实际是(条件1或者 (条件2and条件3))
解决方法:加圆括号提高优先级 修改后: (条件1 OR 条件2)AND 条件3
IN的语法:
where 列名1 IN (“值1”,“值2”,,,,“值n”) 从表中找列名满足值1,或者值2,,,,或者值n
相当于: where 列名1=“值1” OR 列名1=“值2” OR ------列名1=“值n”;
注意:如果匹配的值为字符串需要加引号“”,如果是数字等,则无需加引号。
NOT操作符,否定后续所有条件,相当于!,非;
LIKE谓词,后面可以跟随不确定值的通配符 *,%;
“”fish%“” :搜索以fish开头的所有匹配项;
“%fish%”:搜索匹配任何位置包含fish的值
“%fish ”:匹配以fish结尾的所有匹配项
“f&y”:匹配以f开头,y结尾的所有匹配项
_通配符作用于%很像,但一次只能通配1个字符,不能多也不能少
注意:%也能匹配0个字符,》=0
[]方括号通配符用来指定一个字符集,它必须匹配指定位置(通配符的位置)的一个字符
例如字符集[JM]
WHERE 列名 LIKE '[JM]%',匹配以J开头或者M开头后任意字符的行
否定集合 ^
WHERE 列名 LIKE '[^JM]%',匹配除了以J开头和M开头后任意字符的行
相当于 WHERE NOT 列名 LIKE '[JM]%'
注意:通配符是需要付出性能的部分代价,在保证正确性的情况下可以尽量不使用通配符
通配符最早使用的话,性能付出的越大。越后使用的话,付出的越小。
计算字段(成为新列)
有的数据并不是我们直接想要用的,如单价和数量需要计算才能得到总价格。
杭州的区域,邮政编码,电话号码等需要组合在一起才能形成有效信息
计算字段在DBMS中运算要比在客户机中高效。
计算字段在用户看来也许和普通的列相同,计算机才知道区分它们。
字段拼接 + 或者 ||
如公司名称 film-name 和位置 site需要一起弄出来
film-name + site film-name || site
+ || 看实际的DBMS是否支持
SELECT CONCAT(name,'(',jiage,')') FROM room; 将房间名和价格拼接成一个新的列
CONCAT为拼接函数,Mysql有效
RTRIM()
RTRIM函数可以取消字段右边的空格。
L----- 左边
TRIM 两边的空格
关键字AS:给列取别名(导出列)
SELECT CONCAT(name,'(',jiage,')') AS room-price FROM room; 将房间名和价格拼接成一个新的列,列的名称叫room-price
函数:
常用的包含字符串处理函数,数值计算函数,处理日期时间并截取的函数,返回DBMS正使用的特殊信息的系统函数。
UPPER(列名) AS 新列名 将列名中的字母全部大写后,改为新列名的一列。
LEFT() 返回串左边的字符
RIGHT() 右边
LENGTH() 串的长度
LOWER() 串全部小写
SOUNDEX() 返回串的SOUNDEX值
注意:SOUNDEX(‘str1’)匹配的是发音与str1相似的字符串
YEAR() 提取年份
NOW() 获取当前的日期+时间
SYSDATE() 和now()一样,不过NOW()是执行就立刻得到值,而SYSDATE()是执行中动态得到的值;
current_timestamp, current_timestamp() 获取当前时间戳,和now()很像
mysql> 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 | +----------------------------------------------------+
date_format() 时间格式化函数(日期可以转化为字符串,这样其实比较方便比较)
str_to_date(str,format) 转换函数,可以把一些杂乱无章的字符串转换为日期格式。
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
格式参考以上,'%Y%m%d%h%i%s' 分别对应 年月日时分秒
MySQL (日期、天数)转换函数:to_days(date), from_days(days)
select to_days('0000-00-00'); -- 0 select to_days('2008-08-08'); -- 733627
MySQL (时间、秒)转换函数:time_to_sec(time), sec_to_time(seconds)
select time_to_sec('01:00:05'); -- 3605 select sec_to_time(3605); -- '01:00:05'
数值函数
ABS() 返回数的绝对值
COS() 余弦
SIN() 角的 正弦
TAN() 正切
EXP() 返回数的指数值
SQRT() 数的平方根
PI() 返回圆周率
聚集函数
有时候不需要实际把数据检索出来,只需要统计表的某些数据并打印即可
例如,打印某些行的总行数,找出表列最大值,最小值,平均值。
AVG() 返回 某列的平均值
COUNT() 某列的总行数
MAX() 某列的最大值
MIN() 小
SUM() 某列的总和
注意:默认条件下,聚集函数会忽略值为Null的行,不参与计算
AVG()
例子:SELECT AVG(jiage) AS avg_price FROM room; 计算room 价格的平均值,打印为avg_price的列表示
COUNT()
COUNT(*) 计算所有的行数,包含值为NULL的行
COUNT(列名) 忽略列名值为NULL的行
MAX()
例子:SELECT MAX(jiage) AS max_price FROM room;
注意:要求指定列名
MIN() 与MAX()类似
注意:max(),min()如果列中存在两个以上的最大或者最小值,要小心
SUM()
例子:SELECT SUM(jiage*5.4) FROM room ; 把room中的所有行jiage*5.4后加在一起。同理,()内可以加任意的表达式,得到想要的结果
组合聚集函数
例子:SELECT
COUNT(*) as item_nums,
MIN(jiage) AS price_min,
MAX(jiage) AS price_max,
AVG(jiage) AS price_avg
FROM room;
输出:(列名没有打出来但实际上有)
8 299 2880 929.0000
数据分组:group by(不一样的where) group by 列名1 类似将以经被筛选过的行,根据列名1的种类给进行行划分(如果是数值,貌似还会按升序排列分组(可能仅仅是你的DBMS支持,这并不像是order by 那种必须要求的规范))
注意:
group by 可以包含任意数目的列,可以更细致的分组
如果嵌套了分组,数据将在最后规定的分组上进行汇总。
group by字句中的每个列必须是检索列或有效的表达式(但不能是聚集函数),如果在select中使用表达式,则必须在group by子句中使用相同的表达式,不能用别名
大多数SQL实现不允许group by列带有长度可变的数据类型(如文本或者备注型字段)
除聚集计算语句外,select的每个列都必须在group by子句中给出
如果含有null的行,会把他们聚集在一起为新的分组
group by 语句必须在where后,order by之前
例子:
SELECT
type,
COUNT(*) AS items
FROM room;
输出
单人间 8
如果用上group by
SELECT
type,
COUNT(*) AS items
FROM room;
输出
单人间 2
双人房 4
总统套房 2
分组过滤 having
在已经数据分组的情况下,可以用having过滤不满足条件的分组
注:
where过滤行,行被数据分组后,having过滤分组
having支持所有的where操作符,只是关键字有所差别
子查询
嵌套查询,从内而外
select 列名1
from 表1
where 列名2 IN(
select 列名3
from 表2
where 列名4=“”);
特点:嵌套灵活且无数量限制,但有性能代价
子查询的select只能查询一个列,检索多个列时会有错误
联结,将不同的表(有主键)通过能够对应的列,组成一张新的关系表;
特点:如果每个表的列名都不重复,联结在一起时节省了时间和空间。另外在修改某一列某行数据时,由于在所有表中此表唯一,联结在一起时就不用修改多个表;
创建联结
例子:
SELECT
name,
yddate,
user.tel
FROM torder,user
WHERE torder.username=user.name
输出
李磊 2020-03-31 20:51:17 15299998483
李磊 2020-03-31 23:37:40 15299998483
李磊 2020-04-01 00:08:12 15299998483
李磊 2020-04-03 00:14:29 15299998483
李磊 2020-04-02 00:15:21 15299998483
李磊 2020-04-03 00:25:10 15299998483
where作为限定条件,可以将两个表中有关系的行完全逻辑匹配(不会出现畸形表)
而没有的话就会不管逻辑,出来的表可能会很畸形(笛卡尔积)
为了避免这种情况,我们每次联结时都需要加where条件匹配
笛卡尔积就是把没有联结的两张表联结在一起。行数=第一张表的行数*第二张表的行数。
内部联结:
FROM 表1 INNER JOIN 表2
ON 表1.列名1=表2.列名2;
多表联结:
当然也可以用where 条件1 and 条件2 and,,,,条件n
进行多表联结;多表联结的表没有数目限制,但是很明显,联结的表越多,性能下降的越厉害
注意,多表联结和子查询可以产生同样的效果,但是为了达到某一种效果,并不存在绝对正确的写法,
因此,在性能优化时,有必要进行多种尝试,达到性能局部优化。
除了给列名和计算字段取别名外,SQL还允许给表取别名,好处有两个:
1,缩短SQL语句
2,可以多次使用别名表
其他三种联结:
自联结
FROM 表1 AS A,表1 AS B
WHERE A.列名1=B.列名1
AND B.列名3=“属性值1”;
从列名3找到属性1的行,然后根据列名1 select打印出来
自然联结
自然联结使在多个表中相同的列只出现一次,一般通过对表使用通配符,其他的表使用子集明确使用的列;
我们建立的每个内部联结都属于自然联结
外部联结
有时候也要包含没有关联行的那些行
FROM 表1.列名1 (LEFT/RIGHT)OUTER JOIN 表2.列明2
若为left join 以左边的表为基准,去匹配右边的表
right 右边 左边
简化的外部联结语法:
FROM 表1,表2
WHERE 表1 .列名1 ( *= 或者 =* )表2.列名2
此处的联结语句在where中规定,*=是左外部联结操作符;;;
含有FULL OUTER JOIN 全外部联结的语法,他能让两个表中的关联行组合,保留非关联行,但有的数据库不支持
带聚集函数的联结
例子:
SELECT user.name,COUNT(user.`name`) AS uname,user.tel,user.sex,upwd
FROM torder RIGHT OUTER JOIN user
ON user.name=torder.username
GROUP BY user.name
解释,COUNT聚集函数在selec后完成计数并命名为uname列(统计了每个名字出现的行数的数量)
结果
刘永 1 15299998483 男 123456
李磊 6 15299998483 男 123456
王东方 1 18957865821 男 123456
王铁锤 1 15299998484 男 123456
组合查询
其实就是多个select语句但只返回一个组合在一起的结果(表)
两种情况下用组合查询的情况比较多:
对单个查询中从不同的表类似返回结构数据
对单个表执行多次查询,按单个查询返回数据
任何具有多个WHERE子句的SELECT语句都可以作为一个组合查询给出。
UNION可以给出多条SELECT语句,并将结果组合成单个的结果集
UNION可以放在两个SELECT查询的中间,并将结果集去重合并在一起
注意:
UNION可以连接前后两个SELECT查询,使用N个UNION,可以连接N+1个SELECT查询
UNION的结果可能和WHERE ---OR---OR--- 结果一致,使用时的取舍参考筛选的复杂度,当然后期也可以测试两种方法的性能
UNION查询的列必须包含相同的列,表达式或聚集函数(不过顺序方面没有要求)
列数据类型应该可以兼容(可以不必完全相时间同,但必须能被DBMS隐含的转换)
如果想要不去掉重复的行,可以使用UNION ALL
UNION查询结果的排序:
只能使用一次GROUP BY,GROUP BY 只能出现在最后一个SELECT语句后
(虽然出现的结果是筛选后排序的,但实际排序的是所有SELECT语句的返回结果)
其他两种UNION类型
EXCEPT ,检索第一个表中存在,但第二个表中不存在的行
INTERSECT ,检索两个表中都存在的行
注意:这两种UNION类型很少使用,因为可以通过联结得到同样的结果
Mysql时间处理函数
思路:总体数据分两类,日期和时间戳,时间戳通过from_unixtime(字段,'%--%--%--')转化为日期
然后学会日期的处理即可
插入数据
INSERT 表1 VALUES(值1,值2,值3,,,,,值n)
在表1中插入值,值可以为NULL,只要创建表的时候允许即可,值与表1中列的前后顺序也对应
注:
1.INSERT 后可以加入INTO的关键字,虽然不加也可以,但加了可以增强可移植性
2.INSERT 表1(表列名) VALUES(值1,值2,值3,,,,,值n),这样写虽然繁琐,但是列的顺序改变后依然可以对应准确插入
3.不插入值的时候需要两个条件之一(允许为空或者 含有默认值)
插入检索(SELECT)出的数据
INSERT 表1 SELECT 值1,值2,,,值n FROM 表2
在表1中插入表2中被筛选出来的值
注:
1.值1~n必须是表1所有列的子集。
2.并且对于主键的值是不能重复的,否则会报错
3.表2中可以筛选列的数量可以为0,甚至比表1的列数量要少,这是合法的。将SELECT的第一列与
INSERT表的第一列对应插入(不管其列名)
4.表2中也可以筛选出0条记录行插入,这也是合法的。
复制表数据到一个新表 SELECT INTO
SELECT * INTO 表1 FROM 表2
把表2中的所有数据复制到表1(当然也可以选取部分数据复制),有的不是复制新的数据过去,也可能是覆盖重写(看具体的数据库)
注:
1.可以在任何SELECT选项和子句中使用,包括WHERE和GROUP BY
2.可以使用联结从多个表中筛选相应的列和行
3.不管从多少个表内筛选数据,一次只能插入一个表
更新(修改)数据UPDATE
1.更新表中特定行
2.更新表中所有行
注意:
1.要注意where条件,以免更新的行发生错误
2.要确认自己的权限是否足够
UPDATE 表1
SET 列名1=值1,列名2=值2,,,,,,,,列名n=值n
WHERE 限定条件1
在表1筛选出限定条件1的行,按照列名和值一一对应的修改更新
注:
1.UPDATE可以使用子查询
2.可以支持FROM关键字,这样可以使用另外表的行来更新某个表的特定行数据(要看数据库支不支持)
3.如果想使用删除,也可以用NULL设置相关的行中列的数据。(只要支持为空)
删除数据DELETE
删除表中特定(或者所有)行
例子:
DELETE 表1
WHERE 条件1
删除表1中满足条件1的所有行
注:
1.如果省略WHERE,则是删除所有行(若要删除指定的列,使用UPDATE语句)
2.DELETE后可以加FROM,增加可移植性
3.DELETE删除表中所有行,并不是删除表,只是表为空
4.如果想要删除表中的所有数据,不要用DELETE,可以用TRUNCATE TABLE语句,这样会更快
使用UPDATE和DELETE应该遵循的习惯
1.保证尽量使用WHERE
2.保证每个表都会有主键,且这些主键数据唯一性
3.使用UPDATE和DELETE前,先SELECT,看需要操作的数据是否正确
4.使用强制实施引用完整性的数据库,这样DBMS将不允许删除具有与其他表相关联数据的行
创建表CREATE
表的创建有两种办法:
1.大多数DBMS有交互式的界面,通过这个界面可以建立表(实际上是DBMS在使用SQL语句执行你的操作)
2.运用SQL语句执行创建表
利用CREATE 表名1,要给出以下的信息:(创建表也要考虑不同数据库的差别)
1.表名1,也就是名字
2.列名和对应的数据类型
例子:
CREATE TABLE emp
(
id INT(4) NOT NULL,
emp_no INT(4) NOT NULL,
emp_name VARCHAR(100) NOT NULL,
emp_sex TINYINT(1) NOT NULL
);
显示表结构:DESC 表名1 或 describe 表名1
显示数据库内所有表 SHOW TABLES
NULL值相关
1.如果某列不指定为NOT NULL,创建时默认为NULL(大多数DBMS)
2.只有为NOT NULL的列才可以成为主键或者唯一标识
3.要明白NULL和‘ ‘(空字符串)的差别。空字符串并不为空,用ISNULL()等函数判断时需要小心
默认值DEFAULT
在创建表时,尽量不要使用NULL列,而是用默认值塞入数据
更新表 ALTER TABLE
几个原则:
1.尽量不要做更新这个举动,在创建表时应充分的考虑好未来的可能需求,不要对表结构做较大改动
2.一般DBMS支持表的列增加。而对已有表的列删除和更新有限制(这也需要仔细的斟酌)
3.多数DBMS允许更改列名
4.多数DBMS对未填数据的列更改几乎无限制,对填有数据的列更改有限制
使用ALTER TABLE表需要几个关键信息,表名,更改的列
例子
ALTER TABLE emp
ADD phone VARCHAR(50);
注意:
1.在使用ALTER TABLE 前,最后把原来的表结构和数据都复制一遍,以免发生不可挽回的错误
删除表DROP
DROP 表名1
即可删除 表名1,不仅仅是内容,而是整个表都没了。(不同于显示空表)
注意:有些表和其他的表有所关联,要确认好这些关系才可以考虑DROP操作
重命名表RENAME
一般指定好旧表名和新表名就行,具体语法查看相应的DBMS
视图
视图相比于实际存在的表,是个虚拟的表。它只包含使用时动态检索出的数据
使用视图的目的:
1.重用SQL语句
2.简化复杂的SQL操作
3.使用表的组成部分而不是整个表
4.可以保护数据,可以给予用户重要表的部分数据的查看权限,而不会给用户查看原表并泄露出重要的数据。
5.更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。
注:视图中不存储真实的数据,这样的虚拟表在经过复杂或庞大的数据,表操作时,会有较大的性能下降。因此,在部署了大量视图的应用应该进行测试
视图的一些常见规则和限制:
1.与表一样,视图必须唯一命名(不能让某个视图的名字和别的视图或者表名’撞车‘)
2.创建视图的数目没有限制
3.创建视图时,需要得到相应的权限
4.视图是可以嵌套使用的。(像表一样)
5.很多DBMS禁止在视图查询中使用ORDER BY子句
6.视图不能索引,也不能有关联的触发器和默认值
7.有的DBMS只把视图作为只读查询,视图的数据是不允许写入表的(为了一定的安全性)
视图创建 CREATE VIEW
注:
1.用DROP删除视图,语法为DROP VIEW 视图名1
2.覆盖或者更新视图时,必须先DROP,再重新创建
利用视图简化复杂的联结
CREATE VIEW 视图名1 AS (SELECT检索出来的表);
思考的一点,如果有的表经常是作为别的表的基石,甚至是多层嵌套,那么最好不要用视图。如果是那种只需要一些条件筛选便能够展现多种不同维度的表(只需要一层加工),用视图会比较方便
使用存储过程(或许可以理解为函数)
简单来说,就是为以后的使用而方便保存的一条或者多条SQL语句的集合。可以视其为批文件。尽管他们的作用不仅局限于批处理。
使用存储过程的理由:
1.通过把处理封装在容易处理的单元中,简化复杂的操作
2.保证了数据的一致性。如果开发人员们和应用程序都使用同一存储过程,则使用的代码是相同的。
3.简化了对变动的管理。如果数据是正确的情况下,改变了数据的处理流程或者业务逻辑,那么只需要更改存储过程的代码。使用它的人员甚至并不知道这种变化。不仅很方便,而且提升了安全性。
4.存储过程会经过编译后的形式来存储。所以DBMS在一次编译之后,后续的使用无疑减少工资,提高了性能。
(简单,安全,高性能)
一些缺陷:
1.可移植性比较差。改变环境时要考虑这一点(不同的DBMS也许需要编写不同的语句完成相同功能)
2.编写比一般的SQL语句复杂,对技能有所要求。在编写存储过程并使用的过程中也要保证自己权限
执行存储过程 EXECUTE
管理事务处理COMMIT(提交) ROLLBACK(回退)SAVEPOINT(保留点)
事务处理可以维护数据库的完整性,它保证成批的SQL操作要么完全执行,要么完全不执行
示例:(1)插入新订单前,检索客户是否在数据库中,若无,则插入
(2)在订单表表插入新的订单号
(3)在货物表中插入新的行。
如果数据库发生故障(如内存已满,安全限制,表锁等)那么可能会在其中中断。我们分析,如果在完成(1)中断,有新用户但是没订单是完全合法的。如果在完成(2)之后,(3)未完成就中断退出。那么数据库会出现新的订单号,这是个空的订单。这样会造成未知的后续威胁。
这时我们使用事务管理,将(1),(2),(3)绑定在一起称为S1。那么S1将作为一个新的原子操作。要么S1发生,要么S1不发生。这样就完成了数据的一致性。
四个关键词:
1.事务:一组SQL语句
2.回退:撤销指定的SQL语句
3.提交:将未存储的SQL语句结果写入数据库表
4.保留点:指事务处理中设置的临时占位符,你可以对它发布回退(与整个回退不同,相当于你SAVE了--游戏存档)
回退的范围:
回退可以管理INSERT,DELETE,UPDATE。不能回退SELECT(也没啥必要),不能回退CREATE和DROP操作(事务处理中可以使用,实际上回退后,这些并不被撤销)
事务处理的关键是把一组SQL语句按逻辑分块。比如原来是S1的操作把他分为(1)(2)(3),然后设置提交,保留点和回退操作。
思考:
在查询操作中,无所谓事务处理的。我们需要真正注意的是复杂或大规模下的增删改操作,需要判断这些操作在其中一旦发生错误,是否会产生不可挽回的损失。另外就是需要把一整组的SQL语句进行逻辑分块,并在适当的位置进行回退和保存操作。
使用游标
(暂不了解)
SQL高级特性:约束,索引和触发器
约束
管理如何插入或处理数据库数据的规则。大多数约束是在表定义的。
主键PRIMARY KEY
外键REFERENCES 后面接 表名1(主键1) 在一个表中的列是另外一张表的主键
(外键的使用可以防止某些意外的删除,有些数据库在删除主键表时,那么相关外键的表就会失去引用。有些DBMS事不允许的。除非先将这些关系解除。或者是删除主键表,所有与之相关的外键表全部删除,这叫级联删除)
唯一约束UNIQUE
用来保证一个列(或者一组列)中的数据唯一。类似于主键,但存在一些重要差别:
1.表只存在一个主键,但可能有多个唯一约束
2.唯一约束列可以包含NULL值
3.唯一约束列克修改或者更新
4.唯一约束列的值可重复使用
5.与主键不同,唯一约束列不能用来定义外键。
检查约束CHECK
可以保证一个(或一组)列中的数据满足一组指定的条件。常用的用途有:
1.检查最大最小值。例如,防止0个物品的订单
2.指定范围。例如:选定满足某段日期内的订单
3.只允许特定的值。例如:性别字段只允许F或者M。
数据类型指定了保存数据的类型。检查约束在此之上进一步的筛选
索引CREATE INDEX
按照某些顺序去加速查找特定的数据,而不是顺序查找所有的数据。例如:书本的页码用来定位。查字典有按照英文顺序去查找。
使用索引前的注意事项:
1.索引能提高查找的效率,但是会对增删改的性能造成影响。在执行这些操作时。DBMS必须动态的更新这些索引
2.索引数据可能要占用大量的存储空间
3.并非所有的数据都适合索引。尤其要小心唯一性不好的数据。
4.索引用于数据过滤和数据排序。如果经常以某种特定的顺序排序数据,则该数据可能是索引的备选
5.可以用索引定义多个列。(如州加上城市)
6.建立好索引后,最好评估下性能(随着数据的增删改和变化,也需要定期的检查索引)
触发器(可能类似于事件或者监听器??)TRIGGER
触发器是特殊的存储过程。可以与特定表上的增删改(或这些操作的组合)相关联
触发器与单个的表相关联
触发器内的代码具有以下数据的使用权:
1.INSERT所有的新数据
2.UPDATE所有的新数据和旧数据
3.DELETE删除的旧数据
触发器的常用用途:
1.保证数据的一致(类似检查约束),例如把州名的字母都转化为大写
2.关于某个表的变动在其他表上执行活动。例如,某个表的更新会被写入日志
3.进行额外的验证,若不符合,回退操作
4.计算某个计算列的值或者更新时间戳
注意:一般情况下约束比触发器更快,因此,在可能的情形下尽量用约束
数据库安全
主要涉及到访问权限,和数据库数据的存放管理
一般需要保护的操作有:
1.对数据库增删改操作的权限管理
2.对某些极为重要的数据库和表的保护
3.访问的类型(只读,特定列的访问)
4.仅通过视图或者存储过程对表进行访问
5.灵活多变的层次和动态的权限控制‘
SQL变量
大致分为系统变量和用户变量,实际使用细化为四种:局部变量,用户变量,会话变量和全局变量。
一,局部变量
mysql局部变量,只能用在begin/end语句块中,作用域也仅限该语句块。
用法:
declare x int default num; 定义一个Int变量x,默认值为num
set x=num; 设置x = num
select X into x from demo.student where [];
二,用户变量
mysql使用用户变量不需要提前申明,用的时候“@变量名”使用即可,作用域为当前连接
-- 第一种用法,使用set时可以用“=”或“:=”两种赋值符号赋值
set @age=19;
set @age:=20;
-- 第二种用法,使用select时必须用“:=”赋值符号赋值
select @age:=22;
select @age:=StuAge
from demo.student
where StuNo='A001';
三,会话变量
MySQL会话变量,服务器为每个连接的客户端维护一系列的会话变量。
其作用域仅限于当前连接,即每个连接中的会话变量是独立的
-- 显示所有的会话变量
show session variables;
-- 设置会话变量的值的三种方式
set session auto_increment_increment=1;
set @@session.auto_increment_increment=2;
set auto_increment_increment=3; -- 当省略session关键字时,默认缺省为session,即设置会话变量的值
-- 查询会话变量的值的三种方式
select @@auto_increment_increment;
select @@session.auto_increment_increment;
show session variables like '%auto_increment_increment%'; -- session关键字可省略
-- 关键字session也可用关键字local替代
set @@local.auto_increment_increment=1;
select @@local.auto_increment_increment;
四,全局变量
mysql全局变量,全局变量会影响服务器的整体操作,当服务启动时,它把所有全局变量初始为默认值。要向更改全局变量,必须具有super权限。作用域为server整个生命周期
-- 显示所有的全局变量
show global variables;
-- 设置全局变量的值的两种方式
set global sql_warnings=ON; -- global不能省略
set @@global.sql_warnings=OFF;
-- 查询全局变量的值的两种方式
select @@global.sql_warnings;
show global variables like '%sql_warnings%';