DISTINCT 关键字
它指示数据库只返回不同的值,相同的都被过滤.
注意:这个关键字是作用在所有列上的,除非完全一样,否则会列出所有的列.
用途:可以用来再订单表里面,查找有多少商户下过订单,根据商户ID.
LIMIT 限制结果.
有三种常规用法.返回按照排序规则.
limit n : 表示一共返回n条数据.
limit n,m: 表示返回的是从结果集n位置(包括n)数据开始的m条,所以数据集合一共m行. 数据库中的数据位置从0开始的.所以, 取0,10.取到的才是数据库第一条数据到第十条. SQL里面写的是位置,而不是第几条.
limit n offset m : 表示:从数据库的m位置开始,选择n条数据.
LIKE操作符
需要使用通配符.通配符搜索只能用于文本字段(串).非文本数据类型字段不能使用通配符搜索.
% 表示任何字符出现任意次数.可以在搜索模式中任意位置使用,并且可以使用多个通配符.
注意:%不会匹配为NULL的行.
_ 表示单个字符.总是匹配一个字符,不能多也不能少.
[] 指定一个字符集,它必须匹配指定位置(通配符的位置)的一个字符. MySQL不支持.
注意:把通配符置于开始处,搜索起来是最慢的.通配符的位置很重要.
计算字段
计算字段是运行时在SELECT语句内创建的.
字段基本上与列的意思相同,经常互换使用,不过数据库列一般称为列,而术语字段通常与计算字段一起使用.
在数据库上完成转化和格式化工作要比在客户端中完成的要快得多.
常用方法一: 拼接字段.
TRIM(String) :去掉左右两边的空格
LTRIM(String) :去掉左边的空格
RTRIM(String) :去掉右边的空格
CONCAT(str*) : 可以将多个搜索结果组织在一起.例:CONCAT(o.city_id,'市 ',o.province_id,'省 ') AS location
常用方法二: 执行算术计算.
+ - * / 基本运算.
SELECT关键字可以用来测试,检验函数和计算.
别名
别名是一个列或者值的替换名.别名使用AS关键字赋予.
AS通常可选,不过最好使用它,这个是最佳实践.
别名通常既可以是一个单词也可以是一个字符串.
使用数据处理函数.
函数一般是在数据上执行的,为数据的转换和处理提供了方便.
使用函数:
1.大多数SQL支持以下类型的函数:用于处理文本字符串(如删除或者填充值,转换值为大些或者小写)的文本函数.
UPPER(str): 将文本转化为大写.
LEFT(str,n) :从左开始,取字符串的前n位.n从1开始.
RIGHT(str,n):从右开始,取字符串的后n位,n从1开始.
SOUNDEX(str): 将任何文本串转换为描述其语音表示的字母数字模式的算法.
TRIM(String) :去掉左右两边的空格.
LTRIM(String) :去掉左边的空格.
RTRIM(String) :去掉右边的空格.
2.用于在数值数据上进行算术操作(如返回绝对值,进行代数运算)的数值函数.在各个平台上最为统一.
ABS(): 返回一个绝对值
COS(): 返回一个角度的余弦值
EXP(): 返回一个数的指数值
PI(): 返回圆周率
SIN(): 返回一个角度的正弦.
SQRT(): 返回一个数的平方根.
TAN():返回一个角度的正切.
3.用于处理日期和时间值并且从这些值中提取特定成分(如返回两个日志之差,检查日期有效性)的日期和时间函数.在各个平台移植困难.
SELECT DAYOFYEAR('2016-11-29 16:19:13'); 获取年中的具体哪一天
SELECT WEEKOFYEAR('2016-11-29 16:19:13');获取年中的具体那一周
SELECT DATE('2016-11-29 16:19:13'); 获取日期
SELECT YEAR('2016-11-29 16:19:13'); 获取年
SELECT MONTH('2016-11-29 16:19:13'); 获取月
SELECT DAY('2016-11-29 16:19:13'); 获取日
SELECT TIME('2016-11-29 16:19:13'); 获取时间
SELECT HOUR('2016-11-29 16:19:13'); 获取时
SELECT MINUTE('2016-11-29 16:19:13'); 获取分
SELECT SECOND('2016-11-29 16:19:13'); 获取秒
具体用法:
SELECT
o.id,
UPPER(TRIM(o.downstream_account_id)) AS account_id,
o.create_time
FROM order_info o
WHERE WEEKOFYEAR(o.create_time) = 30/*后面的这个数值可以动态改变*/
ORDER BY o.id;
4.返回DBMS正使用的特殊信息(如返回用户登录信息)的系统函数.
SELECT current_user: 返回当前登录用户.
使用注释
1. # 单行注释
2. /* */ 多行注释
聚集函数
功能作用:希望获取汇总信息:
* 确定表中行数.(或者满足某个条件或包含某个特定值的行数). * 获得表中某些行的和. * 找出列表(或所有行或某些特定的行)的最大值,最小值,平均值. * 返回结果要比应用程序中计算要快得多.常用函数:
AVG(): 返回某列的平均值.只能用于单个列,多个列需要使用多个,忽略列值为null的列.可以使用DISTINCT字段来去除重复的值 COUNT(): 返回某列的行数.用来确定表中行的数目或符合特定条件的行的数目. COUNT(*): 对表中行的数目进行计数,无论是Null或非Null. COUNT(列): 对特定列中具有值的行数进行计数,忽略Null值. MAX(): 返回某列的最大值.返回指定列的最大值,要求指定列名. MIN(): 返回某列的最小值. SUM(): 返回某列值之和.返回和,也可以返回计算字段之和.
数据分组
分组可以将数据分为多个逻辑组,对每个组进行聚集计算.
分组是使用GROUP BY子句建立的.使用聚集函数时,是对每个组而不是整个结果进行聚集.分组使用规则
- GROUP BY 字句可以包含任意数目的列,因而可以对分组进行嵌套,更细致地进行数据分组.
- 如果在GROUP BY子句中嵌套了分组,数据将在最后指定的分组上进行汇总.换句话说,在建立分组时,指定所有的列都一起计算.
- GROUP BY子句中列出的每一列都必须是检索列或有效的表达式(但不能是聚集函数).如果在SELECT中使用表达式,则必须在GROUP BY中指定相同的表达式.不能使用别名.
- 大多数实现不允许GROUP BY 列带有长度可变的数据类型.
- 除计算语句外,SELECT语句中的每一列都必须在GROUP BY 子句中给出.
- 如果分组列中包含具有Null的行,则Null将作为一个分组返回.如果列中有多行NULL值,它们将分为一组.
- GROUP BY 字句必须出现在WHERE字句之后,ORDER BY 字句之前.
过滤分组
- WHERE过滤指定的是行而不是分组.WHERE没有分组概念.
- HAVING非常类似WHERE,事实上,目前学过的所有WHERE字句都可以使用HAVING来代替.唯一差别是,WHERE过滤行,HAVING过滤分组.
- HAVING支持所有WHERE操作符.
- WHERE在数据分组之前进行过滤,HAVING在数据分组之后进行过滤.WHERE排除的行不包括在分组中,这可能会改变计算值,从而影响HAVING子句中基于这些过滤掉的分组.
- 分组和排序
GROUP BY 对行分组,但输出可能不是分组的顺序.不能依赖此种排序方式.
子查询
- 子查询
- MySQL是从4.1版本引入的,早期的版本不支持.在SELECT语句中,子查询总是从内向外处理.
- 作为子查询的SELECT语句只能查询单个列.企图检索多个列将返回错误.
- 子查询常用于WHERE子句的IN操作符中,以及使用填充计算列.
- 作为计算字段使用子查询
- 使用子查询的另一种方法是创建计算字段.
- 使用完全限定类名.避免歧义.
联结表
- 联结
SQL最强大的功能之一就是能在数据查询的执行中联结表.联结睡利用SQL的SELECT能执行的最重要的操作. - 关连关系表
- 将信息分解成多个表,一类数据一个表.各表通过某些共同的值互相关联.
- 好处:避免浪费存储空间;只需修改一次信息相对应的关联表无需更改.
- 关系数据可以有效存储,方便处理,可伸缩性远比非关系型数据库要好.
- 可伸缩:能够适应不断增加的工作量而不失败.设计良好的数据库或应用称为可伸缩性好(scale well).
- 为何使用联结
- 将数据分为多个表能更有效的存储,更方便地处理,并且可伸缩性好.因此使用联结来检索数据.
- 联结是一种机制,用来在一条SELECT语句中关联表.使用特殊的语法,可以联结多个表返回一组数据,联结在运行时关联表中正确的行.
- 联结不是物理实体,它在实际的数据库中并不存在.DBMS会根据需要建立联结,它在查询期间一直存在.
- 创建联结.
- 使用WHERE子句建立联结关系.在一条SELECT语句中联结几个表时,相应的关系是在运行中构造的.在数据库表的定义中没有指示DBMS如何对表进行联结的内容.这个必须由开发者自己做.在联结两个表时,实际要做的是将第一个表中的每一行与第二个表中的每一行配对.WHERE子句作为过滤条件.没有WHERE条件,第一个表中的每一行将与第二个表中的每一行配对,而不管它们逻辑上是否能配在一起.
- 由没有联结条件的表关系返回的结果为笛卡尔积.检索出的行的数目是第一个表中的行数乘以第二个表中的行数.有时返回笛卡儿积的联结,也称叉联结.
- 联结多个表
- SQL不限制一条SELECT语句中可以联结的表的数目.创建联结的基本规则也相同.处理联结非常消耗资源,需注意,不要联结不必要的表.联结表越多,性能下降越厉害.
创建高级联结
- DBMS处理联结远比处理子查询快得多.
多种联结方式:
* 标准联结(内联结 INNER JOIN):返回所有数据,相同的列甚至出现多次. * 自然联结:排除多次出现,使每一列只返回一次.系统不完成这项工作,由你自己完成.自然联结要求你只能选择那些唯一的列,一般通过对一个表使用通配符( * ),而对其他的表使用明确的子集来完成. * 外联结:联结包含了那些在相关表中没有关联的行.在不同SQL中的实现稍有不同. > 内联结查询订单和顾客,只能查到下了订单的顾客,而无法统计没有下订单的顾客,此时需要通过外联结来统计.查外联之前的全部,外联之后可以为null.(前后通过LEFT,RIGHT来判断).LEFT: 从子句的左边的表中选择所有行.RIGHT: 从子句的右边的表中选择所有的行.总是有两种基本的外联结形式:左联结和右联结.它们之间的唯一差别是所关联的表的顺序. > 全外联结: 它检索两个表中的所有行,并关联那些可以关联的行.MySQL不支持此语法.
组合查询–UNION
定义:
SQL允许执行多个查询(多条SELECT语句),并将结果作为一个查询结果集返回.这些组合查询通常称为:并(UNION)或复合查询(compound query). 使用场景: 在一个查询中,从不同的表返回结构数据; 对一个表执行多个查询,按一个查询返回数据; 多数情况下,组合相同的两个查询说完成的工作与具有多个WHERE子句条件的一个查询所完成的工作相同.换句话说,任何具有多个WHERE子句的SELECT语句,都可以作为一个组合查询.- 使用
- 使用比较简单,说要做的只是给出每条SELECT语句,在各条语句之间放上关键字UNION.
- 多数好的DBMS使用内部查询优化程序,在处理各条SELECT语句前组合他们,理论上,这意味着从性能上看,使用多条WHERE语还是UNION应该没有实际的差别.实践中,最好测试一下这两种方法.
- 规则
- UNION必须由两条以上的SELECT语句组成.
- UNION中的每个查询都必须包含相同的列,表达式或聚集函数(不过,各个列不需要以相同的次序列出).
- 列数据类型必须兼容: 类型不必完全相同,但是必须是DBMS可以隐含转换的类型.
- 返回规则
- UNION从查询结果集中自动去除了重复的行;换句话说,它的行为与一条SELECT语句中使用多个WHERE条件一样.
- 这个是UNION的默认行为,如果愿意也可以改变它.如果想返回所有的匹配行,可使用UNION ALL.
排序
UNION排序使用在最后一条SELECT 的ORDER BY规则.DBMS用它来排序所有SELECT语句返回结果.
操作多个表
实际上,UNION在需要组合多个表的数据时也很有用,即使是不匹配列明的表,在这种情况下,可以将UNION与别名组合,检索一个结果.
插入数据
INSERT插入(或添加)到数据库表
- 有几种方式:插入完整的行;插入行的一部分;插入某些查询的结果.
- 插入需要服务器DBMS中特定的权限.
- 插入时,加入列名和值,优点:即使表的结构改变,这条INSERT语句仍然可以工作.
- 不论使用那种INSERT语法,VALUES的数目都必须正确.如果,不提供列名,则必须给出每个列一个值.如果提供列名,则必须给列出的每个列一个值.
- 插入部分行:满足以下条件:1,该列定义为允许NULL值.2,在表定义中给出默认值.否则插入报错.
插入检索出的数据
利用SELECT语句的结果插入表中.INSERT SELECT.
例如:想把另一表中的顾客列合并到CUSTOMERS表中,可以使用如下方式: INSERT INTO Customers (cust_id,cust_contact,cust_email,cust_name,cust_address,cust_city,cust_state,cust_zip,cust_country) SELECT cust_id,cust_contact,cust_email,cust_name,cust_address,cust_city,cust_state,cust_zip,cust_country FROM CustNew; CustNew表的结构与Customers结构相同.DBMS并不关心返回的列名,它使用的是位置.SELECT可以包含WHERE子句,以过滤插入的数据.INSERT通常只插入一行.要插入多行,必须执行多个INSERT语句,但是INSERT SELECT 是个例外.可以用一条INSERT插入多行.
复制表内容
SELECT INTO 命令.将数据复制到一个新表(有的DBMS可以覆盖已经存在的表,这依赖于所使用的具体DBMS)
例如:SELECT * INTO CustCopy FROM Customers; 这条语句,创建一个名为CustCopy的新表,并且把整个Customers表的内容复制到新表中. 注意: 任何SELECT选项和子句都可以使用,包括WHERE和GROUP BY. 可以利用联结从多个表插入数据. 不管从多少个表中检索数据,数据都只能插入一个表中.
更新和删除数据
- 更新数据
- UPDATE进行更新
注意:不要忽略WHERE条件,因为稍不注意就会更新表中的所有行.
UPDATE table SET aa=bb WHERE xxx
- UPDATE进行更新
- 删除数据
- DELETE进行删除.
- 外键强关联时,删除其中一个时就会导致另一个报错.
DELETE FROM table WHERE aa=bb
- 指导原则
- 除非确实打算更新和删除每一行,否则绝对不要使用不带WHERE子句语句.
- 保证每个表都有主键.
- 使用UPDATE和DELETE之前,先用SELECT语句进行测试,确保它过滤的是正确的记录,以防编写的WHERE子句不正确.
创建和操纵表
- 创建
- CREATE TABLE table_name
- 创建新表时,指定的表名必须不存在,否则会出错.防止意外覆盖现有的表,SQL 首先要求删除该表.
- 使用DEFAULT 设置默认值.
- 更新表
ALERT TABLE .. - 删除表
DROP TABLE …
使用视图
- 视图
- 视图是虚拟的表.与包含数据的表不一样,视图只包含使用时动态检索数据的查询.
- MySQL从版本5开始支持视图.
为何使用视图
- 所有的DBMS一致地支持视图创建语法.
- 重用SQL语句.
- 简化复杂的SQL操作.在编写查询后,可以方便地重用它而不必知道其基本查询细节.
- 使用的表的一部分而不是整个表.
- 保护数据.可以授予用户访问表的特定部分的权限,而不是整个表的访问权限.
- 更改数据格式和表示.视图可返回与底层表的表示和格式不同的数据.
- 创建视图之后,可以用表基本相同的方式使用它们.可以对视图执行SELECT操作,过滤和排序数据,将视图联结到其他视图或表,甚至添加和更新数据.
重要的是,要知道视图仅仅是用来查看存储在别处数据的一种设施.视图本身不包含数据,因此,返回的数据是从其他表中检索出来的.在添加或更改这些表中的数据是,视图将返回改变过的数据.
注意:性能问题 因为视图不包含数据,所以每次使用视图时,都必须处理查询执行时需要的所有检索.如果你用多个联结和过滤创建了复杂的视图或者嵌套了视图,性能可能下降的很厉害.因此,在部署大量视图的应用前,应该进行测试.
- 视图的规则和限制
- 与表一样,视图必须唯一命名(不能给视图取与别的视图或表相同的名字)
- 对于可以创建的视图数目没有限制.
- 视图允许嵌套,即可以利用从其他视图中检索数据的查询来构造视图.性能影响很大.
- 视图不能索引,也不能有关联的触发器和默认值.
- 创建视图
- 使用CREATE VIEW 语句来创建视图.CREATE VIEW 只能用来创建不存在的视图.
- CREATE VIEW users AS SELECT * FROM statistics_user
- 视图重命名: 先删除 DROP VIEW name ,然后再重新创建.
DROP VIEW users;
- 通常使用
- 常见的应用是隐藏复杂的SQL,这通常涉及联结.
- 用视图重新格式化检索出的数据.
使用存储过程
- 什么是存储过程
- 简单的说,就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法;
- 有输入输出参数,可以声明变量,有if/else, case,while等控制语句,通过编写存储过程,可以实现复杂的逻辑功能;
- 函数的普遍特性:模块化,封装,代码复用;
- 速度快,只有首次执行需经过编译和优化步骤,后续被调用可以直接执行,省去以上步骤;
- 背景
- 经常需要有一些复杂的操作需要多条语句才能完成.
例如: 为了处理订单,必须核对以保证库存中有响应的物品.
如果物品有库存,需要预订,不再出售给别的人,并且减少物品数据以反映正确的库存量
库存中没有的物品需要订购,这需要与供应商进行某种交互.
关于哪些物品入库(并且可以立即发货)和哪些物品退订,需要通知相应的顾客.
执行这些处理需要针对许多表的多条SQL语句.此外,需要执行的具体SQL语句及其次序也不是固定的.如何编写SQL.
可以创建存储过程.简单来说,存储过程就是为以后使用而保存的一条或多条SQL语句.可将其视为批处文件,虽然它们的作用不仅限于批处理.
- 经常需要有一些复杂的操作需要多条语句才能完成.
- 支持
- Microsoft Access 和SQLite 不支持存储过程.MySQL 5 已经支持,早起的MySQL版本并不支持.
为何使用存储过程
- 通过把处理封装在一个易用的单元中,可以简化复杂操作.
- 由于不要求反复建立一系列处理步骤.因而保证了数据的一致性.如果所有开发人员和应用程序都使用同一存储过程,则所使用的代码都是相同的.这样能够防止错误.保证了数据的一致性.
- 简化对变动的管理.如果表名,列明或业务逻辑有变化,那么只需要更改存储过程的代码.使用的人不需要知道这些变化.这样就是提高了安全性.通过存储过程限制对基础数据的访问,减少了数据讹误的机会.
- 因为存储过程通常以编译过的形式存储,所以DBMS处理命令的工作较少,提高了性能.
存在一些只能用单个请求的SQL元素和特性,存储过程可以使用它们来编写功能更为灵活的代码.
缺点:不同DBMS中的存储过程语法有所不同.编写可移植的存储过程几乎是不可能的.
- 执行存储过程
- 执行EXECUTE. 接受存储过程名和需要传递给它的任何参数.
创建存储过程
- 百度MySQL的存储过程DEMO.
调用存储过程关键字: call
-- ---------------------------- -- Procedure structure for `proc_adder` -- ---------------------------- DROP PROCEDURE IF EXISTS `proc_adder`; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_adder`(IN a int, IN b int, OUT sum int) BEGIN DECLARE c int; if a is null then set a = 0; end if; if b is null then set b = 0; end if; set sum = a + b; END ;; DELIMITER ; 调用方式: set @a = 12; set @b = 42; call proc_adder(@a,@b,@s); select @s as sum ; 结果为:54.传入小数类型,会直接省去小数.可以申明方法入参和出参为float或者double类型,可以使用带小数. 但是经过一些测试:发现有一些特点:以数字开头的字符串可以相加.相加的数字长度直到出现非数字为止.double 类型的会出现精度丢失问题. DROP PROCEDURE IF EXISTS `proc_adder`; DELIMITER ;; CREATE PROCEDURE `proc_adder`(IN a double, IN b double, OUT sum double) BEGIN #Routine body goes here... DECLARE c int; if a is null then set a = 0; end if; if b is null then set b = 0; end if; set sum = a + b; END ;; DELIMITER ; set @a = '12.3'; set @b = '42.22'; call proc_adder(@a,@b,@s); select @s as sum ; 结果为: 54.519999999999996 如上结果,改为decimal类型,可以避免出现这种精度丢失问题. DROP PROCEDURE IF EXISTS `proc_adder`; DELIMITER ;; CREATE PROCEDURE `proc_adder`(IN a decimal(24,2), IN b decimal(24,2), OUT sum decimal(24,2)) BEGIN #Routine body goes here... DECLARE c int; if a is null then set a = 0; end if; if b is null then set b = 0; end if; set sum = a + b; END ;; DELIMITER ; set @a = '12.3'; set @b = '42.22'; call proc_adder(@a,@b,@s); select @s as sum ; 结果为: 54.52 同样有其他if语法,循环语法,case语法,语法类似shell语法.如下网页: https://www.cnblogs.com/chenpi/p/5136483.html
弊端
- 不同数据库,语法差别很大,移植困难,换了数据库,需要重新编写;不好管理,把过多业务逻辑写在存储过程不好维护,不利于分层管理,容易混乱,一般存储过程适用于个别对性能要求较高的业务,其它的必要性不是很大;
管理事物处理
- 事物处理
- 通过确保成批的SQL操作要么完全执行,要么完全不执行,来维护数据库的完整性.
- 事物:指一组SQL语句.
- 回退:指撤销指定SQL语句的过程.
- 提交:指将未存储的SQL语句结果写入数据库表.
- 保留点:指事物处理中设置的临时占位符,可以对它发布回退(与回退整个事物处理不同).
- 回退作用范围
- 事物用来管理INSERT ,UPDATE 和DELETE语句.不能回退SELECT(也没必要),也不能回退CREATE 或DROP 操作.事物中可以处理这些语句,但进行回退时,这些操作也不能撤销.
- 控制事物处理
- 不同的DBMS会有不同的语法.管理事物的关键在于将SQL语句组分解为逻辑块,并明确规定数据何时应该回退,何时不应该回退.
- 使用保留点
- MYSQL,Oracle,MariaDB中创建占位符,可以使用SAVEPOINT 语句.
- 保留点越多越好,就能够越灵活地进行回退.
- SAVE TRANSACTION
游标
- 定义
- 游标是一个存储在DBMS服务器上的数据库查询,它不是一条SELECT语句,而是被该语句检索出来的结果集.在存储了游标之后,应用程序可以根据需要滚动或浏览其中数据.
- 特性
- 能够标记游标为只读,使数据能读取,但不能更新和删除.
- 能控制可以执行的定向操作(向前,向后,第一,最后,绝对位置,相对位置)
- 能标记某些列为可编辑的,某些列为不可编辑的.
- 指示DBMS对检索出的数据进行复制,是数据在游标打开和访问期间不变化.
- 游标主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或做出更改.
- 游标对基于Web的应用用处不大.
使用
使用前必须声明它.一旦声明就必须打开游标以供使用.对于填有数据的游标,根据需要取出各行.在结束游标使用时,必须关闭游标,释放游标.
DECLARE CustCursor CURSOR FOR SELECT * FROM Customers WHERE cust_email is null
打开:
OPEN CURSOR CustCursor
检索:
FETCH CustCursor INTO CustRecord
FETCH检索当前行,自动从第一行开始.
关闭:
CLOSE CustCursor;
高级SQL特性
约束
- 主键:特殊的约束,保证一列中的值是唯一的,而且永不改动. PRIMARY KEY.
- 外键:外键是表中的一列,其值必须列在另一表的主键中.外键是保证引用完整性的极其重要部分. REFERENCES 表 主键 来关联.
- 唯一约束:用来保证一列中的数据是唯一的.类似主键.区别为:同表仅有一个主键,但多个唯一约束;可包含Null值;可以修改和更新;可重复使用;不能作为外键. UNIQUE .
检查约束:用来保证一列(或一组列)中的数据满足一组指定的条件.常用:
检测最大或最小值.例如:防止0个物品的订单; 指定范围.例如:保证发货日期大于等于今天的日期,但不超过今天起一年后的日期. 只允许特定的值.例如:在性别字段中只允许M或F. 添加: CHECK( 列名 > 0 ) ,或 CHECK (gender LIKE '[MF]') 有些DBMS支持自定义数据类型,其约束会被自动应用.
索引
- 索引用来排序数据以加快搜索和排序操作的速度.
- 特点:索引改善检索操作的性能,但降低了数据插入,修改和删除的性能.在执行这些操作时,DBMS必须动态地更新索引.
- 索引数据可能要占用大量的存储空间.
- 并非所有数据都适合做索引.取值不多的数据不如更多可能值的数据能通过索引得到那么多好处.
- 索引用户数据过滤和数据排序.如果你经常以某种特定的顺序排序数据,则该数据可能适合做索引.
- 可以在索引中定义多个列.(例如:州加上城市,这样的索引仅在以州加城市的顺序排序时有用,如果想按城市排序,则这种索引没有用处).
索引使用 CREATE INDEX 语句创建.
CREATE INDEX prod_name_ind ON PRODUCTS (prod_name);索引必须唯一命名.这里的索引名 prod_name_ind 在关键字 CREATE INDEX 之后定义. ON 用来指定被索引的表,而索引中包含的列在表后的圆括号中给出.
索引的效率随着表数据的增加或改变而变化.最好定期检查索引,并根据需要对索引进行调整.
触发器
- 触发器是特殊的存储过程,它在特定的数据库活动发生时自动执行.可以与特定表上的INSERT,UPDATE,DELETE操作(或组合)相关联.
- 触发器与单个的表相关联.与Orders表上的INSERT操作相关联的触发器只在Orders表中插入行时执行.类似的,Customers 表上的INSERT 和 UPDATE 操作的触发器只在表上出现这些操作时执行.
- 触发器内的代码具有以下数据的访问权:
- INSERT操作中的所有新数据;
- UPDATE操作中的所有新数据和旧数据;
- DELETE操作中删除的数据.
- 根据DBMS的不同,触发器可以在特定操作执行之前和执行之后执行.
常见用途:
- 保证数据一致.例如:在INSERT 或 UPDATE 操作中将所有州名换为大写.
- 基于某个表的变动在其他表上执行活动.例如:每当更新或删除一行时将审计跟踪记录写入某个日志表.
- 进行额外的验证并根据需要回退数据.保证某个顾客的可用资金不超限定,如果已经超出,则阻塞插入.
计算计算列的值或更新时间戳.
SQL SERVERT 版本
CREATE TRIGGER customer_state ON Customer FOR INSERT,UPDATE AS UPDATE Customers SET cust_state = Upper(cust_state) WHERE Customers.cust_id = inserted.cust_id
一般来说,约束的处理比出发器更快,因此,在可能的时候,应该尽量时候约束.
- 数据库安全
- 一般来说,需要保护的操作有:
- 对数据库管理功能(创建表,更改或删除已存在的表等)的访问.
- 对特定数据库或表的访问.
- 访问的类型(只读,对特定列的访问等)
- 创建多层次的安全措施,从而允许多种基于登录的访问和控制.
- 限制管理用户帐号的能力.
- 安全性使用SQL的GRANT 和 REVOKE 语句来管理,不过,大多数DBMS提供了交互式的管理实用程序,这些实用程序内部使用GRANT 和 REVOKE 语句.