第二章 Senior进阶 数据库

第二章 Senior进阶 数据库

一、数据库管理系统
1.SQL:SQL是Structured Query Language(结构化查询语言)的缩写。SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言。
2.常见的数据库“
    1.My SQL:MySQL是一个精巧的SQL数据库管理系统,而且是开源的数据管理系统。MySQL主要目标是快速、健壮和易用。由于它的强大功能、灵活性、丰富的应用编程接口(API)以及精巧的系统结构,受到了广大自由软件爱好者甚至是商业软件用户的青睐
    2.Oracle:Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。系统可移植性好、使用方便、功能强。
3.数据库的好处(特征):
    1.以一定方式存储在一起
    2.能为多个用户共享
    3.具有尽可能少的冗余代码
    4.与程序彼此独立的数据集合
4.数据库
    1.定义:数据库(Database)是按照数据结构来组织、存储和管理数据的仓库
    2.分类:关系型数据库(主流)、对象型数据库、层次式数据库、网格式数据库
    3.常用的关系型数据库
        PC端:Oracle、MySQL、SQL Server、Access、DB2、Sybase
        嵌入式\移动客户端:SQLite
5.SQLite(http://www.sqlite.org/doc.html)是一个轻量级的关系数据库。SQLite最初的设计目标是用于嵌入式系统,它占用资源非常少,在嵌入式设备中,只需要几百k的内容就够了,目前应用于Android、iOS等智能手机。iOS使用SQLite时,只需加入libsqlite3.0.tbd以及引入sqlite3.h头文件即可。
6.表:是数据库中一个非常重要的对象,是其他对象的基础。根据信息的分类情况,一个数据库中可能包含若干个数据表
7.字段:标的“列”称为“字段”,每一个字段包含某一个专题的信息。用来标识本列数据类型
8.记录:是指对应于数据表中一行信息的一组完整的相关信息。用来表示表中一行的信息
二、SQL语句
1.SQLite是无类型的数据库,可以保存任何类型的数据,对于SQLite来说对字段不指定类型是完全有效的(==注:良好的编程习惯应该要为字段标注类型==)
2.SQLite近似类型规则
    为了使SQLite和其他数据库间的兼容性最大化,sqlite支持“类型近似”的观点,列的类型近似指的是存储在列上的数据的推荐类型
    1.如果类型字符串中包含“INT”,那么该字段的亲缘类型是INTEGER。
    2.如果类型字符串中包含“CHAR”、“CLOB”或者“TEXT”,那么该字段的亲缘类型是TEXT,如VARCHAR。
    3.如果类型字符串中包含“BLOB”。那么该字段的亲缘类型是NONE。
    4.如果类型字符串中包含“REAL”、“FLOA”或“DOUB”,那么该字段的亲缘类型是REAL
    5.其余情况下、字段的亲缘类型为NUMERIC。
3.SQLite的字段约束条件
    NOT NULL -- 非空       该字段数据不能为空
    UNIQUE ----唯一        该字段数据不能重复
    PRIMARY KEY ---主键    用于唯一标识一条数据
    FOREIGN KEY ---外键    该字段作为另一个表的主键,联表查询
    CHECK --- 条件检查,确保一列中的所有值满足一定条件   该字段数据必须满足一定条件
    DWDAULT ---- 默认      该字段数据可以给定默认值
    AUTOINCREATEMENT --- 自增型变量   该字段数据如果为整型可以自动加1
4.SQLite字段约束条件:PRIMARY KEY -- 主键
    首先,数据表中每一条记录都有一个主键,这就像我们每个人的身份证号码、员工号、银行账号;反过来说,每一个主键对应着一条数据记录,所以,主键必须是唯一的
    其次,一般情况下注键同时也是也是一个索引,所以通过逐渐查找记录速度比较快
    第三,在关系型数据库中,一个表的主键可以作为另一个标的外键,这样,这两个表之间就通过这个键建立了关系
    最后,逐渐一般是整数或者字符串,只要保证唯一就行。在SQLite中,主键如果是整数类型,该列的值可以自动增长
5.SQL语句:
    1.建表命令(Create table)
        create table if not exists 表名 (字段1 约束1 约束2····,字段2 约束1 约束2,····);
    2.数据插入命令(Insert)
        insert into 表名 (字段1,字段2,···) values (字段1值,字段2值,···);
        注意:要插入的数据要和字段顺序相同
    3.数据库更新命令(Update)
        update 表名 set 字段名1 = 修改值1,字段名2 = 修改值2,···· where 条件;
        注意:关键字 update set
              条件可以有一个或多个。多个条件使用and(与),or(或)连接
    4.数据库删除命令(Delete
        delete from 表名 where 条件;
    5.数据库检索命令(Select)
        select 要查找的字段 form 表名 where 条件
        注意:要查找的字段,如果查找所有字段可以使用通配符 * 
三、iOS的数据库技术实现
1.Linux系统级的SQLite技术实现框架
    Xcode 6 中libsqlite3.0.dylib
    Xcode 7 中libsqlite3.0.tbd
2.使用SQLite数据库的流程
    1.引入<sqlite3.h>头文件
        //包含了sqlite数据库操作所需要的所有函数
        #import <sqlite3.h> 
    2.在.m文件中声明一个sqlite3的属性
        //数据库句柄 这个属性相当于数据库的对象
        sqlite3* sqliteHandle;
    3.创建数据库文件将要存储的文件路径
        - (NSString*)dbPath{
            NSString* documentsPathString = [[SandBoxPaths documentsPath] stringByAppendingPathComponent:@"textDB.sqlite"];
            return documentsPathString;
        }
    4.打开数据库
        - (void)createDataBase{
           //创建数据库文件的函数,如果数据库文件存在,那么这个方法就是打开数据库文件,如果数据库不文件存在,这个方法就是创建数据库文件,再打开
           //第一个参数:数据库文件的路径,并且需要将其转换为char * 类型(是C语言的字符串类型)
           //第二个参数:数据库文件的句柄,取地址  &(and) 符号就是取地址
           //将数据库句柄指向数据库内存,我们对数据库的操作,都是通过句柄来完成的
           int result =  sqlite3_open([self dbPath].UTF8String, & sqliteHandle);
           if(result == SQLITE_OK){
               NSLog(@"数据库打开成功");
           }else{
               NSLog(@"数据库打开失败 --- %d",result);
            }
        }
    3.执行SQL命令(建表,增删改查)
        1.非查询操作(无返回结果集的操作) 插入 更新 删除等
        //参数为需要执行的sql语句
        - (void)noQueryOpertion:(NSString*)sql{
            //用来执行无返回结果的操作
            //第一个参数:数据库的句柄,所有对数据库的操作都是通过句柄来完成的,所以这里需要句柄
            //第二个参数:要执行的sql语句
            //第三个参数:回调函数,exec函数执行完毕之后会执行的函数。如果需要在该操作执行完毕的时候做一些其他操作,就需要实现该回调函数,一般我们直接NULl
            //第四个参数:回调方法的第一个参数
            //第五个参数:错误日志
            int result =  sqlite3_exec(sqliteHandle, sql.UTF8String, NULL, NULL, NULL);
            if (result == SQLITE_OK) {
                NSLog(@"操作执行成功");
            }else{
                NSLog(@"操作执行失败");
            }
        }
        
        2.查询操作
        - (void)queryWithSql:(NSString*)sql{
           //伴随指针 当我们进行查询操作的时候,该指针可以理解为存储一条一条的记录。我们获取一条记录的所有信息都是通过伴随指针。
           sqlite3_stmt * stmt = NULL;
           //预执行sql语句,如果预执行成功说明,那么我们就可以获取一条一条的记录;如果预执行失败,说明我们的sql语句有问题 不能获取表中的记录信息
           //第一个参数:数据库句柄
           //第二个参数:要执行的SQ语句
           //第三个参数:要执行的长度,如果全部执行,这里就赋值为-1
           //第四个参数:伴随指针
           //第五个参数:如果sql语句不全部执行,该参数保存未执行的sql语句
           int result = sqlite3_prepare(sqliteHandle, sql.UTF8String, -1, &stmt, NULL);
           //初始化一个可变数组,用来存放所有的记录,每一条记录就相当于一个字典
           NSMutableArray* allDataMArray = [[NSMutableArray alloc] init];
           //判断是否预执行成功
           if(result == SQLITE_OK){
                //说明预执行成功,可以取表中的数据了
                //通过while循环将表中的每一条记录取出
                //step方法没执行一次,伴随指针就会执行下一条记录;当所有的记录都取完之后,step函数的返回值就不等于SQLITE_ROW了,循环也就停止了
                while (sqlite3_step(stmt) == SQLITE_ROW) {
                    //每次执行while循环,都是一条新的纪录,一条新记录要对应一个新字典。
                    NSMutableDictionary* mDictionary = [[NSMutableDictionary alloc] init];
        
                    //进入循环体内,伴随指针就相当于当前取出的一条记录
                    //从记录中取值,是一个字段一个字段取出
                    //取出第0列的值
                    //
                    const unsigned char* name = sqlite3_column_text(stmt, 0);
                    //将char*类型转换为我们OC中可用的字符串类型
                    NSString* nameString = [[NSString alloc] initWithCString:(const char *)name encoding:NSUTF8StringEncoding];
                    //将数据存入到字典中
                    [mDictionary setObject:nameString forKey:@"name"];
                    //取出第一列的值,存入字典中
                    int age = sqlite3_column_int(stmt,1);
                    //将int数据转换为NSNumber放入字典
                    [mDictionary setObject:@(age) forKey:@"age"];
                    //取出第二列的值
                    const unsigned char* gender = sqlite3_column_text(stmt, 2);
                    //将char*类型转换为我们OC中可用的字符串类型
                    NSString* genderString = [NSString stringWithCString:(const char*)gender encoding:NSUTF8StringEncoding];
                    [mDictionary setObject:genderString forKey:@"gender"];
                    //将该字典添加到可变数组中
                    [allDataMArray addObject:mDictionary];
                }
            }else{
                NSLog(@"预执行失败 --- %d",result);
        }
              //将伴随指针所有持有的资源释放
              sqlite3_finalize(stmt);
              //打印结果
              NSLog(@"查询结果 ---- %@",allDataMArray);
        }
        3.SQL语句操作
            1.建表操作
            NSString* sql = @"create table if not exists stu (name text,age integer,gender text)";
            [self noQueryOpertion:sql];
            2.插入一条数据
            NSString* insertSql = @"insert into stu values ('kk',16,'男')";
            [self noQueryOpertion:insertSql];
            3.更新操作
            NSString* updateSql = @"update stu set age = 18 where age = 16";
            [self noQueryOpertion:updateSql];
            4.删除一条数据
            NSString* deleteSql = @"delete from stu where name = 'kk'";
            [self noQueryOpertion:deleteSql];
            5.查询方法
            [self queryWithSql:@"select * from stu"];
    4.关闭数据库
        sqlite3_close(sqliteHandle);
3.SQLite常用系列函数
    1.sqlite3_exec()可以执行任何SQL语句,比如创表、更新、插入和删除操作。但是一般不用它执行查询语句,因为它不会返回查询到的数据
    2.SQLite语法:预执行
        sqlite3_prepare()
            这个函数将sql文本转换为一个准备语句(prepared statement)对象,同时返回这个对象的指针。它实际上并不执行(evaluate)这个SQL语句,他仅仅为执行准备这个sql语句
        sqlite3_bind_*()
            给宿主参数(host parameters)绑定值(*代表不同类型)
        sqlite3_step ()
            一次或多次来执行有前面sqlite3_prepare创建的准备语句
        sqlite3_column()
            这个过程从执行sqlite3_step()执行一个准备语句得到的结果集的当前行中返回一个列。每次sqlite3_step得到一个结果集的列停下后,这个过程就可以被多次调用去查询这个行的各列的值。对列操作是有多个函数,均以sqlite3_column为前缀
        sqlite3_finalize()
            这个过程销毁前面被sqlite3_prepare创建的准备语句,每个准备语句都必须使用这个函数去销毁以防止内存泄露
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351

推荐阅读更多精彩内容