数据库完整性
类型
有四种数据库完整性约束的分类。
注:这部分参考https://blog.csdn.net/bzhxuexi/article/details/43671251
实体完整性
用来确保数据库中一个特定实体的记录唯一。
具体来说有以下约束方法:
约束方法 | 功能描述 |
---|---|
primary key 主键约束 | 唯一识别数据库每一行的主键标志,可以包含多个列 |
identity 自增约束 | 指明一个列是由数据库自增序号生成,不能手动插入值 |
unique 唯一约束 | 确保列的值在每一行中都不同,没有重复值(null除外) |
域完整性
域完整性是用来规定列的数据应该满足什么样的取值范围的,确保插入和修改的数据合理。
约束方法 | 功能描述 |
---|---|
check 检查约束 | 用来限定列值的取值范围 |
foreign key 外键约束 | 指明列中的值是参考其他表的主键取值,而不能随意取值 |
default 默认值约束 | 如果没有指定值,插入时给改列赋值为默认值 |
not null 非空约束 | 强制指明该列不接受空值 |
参照完整性
又叫做“引用完整性”,指的是:如果一张表的主键作为另一张表的外键出现,那么外键的取值只能和主键保持一致,或者为null,而不能随意取其他值。
参照完整性约束实现的方式是通过外键约束来规定。
用户自定义完整性
特别应用情境下,用户可以根据需要自定义一些完整性规则。
完整性具体实现方式
可以在创建表的时候,为创建的语句加入列约束和表约束,来实现数据库完整性的规定。
列约束是指,在申明列的时候就在后面顺带写上对这个列内值的约束。可以使用的约束方法包括:主键、外键、唯一、检查、默认、非空、自增。
表约束则是在声明了所有列后,单独增加的约束语句,此时必须要指定约束的列名。可以使用的约束方法包括:主键、外键、唯一、检查。
不管是写列约束还是表约束,都可以选择性加一个constraint <约束名>
来指定一个约束的名字,这样方便创建之后对约束内容进行更改。
下面来说一下实现各种约束方法具体的SQL语句该怎么写。
主键约束
如果以列约束的方式去写,只需要在列声明后面写[constraint <约束名>] primary key
就可以指定一个列为主键列。(方括号表示可选)
如果是写成表约束,则可以指定多个列为主键。写法为 [constraint <约束名>] primary key(col1, col2 ...)
唯一约束
和主键约束一样的,改成unique
就行了。一个表中可以有多个唯一约束,但只能有一个主键约束。
外键约束
列约束的方式可以写成[constraint <约束名>] REFERENCES <父表名>[(<属性名>)]
,而表约束中要多指明列名:[constraint <约束名>] foreign key (<列名>) REFERENCES <父表名>[(<属性名>)]
。注意参考表的属性名是可选的,一般要参考主键列。
另外,SQL还对违反参照完整性约束的行为制定了三种策略:
- restrict,严格。如果有违反完整性的行为就拒绝。默认是这种。
- cascade,级联。如果有违反的行为影响了被参照表的主键,就把这种影响扩散到参照它的表中。比如删除了被参照表中的一个行,就会级联地删除参照它的表中对应外键的行。
- set null,置空。把被参照表中的一个行删除后,参照它的表中相同的外键被设置为null
可以通过on delete
或者on update
来指定触发处理策略的行为。比如on delete cascade
表示删除是使用级联策略。
直接在外键约束后面加上策略方式就可以应用。比如foreign key (cid) on delete set null
检查约束
[constraint <约束名>] check(<检查条件表达式>)
即可,不满足表达式(表达式计算结果为false)的插入和修改行为将被拒绝。如果以表约束来写,可以涉及多个列。
默认约束
只能写在列后面,表示这个列的默认值(缺省值)。
[constraint <约束名>] default <值>
非空约束
在列后面写上not null
即可
自增约束
在列后面写上identity(<起始值>,<增量>)
。如果不写起始值和增量,默认都是1,也就是表中每增加一个行,自动给该行的这个列分配一个上次+1的值。
修改表
可以使用alter table
语句来改变列和约束。
列的操作:
- add 添加
- drop 删除
- modify 更改
约束的操作:
- add 添加
- drop 删除
数据库触发器
CREATE TRIGGER trigger_name {BEFORE|AFTER}
{INSERT|DELETE|UPDATE [OF col1, col2...]}
ON table_name
[FOR EACH ROW|FOR EACH STATEMENT]
[WHEN (searching condition)]
BEGIN
{...statement...}
END
第一行的before和after指定触发的时机实在事件发生之前还是之后,第二行是触发条件,第三行是指定作用在哪个表,第四行可以选择指定粒度(每个被牵连的行触发一次还是一个sql语句触发一次),第五行可以指定额外的条件,然后begin和end中间指定要做的事。
用SELECT name FROM sqlite_master WHERE type = 'trigger';
可以列出数据库所有触发器。而DROP TRIGGER trigger_name;
语句用来删除触发器。
视图
视图就是将查询的结果集可视化的表,所以和表有着很多重合的用法。
视图是虚拟的,也就是说如果依赖的表发生变化,则视图也会变;如果对可更新视图进行修改,则表内容也会被修改。
创建、查看和删除
使用create view <view_name> as <查询语句>
的方法就可以根据查询结果创建一个视图,也可以在as前面加上一些列名,给视图的列重命名。当查询中涉及到重名的列时,则必须给列重命名,否则会创建失败。
在查询语句的后面加上with check option
可以给视图绑定上和查询中where后面一样的检查条件,这样就禁止了向视图中插入非法的行的行为。
select view_name from user_views;
可以像表一样查询视图。
可以使用describe {view_name|table_name}
来查看视图状态。
drop view view_name
可以删除视图。如果后面加上cascade
则表示级联删除,就是说如果这个视图上嵌套有其他视图,则一并删除。如果加上restrict
(默认情况),就不允许删除还存在嵌套视图的视图。
可更新视图和只读视图
如果一个视图内容来自多个表,则一定是只读的。如果在创建时视图的时候用了group by
语句,则也只读。
更新视图实际上是在间接更新表中的数据,所以有时候有些列允许通过视图更新,有些不允许。可以通过select column_name, updatable from user_updatable_columns where table_name ="AGENTORDERS"
展示可更新的列。
安全性和权限
通过grant
语句来给用户赋予权限:
grant <权限名...>
on [table] table_name | view_name
to <用户名...>
[with grant option]
如果加上最后一句with grant option
则表示得到权限的用户也可以把自己拥有的权限再赋予其他人。
常用的权限有select、delete、insert、update(后面可以写列名)、references等。update后面指定列名表示仅允许对一些列进行修改。
通过revoke
语句来撤销权限。