电玩城打鱼捕鱼-专业24小时上下分

2008从入门到精通,数据存储

十二月 26th, 2019  |  电玩城上下分数据库

约束

图片 1 

iOS应用数据存储的常用方式

主关键字约束(Primary Key Constraint)

用来指定表中的一列或几列组合的值在表中具有唯一性。建立主键的目的是让外键来引用。

from Database Design to Physical Form

1. Plist存储(属性列表)

  • Plist存储(Documents)

// 1.Plist存储(生成plist文件)
// 在Plist文件中不能保存自定义对象*+
- (IBAction)saveBtn:(UIButton *)sender {
    // 参数:搜索的目录,搜索的范围,是否展开路径
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    NSLog(@"%@",path);

    // 1.把数组保存到沙盒
    NSArray *dataArray = @[@"LN",@10];
    NSString *filePath = [path stringByAppendingPathComponent:@"data.plist"];
    NSLog(@"%@",filePath);

    // 写入沙盒路径
    [dataArray writeToFile:filePath atomically:YES];

    // 2.把字典保存到沙盒
    NSDictionary *dict = @{@"name":@"LN",@"age":@10};
    NSString *dictPath = [path stringByAppendingPathComponent:@"dict.plist"];
    [dict writeToFile:dictPath atomically:YES];
}
  • Plist提取
  • 特点: 只能存储系统自带的数据类型, 比如NSDictory, NSArray等等.
    自定义的对象无法存储

// 2.Plist提取
- (IBAction)readBtn:(UIButton *)sender {
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    NSString *filePath = [path stringByAppendingPathComponent:@"data.plist"];
    NSArray *dataArray = [NSArray arrayWithContentsOfFile:filePath];
    NSLog(@"%@",dataArray);

    NSString *filePath1 = [path stringByAppendingPathComponent:@"dict.plist"];
    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath1];
    NSLog(@"%@",dict);
}
Primary Key的创建方式

在创建表时创建Primary Key

CREATE TABLE table1(
    t_id VARCHAR(12) ,
    t_name VARCHAR(20),
    t_phone VARCHAR(20),
    CONSTRAINT t_idss PRIMARY KEY(t_id)
);

对t_id列创建主键,约束名为t_idss。

CREATE TABLE

2. preference(偏好设置)

  • 特点: 本质就是一个plist文件; 也是只能存储系统自带的数据类型,
    自定义的对象无法存储

  • NSUserDefaults:
    用来保存应用程序设置和属性、用户保存的数据。用户再次打开程序或开机后这些数据仍然存在。

  • NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。如果要存储其他类型,则需要转换为前
    面的类型(一般转换成NSData),才能用NSUserDefaults存储。

  • 偏好设置存储(Library/Preferences)

#define LNname @"name"
#define LNage @"age"

// 1.偏好设置存储(key存取,最好定义成宏以防写错)
// 偏好设置不能保存自定义对象*+
- (IBAction)saveBtn:(UIButton *)sender {
    // NSUserDefaults保存也是plist文件
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:@"LN" forKey:LNname];
    [defaults setObject:@10 forKey:LNage];

    // 写入文件当中
    [defaults synchronize];
    NSLog(@"%@",NSHomeDirectory());
}
  • 偏好设置提取

// 2.偏好设置提取
- (IBAction)readBtn:(UIButton *)sender {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *name = [defaults objectForKey:LNname];
    NSInteger age = [defaults integerForKeyLNage];

    NSLog(@"%@ %ld",name,age);
}
删除Primary Key
ALTER TABLE table1
DROP CONSTRAINT t_idss;

约束名与列名不一致,此处填写约束名

integrity constraints (完整性约束)

3. NSKeyedArchiver归档(NSCoding协议)

  • 特点: 可以存储自己定义的数据类型, 但是都是一次性的全数据操作

Person

//  Person.h
#import <Foundation/Foundation.h>
@class Dog;
@interface Person : NSObject<NSCoding>

@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, strong) Dog *dog;
@end

//  Person.m
#import "Person.h"
@implementation Person

// 归档存储会调用(在保存对象时要告诉保存对象那些属性)
- (void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeInt:self.age forKey:@"age"];
    [aCoder encodeObject:self.dog forKey:@"dog"];
}

// 归档提取(解析文件的时候)会调用,(告诉当前要解析文件当中哪些属性)
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    /*
        当只有遵守了NSCoding协议时,才有[super initWithCoder]
    @interface Person : NSObject (父类NSObject没有遵守NSCoding协议,继承UIView就可以)
    */
    if (self = [super init]) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.age = [aDecoder decodeIntForKey:@"age"];
        self.dog = [aDecoder decodeObjectForKey:@"dog"];
    }
    return self;
}
  • 归档存储(tmp,生成的文件不可以直接打开)

// 归档
// 保存自定义对象(模型类要遵守<NSCoding>协议)*+
- (IBAction)saveBtn:(UIButton *)sender {Person *person = [[Person alloc] init];
    person.name = @"LN";
    person.age = 10;

    Dog *dog = [[Dog alloc] init];
    dog.name = @"xiao Hui";
    person.dog = dog;

    // 获取沙盒目录
    NSString *tmpPath = NSTemporaryDirectory();
    NSString *filePath = [tmpPath stringByAppendingPathComponent:@"Person.data"];
    NSLog(@"%@",NSTemporaryDirectory());

    // 归档(archiveRootObject会调用encodeWithCoder:)
    [NSKeyedArchiver archiveRootObject:person toFile:filePath];
}
  • 归档提取

// 2.归档提取
- (IBAction)readBtn:(UIButton *)sender {
    // 获取沙盒目录
    NSString *tmpPath = NSTemporaryDirectory();
    NSString *filePath = [tmpPath stringByAppendingPathComponent:@"Person.data"];

    //归档提取 unarchiveObjectWithFile会调用initWithCoder:
    Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
    NSLog(@"%@--%@",person.name,person.dog.name);
}
  • 注意点
    initWithCoderawakeFromNib

//从xib当加载的时候 (是加载完毕时调用)
-(void)awakeFromNib{
    NSLog(@"awakeFromNib==%@",self.btn);
    // awakeFromNib==<UIButton: 0x7ffd08c1e450; frame = (100 153; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x7ffd08c1af60>>
}

//当解析一个文件的时候会调用initWithCoder (一开始加载Xib就调用)
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
    if(self = [super initWithCoder:aDecoder]){
        NSLog(@"initWithCoder==%@",self.btn);
        // initWithCoder==(null)
    }
    return self;
}
向已有表中添加Primary Key
ALTER TABLE table1
ADD CONSTRAINT t_idss
PRIMARY KEY(t_id);

CREATE VIEW

4. SQLite3

  • 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库

  • 数据库可以分为2大种类

    • 关系型数据库(主流):如,MySQL
    • 嵌入式/移动客户端 :如,SQLite 对象型数据库
  • 特点: 存储一些大批量的数据, 排序, 统计等操作

添加Primary Key的另一种示例
ALTER TABLE Products
ADD PRIMARY KEY(prod_id);

虽然上述代码运行没问题,查看表格设计也可以看到Primary
Key设置成功,但是在删除Primary Key操作时会提示:
消息3728,级别16,状态1,第1 行
‘prod_id’ 不是约束。
消息3727,级别16,状态0,第1 行
未能删除约束。请参阅前面的错误信息。
原因是添加Primary
Key语句中没有用CONSTRAINT指明约束名,系统自动生成了主键名和约束名,要先查看主键名和约束名,删除时填写的也是约束名。
这种情况的正确删除方法

ALTER TABLE Products
DROP CONSTRAINT CK__Products__prod_p__1A14E395;
ALTER TABLE Products
DROP CONSTRAINT PK__Products__56958AB222AA2996;

Security

什么是SQLite

  • SQLite是一款轻型的嵌入式数据库
  • 它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了
  • 它的处理速度比Mysql、PostgreSQL这两款著名的数据库都还快
多列组合添加主键约束
CREATE TABLE table1(
    t_id VARCHAR(12),
    s_id VARCHAR(20),
    score FLOAT,
    CONSTRAINT ts_id PRIMARY KEY(t_id,s_id)
);

The GRANT & REVOKE statements

如何存储数据到数据库

  • 数据库的存储结构和excel很像,以表(table)为单位
外关键字约束(Foreign Key Constraint)

定义了表之间的关系,用来维护两个表之间的一致性的关系。
在创建表时创建Foreign Key Constraint

CREATE TABLE table2(
    s_id VARCHAR(20),
    s_name VARCHAR(12),
    s_tellphone VARCHAR(11),
    s_address VARCHAR(20),
    CONSTRAINT PK_s_id PRIMARY KEY(s_id),
);--首先新建table2,设置s_id为主键

CREATE TABLE table1(
    t_id VARCHAR(12),
    s_id VARCHAR(20),
    score FLOAT,
    CONSTRAINT pk_ts_id PRIMARY KEY(t_id,s_id),--新建table1,对t_id和s_id设置联合主键,键名pk_ts_id
    CONSTRAINT fk_s_id FOREIGN KEY(s_id)--对s_id设置外键fk_s_id
    REFERENCES table2(s_id)--外键fk_s_id外键关联table2的列s_id
    ON DELETE CASCADE--设置在table1的s_id删除时table2的s_id同时删除
    ON UPDATE CASCADE--设置在table1的s_id更新时table2的s_id同时更新
);

注:对table1设置外键关联table2,在插入数据时需要先插入table2的数据,才能成功插入table1的数据。更改table2.s_id数据,table1.s_id数据也会自动改变。但是更改table1.s_id数据,执行时报外键冲突。总之对table1设置外键关联table2后,table1的数据跟着table2走,不能反着来。

添加和删除外键约束同主键。

Catalogs

数据库存储数据的步骤

  • 新建数据库文件
  • 新建一张表(table)
  • 添加多个字段(column,列,属性)
  • 添加多行记录(row,每行存放多个字段对应的值)

Navicat 是一套适用于MySQL,
SQLite等多个数据库系统地图形化数据库管理、报告以及监控的工具。具有高性能的、商业智能的、强大的备份功能

UNIQUE约束

除主键外另一种可以定义唯一约束的类型,允许空值。添加UNIQUE的方法同上,这里只简单举例。

USE test
GO
ALTER TABLE table2
ADD CONSTRAINT uk_s_tellphone
UNIQUE(s_tellphone);

Schemas

理论基础:

  • 表格组成: 行(记录)和列(属性)

  • “属性” 是用来标识这一列应该存放什么

  • “记录” 是用来存放一条数据

  • 属性类型

  • blob :二进制类型

  • integer : 整型

  • real : 浮点型

  • text :文本类型

null : 空

  • 主键

  • 主键(Primary Key,简称PK)用来唯一地标识某一条记录

例如t_student可以增加一个id字段作为主键,相当于人的身份证

  • 主键可以是一个字段或多个字段

    例如: 行和列

  • 主键的设计原则

    • 主键应当是对用户没有意义的
    • 永远也不要更新主键
    • 主键不应包含动态变化的数据
    • 主键应当由计算机自动生成
CHECK约束

分为表约束和列约束,用于限制字段值在某个范围。

Introduction

SQL语言简介

  • 特点:不区分大小写(比如数据库认为user和UsEr是一样的)
  • SQL中的常用关键字(注意:数据库中不可以使用关键字来命名表、字段)

select、insert、update、delete、from、create、where、desc、order、by、group、table、alter、view、index等等

  • SQL语句的种类

    • 数据定义语句(DDL:Data Definition Language)

    包括create和drop, Alert等操作,在数据库中创建新表或删除表(create
    table或 drop table)

  • 数据操作语句(DML:Data Manipulation Language)

    包括insert、delete、update等操作,上面的3种操作分别用于添加、修改、删除表中的数据

  • 数据查询语句(DQL:Data Query Language)

可以用于查询获得表中的数据,关键字select是DQL(也是所有SQL)用得最多的操作,其他DQL常用的关键字有where,order
by,group by和having

添加CHECK约束
ALTER TABLE table2
ADD sex CHAR(2);--在table表中添加sex,数据类型为CHAR,用来存放性别
GO
ALTER TABLE table2
ADD CONSTRAINT ck_sex CHECK(sex in('男','女'));

注:此时sex列数据类型不能是bit,如果填写bit,只能存储0和1,用CHECK约束限制结果为男和女就会报错。

  ->The DBA(数据库管理员) must begin by creating the tables
and constraints(约束) and loading the data. Impose(强加上) integrity constraints on the
columns 。

DDL语句

  • 创表

 格式
 create table 表名 (字段名1 字段类型1, 字段名2 字段类型2, …) ;
 示例

 create table t_student (id integer, name text, age inetger, score real) ;



 经验

 实际上SQLite是无类型的

 就算声明为integer类型,还是能存储字符串文本(主键除外)



 建表时声明啥类型或者不声明类型都可以,也就意味着创表语句可以这么写:



 create table t_student(name, age);



 为了保持良好的编程规范、方便程序员之间的交流,编写建表语句的时候最好加上每个字段的具体类型



 语句优化



 创建表格时, 最好加个表格是否已经存在的判断, 这个防止语句多次执行时发生错误



 create table if not exists 表名 (字段名1 字段类型1, 字段名2 字段类型2, …) ;
  • 删表

格式



 drop table 表名 ;



 drop table if exists 表名 ;



 示例



 drop table t_student ;



 语句优化



 删除表格时, 最好加个表格是否已经存在的判断, 这个防止语句多次执行时发生错误



 drop table if  exists 表名 ;
  • 修改表

注意: sqlite里面只能实现Alter Table的部分功能



 不能删除一列, 修改一个已经存在的列名



 修改表名



 ALTER TABLE 旧表名 RENAME TO 新表名



 新增属性



 ALTER TABLE 表名 ADD COLUMN 列名 数据类型 限定符
  • 约束

    • 简单约束

不能为空,not null :规定字段的值不能为null
不能重复,unique :规定字段的值必须唯一
默认值,default :指定字段的默认值

示例
`create table t_student (id integer, name text not null unique, age integer not null default 1) ;`

name字段不能为null,并且唯一
age字段不能为null,并且默认为1
  • 主键约束

添加主键约束的原因?
如果t_student表中就name和age两个字段,而且有些记录的name和age字段的值都一样时,那么就没法区分这些数据,造成数据库的记录不唯一,这样就不方便管理数据,良好的数据库编程规范应该要保证每条记录的唯一性,为此,增加了主键约束,也就是说,每张表都必须有一个主键,用来标识记录的唯一性

  • 主键的声明?

在创表的时候用primary key声明一个主键

create table t_student (id integer primary key, name text, age integer) ;

integer类型的id作为t_student表的主键

  • 主键字段

只要声明为primary key,就说明是一个主键字段

主键字段默认就包含了not null 和 unique 两个约束

如果想要让主键自动增长(必须是integer类型),应该增加autoincrement

create table t_student (id integer primary key autoincrement, name text, age integer) ;

在创建表的时候添加CHECK 约束
CREATE TABLE table3(
    t3_id VARCHAR(12),
    t3_name VARCHAR(20),
    t3_class VARCHAR(12),
    t3_type VARCHAR(12),
    CONSTRAINT ck_t3_type CHECK(t3_type in('类型1','类型2','类型3')) 
)

添加了约束后如果插入不符合约束的数据

INSERT INTO table3(
    t3_id,
    t3_name,
    t3_class,
    t3_type
)VALUES(
'2018038219',
'李建',
'社会与科学',
'任何数据'
);

消息547,级别16,状态0,第1 行
INSERT 语句与CHECK
约束”ck_t3_type”冲突。该冲突发生于数据库”test”,表”dbo.table3″, column
‘t3_type’。

语句已终止。

  ->Then provide views(视图) of the data, virtually
restructuring the physical tables into variant(不同的) table forms, to
simplify access to data.

DML语句

  • 插入数据(insert)

 格式



 insert into 表名 (字段1, 字段2, …) values (字段1的值, 字段2的值, …) ;



 示例



 insert into t_student (name, age) values (‘sz’, 10) ;



 注意



 数据库中的字符串内容应该用单引号 ’ 括住
  • 更新数据(update)

格式



 update 表名 set 字段1 = 字段1的值, 字段2 = 字段2的值, … ;



 示例



 update t_student set name = ‘wex’, age = 20 ;



 注意



 上面的示例会将t_student表中所有记录的name都改为wex,age都改为20
  • 删除数据(delete)

格式



 delete from 表名 ;



 示例



 delete from t_student ;



 注意



 上面的示例会将t_student表中所有记录都删掉
  • 条件语句

作用



 如果只想更新或者删除某些固定的记录,那就必须在DML语句后加上一些条件



 条件语句的常见格式



 where 字段 = 某个值 ;   // 不能用两个 =



 where 字段 is 某个值 ;   // is 相当于 =



 where 字段 != 某个值 ;



 where 字段 is not 某个值 ;   // is not 相当于 !=



 where 字段 > 某个值 ;



 where 字段1 = 某个值 and 字段2 > 某个值 ;  // and相当于C语言中的 &&



 where 字段1 = 某个值 or 字段2 = 某个值 ;  //  or 相当于C语言中的 ||
  • 条件语句练习

    示例

将t_student表中年龄大于10 并且 姓名不等于wex的记录,年龄都改为 5

删除t_student表中年龄小于等于10 或者 年龄大于30的记录

猜猜下面语句的作用

update t_student set score = age where name = ‘wex’ ;

删除CHECK约束
ALTER TABLE table3
DROP CONSTRAINT ck_t3_type;

  ->Provide security(安全性),
so that only authorized users are able to read or update certain
confidential(机密的) data.

DQL

格式



 select 字段1, 字段2, … from 表名 ;



 select * from 表名;   //  查询所有的字段



 示例



 select name, age from t_student ;



 select * from t_student ;



 select * from t_student where age > 10 ;  //  条件查询
DEFAULT约束

通过定义列的默认值或使用数据库的默认值对象绑定表列,来指定列的默认值。

  ->The structure of the various tables, views, and other objects
of a database are made available to the DBA through a set of
system-defined tables, called system
catalogs(系统目录).

查询相关语句

统计



 count(X)



 select count(*) from t_student



 select count(age) from t_student



 avg(X)



 计算某个字段的平均值



 sum(X)



 计算某个字段的总和



 max(X)



 计算某个字段的最大值



 min(X)



 计算某个字段的最小值



 排序



 查询出来的结果可以用order by进行排序



 select 字段1, 字段2 from 表名 order by 字段 ;



 select * from t_student order by age ;



 默认是按照升序排序(由小到大),也可以变为降序(由大到小)



 select * from t_student order by age desc ;  //降序



 select * from t_student order by age asc ;   // 升序(默认)



 也可以用多个字段进行排序



 select * from t_student order by age asc, height desc ;



 先按照年龄排序(升序),年龄相等就按照身高排序(降序)



 limit分页



 使用limit可以精确地控制查询结果的数量,比如每次只查询10条数据



 格式



 select * from 表名 limit 数值1, 数值2 ;



 示例



 select * from t_student limit 4, 8 ;



 可以理解为:跳过最前面4条语句,然后取8条记录



 分页



 limit常用来做分页查询,比如每页固定显示5条数据,那么应该这样取数据



 第1页:limit 0, 5



 第2页:limit 5, 5



 第3页:limit 10, 5



 第n页:limit 5*(n-1), 5



 特殊案例



 select * from t_student limit 7 ;



 相当于select * from t_student limit 0, 7 ;



 表示取最前面的7条记录
在建表时添加DEFAULT约束
CREATE TABLE table3(
    t3_id VARCHAR(12),
    t3_name VARCHAR(20),
    t3_class VARCHAR(12),
    t3_type VARCHAR(12) DEFAULT '类型1' 
)

 

多表查询

select 字段1, 字段2, … from 表名1, 表名2 ;



 别名



 select



 别名1.字段1 as 字段别名1,



 别名2.字段2 as 字段别名2,



 …



 from



 表名1 as 别名1,



 表名2 as 别名2 ;



 可以给表或者字段单独起别名



 as 可以省略



 表连接查询



 select 字段1, 字段2, … from 表名1, 表名2  where 表名1.id = 表名2.id;



 外键



 如果表A的主关键字是表B中的字段,则该字段称为表B的外键



 保持数据一致性,完整性,主要目的是控制存储在外键表中的数据。 使两张表形成关联,外键只能引用外表中的列的值或使用空值。



12-(掌握)代码实现SQLite-DDL



 1. 创建一个Swift项目



 2. 导入系统框架sqlite3.tbd(sqlite3.dylib)



 3. 建立桥接文件, 导入头文件sqlite3.h



 1. 新建一个.h 头文件



 2. 设置为桥接文件
删除DEFAULT约束
ALTER TABLE table3
DROP CONSTRAINT DF__table3__t3_type__3D5E1FD2;
--DF__table3__t3_type__3D5E1FD2是DEFAULT约束的约束名

Integrity(完整性)

代码实现

1. 打开数据库



 2. 使用打开的数据库, 执行DDL语句, 创建一个数据库表



 3.  使用打开的数据库, 执行DDL语句, 创建一个数据库表



 3. 将数据库操作封装成一个工具类



13-(掌握)代码实现DML语句-Insert



 1. 创建一个Student类



 属性



 name



 age



 构造方法



 init(name: String, age: Int)



 2. 创建数据库操作方法



 数据库中, 对Student对象的操作封装



 insertStudent()



14-(了解)代码实现DML语句-Insert绑定参数



 准备语句(prepared statement)对象



 准备语句(prepared statement)对象一个代表一个简单SQL语句对象的实例,这个对象通常被称为“准备语句”或者“编译好的SQL语句”或者就直接称为“语句”。



 操作历程



 1. 使用sqlite3_prepare_v2或相关的函数创建这个对象



 如果执行成功,则返回SQLITE_OK,否则返回一个错误码



 2. 使用sqlite3_bind_*()给宿主参数(host parameters)绑定值



 sqlite3_bind_text



 参数1:



 准备语句



 参数2:



 绑定的参数索引  (从1开始)



 参数3:



 绑定的参数内容



 参数4:



 绑定的参数长度  (-1代表自动计算长度)



 参数5:



 参数的处理方式



 SQLITE_TRANSIENT 会对字符串做一个 copy,SQLite 选择合适的机会释放



 SQLITE_STATIC / nil  把它当做全局静态变量, 不会字符串做任何处理,如果字符串被释放,保存到数据库的内容可能不正确!



 注意: swift中没有宏的概念



 // 替换 sqlite3.h 中的宏



 private let SQLITE_TRANSIENT = unsafeBitCast(-1, sqlite3_destructor_type.self)



 3.  通过调用sqlite3_step() 一次或多次来执行这个sql



 对于DML语句, 如果执行成功, 返回SQLITE_DONE



 对于DQL语句, 通过多次执行获取结果集, 继续执行的条件是返回值 SQLITE_ROW



 4.  使用sqlite3_reset()重置这个语句,然后回到第2步,这个过程做0次或多次



 5. 使用sqlite3_finalize()销毁这个对象, 防止内存泄露
添加约束不指定约束名
ALTER TABLE table3
ADD DEFAULT '类型2' FOR t3_type;
GO

  ->保证数据完整性(主要指数据的正确性与一致性)是数据库管理员的最重要任务之一。

DML语句-Insert插入数据优化

只要在执行多个SQL语句之前, 手动开启事务, 在执行完毕之后, 手动提交事务,
这样 再调用SQL方法执行语句时, 就不会再自动开启和提交事务

添加约束指定约束名
ALTER TABLE table3
ADD CONSTRAINT df_t3_type
DEFAULT '类型2' FOR t3_type;
GO

  ->可以通过约束(Constraint)、规则(Rule)或者缺省值保证数据的完整性,也可以在应用程序层保证数据完整性(这是应用程序设计的问题),或通过触发器保证。

事务

NOT NULL约束

约束字段值不为空。

  ->数据完整性类型包括:实体完整性、参照完整性和用户定义完整性  

5. Core Data

  • 特点: 对SQLite3的一层面向对象的包装,
    本质还是要转换成为对应的SQL语句去执行
建表时设置NOT NULL约束
CREATE TABLE table3(
    t3_id VARCHAR(12) NOT NULL,
    t3_name VARCHAR(20) NOT NULL,
    t3_class VARCHAR(12) NOT NULL,
    t3_type VARCHAR(12) NOT NULL 
)

    ->实体完整性(Entity Integrity)
:现实世界的实体是可区分的,即它们具有某种唯一性标识。相应地,关系模型中主键应作为唯一性标识。因此实体完整性规则规定基本关系的所有主键(Primary
Key)都不能取空值(NULL) 。

钥匙串

  • APP之间数据共享
  • 系统级别的加密, 安全性高
  • 当APP 被删除时, 存储的数据依然存在
为已存在的列添加NOT NULL约束
ALTER TABLE table3
ALTER COLUMN t3_type VARCHAR(12) NOT NULL;

   
 ->参照完整性(Referential Integrity)
:参照完整性维护表与表之间的相关性,通常用“主键(Primary
Key)/外键(Foreign Key)”保证,其中Foreign
Key可以取NULL值,或取其参照表中Primary Key或者候选键的取值。

删除NOT NULL约束
ALTER TABLE table3
ALTER COLUMN t3_type VARCHAR(12) NULL;
GO

    ->用户定义的完整性(User_defined
Integrity
):针对某一具体数据的约束条件,由应用环境决定。例如:某个属性具有缺省值、某个属性必须取惟一值(UNIQUE)、某个非主属性不能取NULL值、某个属性的取值范围在0~100之间(CHECK)等等。

自定义默认值对象维护数据完整性

CREATE DEFAULT date_today AS GETDATE();
--新建默认值对象名date_today,默认值为getdate()函数,获取当前日期
GO
EXEC sp_addtype date_time,'date','NULL';
--利用存储过程新建自定义数据类型date_time,参照系统数据类型date
GO
EXEC sp_bindefault 'date_today','date_time';
--将默认值对象date_today绑定到自定义数据类型date_time上
GO
CREATE TABLE table3(--新建table3,设置字段t3_date的数据类型为date_time
    t3_id VARCHAR(12),
    t3_name VARCHAR(20),
    t3_class VARCHAR(12),
    t3_type VARCHAR(12),
    t3_date date_time
);
GO
INSERT INTO table3(--为新建表table3插入一条数据,不指定t3_date的值,看默认值是否有效
    t3_id,
    t3_name,
    t3_class,
    t3_type
)VALUES(
'2018038220',
'李建',
'社会与科学',
'类型1'
);
GO
SELECT * FROM table3;--查询table3数据,看t3_date是否有默认值为当前日期

查询结果如下
图片 2

ALTER TABLE table3
ADD t3_date1 DATE;--在table3表中新增一列t3_date1,数据类型为DATE
GO
EXEC sp_bindefault 'date_today','table3.t3_date1';
--直接将默认值对象date_today绑定到table3的t3_date1列
GO
INSERT INTO table3(--为新建表table3插入一条数据,不指定t3_date和t3_date1的值,看默认值是否有效
    t3_id,
    t3_name,
    t3_class,
    t3_type
)VALUES(
'2018038221',
'李建',
'社会与科学',
'类型'
);
GO
SELECT * FROM table3;
GO

查询结果如下
图片 3

  ->数据完整性具体实现包括两类

存储过程查询默认值对象的所有者
USE test
EXEC sp_help date_today;
GO

结果如图所示
图片 4

    ->声明性数据完整性
:声明性数据完整性用约束(Constraint)、规则(Rule)
在数据库中提供保证,这是保证完整性的较好方法。它驻留在数据库内,编程简单,开销小,能更集中管理和保证数据的一致性

删除默认值对象
DROP DEFAULT date_today;

删除不成功,提示以下信息:
消息3716,级别16,状态3,第1 行
无法删除默认值’date_today’,因为它已绑定到一个或多个列。
那么我们知道,当一个默认值对象绑定了列之后,就无法删除它,如果想要删除,就必须先解绑。在上面的操作中,我们的默认值对象date_today绑定了test数据库table3表的t3_date1字段。

    ->过程性数据完整性
:过程性数据完整性用触发器和应用程序代码保证,通常较为复杂、开销较大,但可以执行更多的业务规则。
通常,过程性数据完整性是声明性数据完整性的补充

对列解绑默认值对象
USE test
GO
EXEC sp_unbindefault 'table3.t3_date1';

此时我们再次尝试删除默认值对象,发现还是不行,此时要注意,在上面的操作中,默认值对象date_today不止绑定了t3_date1列,还绑定了自定义数据类型date_time,并将该数据类型定义给了t3_date列,我们还需要对date_time解绑默认值对象。

EXEC sp_unbindefault 'date_time';

此时再次删除默认值对象,就可以成功删除。删除默认值对象后,原先绑定的字段不会再有默认值。

           图片 5

自定义规则维护数据完整性

规则是对列或自定义数据类型的值的规定和限制。自定义规则的表达式一定要返回布尔类型的值,并且表达式中不能包含多个变量。

CREATE RULE score_rule AS @math_score>=0;
GO--新建规则score_rule,参数@math_score
EXEC sp_addtype 'score_type','float','NULL';
GO--新建自定义数据类型score_type
CREATE TABLE table_score(--新建表table_score,预设mt_score和at_score字段用于绑定规则
s_id VARCHAR(4),
s_name VARCHAR(10),
mt_score float,--该字段将用于规则score_rule绑定到列
at_score score_type--该字段将用于规则score_rule绑定到自定义数据类型
);
GO
EXEC sp_bindrule 'score_rule','score_type';
GO--将score_rule规则绑定到自定义数据类型score_type
EXEC sp_bindrule 'score_rule','table_score.mt_score';
GO--将score_rule规则绑定到table_score表的mt_score列

----以下进行规则测试
INSERT INTO table_score(
s_id,
s_name,
mt_score,
at_score
)VALUES(
'0001',
'张华',
'-1',
'-1'
);
GO

进行违反规则的插入后,数据库报错
消息513,级别16,状态0,第1 行
列的插入或更新与先前的CREATE RULE
语句所指定的规则发生冲突。该语句已终止。冲突发生于数据库’test’,表’dbo.table_score’,列’mt_score’。

语句已终止。
很明显,mt_score的插入值为-1,违反了必须大于等于0的规则,数据库报错。将mt_score的插入值改成符合规则的数据,再次运行插入语句,数据库依然会报错,因为at_score字段的插入值也是违反规则的。将两个数据改成符合规则的返回,执行成功。

注:新建规则时表达式一定要是返回布尔类型的值,否则会报错

消息4145,级别15,状态1,过程sum_score,第1 行
在应使用条件的上下文(在’;’ 附近)中指定了非布尔类型的表达式。

                 图片 6

删除自定义规则

和自定义默认值对象一样,删除自定义规则要求该规则先与字段和自定义数据类型解绑。在上面的操作中,score_rule规则与自定义数据类型score_type以及列mt_score已绑定。因此执行以下语句:

EXEC sp_unbindrule 'score_type';
GO--解除规则score_rule与score_type之间的绑定
EXEC sp_unbindrule 'table_score.mt_score';
GO--解除规则score_rule与表table_score的mt_score列的绑定
DROP RULE score_rule;--删除score_rule规则

注:经过试验,一个列只能绑定1条规则,如果对一个列绑定2条规则,前一条规则会被后一条规则顶替。

           

查看自定义规则
EXEC sp_help 'score_rule';

结果如图所示
图片 7

-》》》完整性再阐述

查看自定义规则的定义信息
EXEC sp_helptext 'score_rule';
GO

结果如图所示
图片 8

     数据有着复杂的数据类型,用来满足不同的需求。实际应用中的数据也有着一定的取值范围,如年龄不小于0,性别只有男女等。而表之间的联系使相连的字段要保持一致和完整。但是,实际操作无法保证插入和删除的数据都符合要求,不符合要求的操作极可能会破坏数据的完整性,对数据库的可靠性和运行能力造成威胁。

因此存放数据集的数据库必须要对数据表和列有所限制和规范,为此SQLServer系统使用一系列的方法来维护数据完整性。

标签:, ,

Your Comments

近期评论

    功能


    网站地图xml地图