当前位置: 代码迷 >> 综合 >> Sql必知必会
  详细解决方案

Sql必知必会

热度:50   发布时间:2024-02-01 19:35:23.0

主键:

主键能唯一标识表中某行,类似人的身份证号,一个名字可以对应多个人,但一个身份证号只能唯一对应一个人

注意

  1. 主键在任意两行都不相同(主键唯一)
  2. 每行都需要有个主键值,主键不能为空。(该行能被唯一找到)
  3. 主键值不能被修改和更新
  4. 主键不能被重用,哪怕该行被删除,该主键也不该赋予新的行。

 

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%';

 

 

 

 

  相关解决方案