sqlite(輕量級數據庫)
1.為什么要使用數據庫呢?
文件讀寫, NSUserDefualts, 歸檔, 寫入的過程是覆蓋, 效率比較低, 並且不支持針對某些數據的修改
2.數據庫: 存放數據的倉庫
數據庫以表的形勢存放數據
每個表都有字段, 用於標示存什么樣的數據
在字段中, 有一種特殊的字段(主鍵), 主鍵數據是唯一, 不重復, 用於區分數據使用
3.常用的數據庫: Oracle, SQLServer, access, sqlite(輕量級數據庫, 體積小, 占用內存小, 能夠滿足基本的要求, 增刪改查)
4.sqlite Manger 對sqlite數據庫操作的軟件
5.SQL: 結構化查詢語句, 用於對數據庫進行操作的語句
注: SQL不區分大小寫, 不區分""和'', 字符串要加""或''
創建表
create table "表名"(列名1 類型, 列名2 類型, ...)
例如: CREATE TABLE IF NOT EXISTS "Person" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , "name" TEXT DEFAULT 小明, "gender" TEXT DEFAULT 未知, "age" INTEGER DEFAULT 18)
插入數據
insert into "表名"(列名1 類型, 列名2 類型, ...)
例如: INSERT INTO "main"."Person" ("id","gender") VALUES (2,?1)
INSERT INTO 'Person' ('id', 'name', 'gender', 'age') VALUES (%ld, '%@', '%@', %ld)
更新數據
update "表名" set "列名" = 值 where "id" = 值
例如: UPDATE "main"."Person" SET "age" = ?1 WHERE id = 5
查詢數據
select (列名1, 列名2, ...) from "表名" where 條件
例如: select *from "Person"
selec *from "person" where "age" <= 18
刪除數據
delete from "表名" where 條件
例如: delete from "Person" where id = 2
6.通過代碼對數據庫進行操作的步驟
a.創建一個單例類, 對數據庫操作全部封裝起來
b.對sqlite的數據庫進行操作, 需要引入sqlite的框架
7.多次打開同一個數據庫, 就會造成數據庫被鎖住, 導致數據庫無法修改
創建一個單例類
DatabaseManager.h #import <Foundation/Foundation.h> @class Person; @interface DatabaseManager : NSObject 一般來說, 一個應用只需要一個數據庫就夠了, 為了保證數據庫管理類和數據庫文件一一對應, 把數據庫管理類封裝成單例類 + (DatabaseManager *)sharedDatabaseManager; 創建數據庫文件, 並打開數據庫 - (void)openDB; 關閉數據庫 - (void)closeDB; 創建表 - (void)createTable; 增加數據 - (void)insertPerson:(Person *)person; 刪除數據 - (void)deletePerson:(NSInteger)ID; 更新數據 - (void)updatePersonWithName:(NSString *)name ID:(NSInteger)ID; 查詢數據 - (NSMutableArray *)sellectAllPerson; @end
DatabaseManager..m #import "DatabaseManager.h" #import <sqlite3.h> #import "Person.h" sqlite3 *db = NULL; @implementation DatabaseManager
創建單例 + (DatabaseManager *)sharedDatabaseManager { static DatabaseManager *databaseManager = nil; if (databaseManager == nil) { databaseManager = [[DatabaseManager alloc] init]; } return databaseManager; }
打開數據庫 - (void)openDB { 判斷數據庫指針是否為nil, 數據庫是否處於打開狀態 if (db) { return; } //documents的路徑 NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; //數據庫文件路徑 NSString *filePath = [documentPath stringByAppendingPathComponent:@"database2.sqlite"]; NSLog(@"%@", filePath); //參數1: 數據庫文件路徑 //參數2: 數據庫指針 打開指定路徑的數據庫文件, 如果沒有數據庫文件, 就創建數據庫庫文件, 如果有, 就直接打開, 打開以后, 把指針指向數據庫的首地址, 這樣就可以對數據庫進行操作 int result = sqlite3_open([filePath UTF8String], &db); if (result == SQLITE_OK) { NSLog(@"打開數據庫成功"); } else { NSLog(@"打開數據庫失敗:%d", result); } }
關閉數據庫 - (void)closeDB { if (!db) { return; } //關閉數據庫 int result = sqlite3_close(db); //安全操作 db = NULL; if (result == SQLITE_OK) { NSLog(@"關閉數據庫成功"); } else { NSLog(@"關閉數據庫失敗:%d", result); } }
創建表 - (void)createTable { //參數1: 數據庫的地址 //參數2: sql語句 //參數3: 函數指針, 當操作執行后, 去執行函數指針指向的函數 //參數4: 回調的參數 //參數5: 錯誤信息 NSString *sqlString = @"CREATE TABLE IF NOT EXISTS \"Person\" (\"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , \"name\" TEXT DEFAULT 小明, \"gender\" TEXT DEFAULT 未知, \"age\" INTEGER DEFAULT 18)"; char *error = NULL; int result = sqlite3_exec(db, [sqlString UTF8String], NULL, NULL, &error); if (result == SQLITE_OK) { NSLog(@"創建表成功"); } else { NSLog(@"創建表失敗:%d %s", result, error); } }
插入數據 - (void)insertPerson:(Person *)person { if (!db) { [self openDB]; [self createTable]; } NSString *sqlString = [NSString stringWithFormat:@"INSERT INTO 'Person' ('id', 'name', 'gender', 'age') VALUES (%ld, '%@', '%@', %ld)", person.ID, person.name, person.gender, person.age]; char *error = NULL; //執行sql語句 int result = sqlite3_exec(db, [sqlString UTF8String], NULL, NULL, &error); if (result == SQLITE_OK) { NSLog(@"插入成功"); } else { NSLog(@"插入失敗:%d %s", result, error); } [self closeDB]; }
刪除數據 - (void)deletePerson:(NSInteger)ID { if (!db) { [self openDB]; [self createTable]; } NSString *sqlString = [NSString stringWithFormat:@"delete from 'Person' where id = %ld", ID]; char *error = NULL; //執行sql語句 int result = sqlite3_exec(db, [sqlString UTF8String], NULL, NULL, &error); if (result == SQLITE_OK) { NSLog(@"刪除成功"); } else { NSLog(@"刪除失敗:%d %s", result, error); } [self closeDB]; }
修改數據 - (void)updatePersonWithName:(NSString *)name ID:(NSInteger)ID { if (!db) { [self openDB]; [self createTable]; } NSString *sqlString = [NSString stringWithFormat:@"update 'Person' set 'name' = '%@' where id = %ld", name, ID]; char *error = NULL; //執行sql語句 int result = sqlite3_exec(db, [sqlString UTF8String], NULL, NULL, &error); if (result == SQLITE_OK) { NSLog(@"更新成功"); } else { NSLog(@"更新失敗:%d %s", result, error); } [self closeDB]; }
查詢數據 - (NSMutableArray *)sellectAllPerson { NSMutableArray *array = [NSMutableArray arrayWithCapacity:0]; if (!db) { [self openDB]; [self createTable]; } //sql語句 NSString *sqlString = @"select *from 'Person'"; sqlite3_stmt *stmt = NULL; //准備sql語句 //參數3: 語句的長度 //參數4: 語句指針(statement) //參數5: 預留參數, 為未來做准備 int result = sqlite3_prepare(db, [sqlString UTF8String], -1, &stmt, NULL); if (result == SQLITE_OK) { NSLog(@"准備成功"); 單步執行, 把一條一條數據給提取出來 判斷是否有下一行數據 while (sqlite3_step(stmt) == SQLITE_ROW) { Person *person = [[Person alloc] init]; //找第一列的整型數據 int ID = sqlite3_column_int(stmt, 0); const unsigned char *name = sqlite3_column_text(stmt, 1); const unsigned char *gender = sqlite3_column_text(stmt, 2); int age = sqlite3_column_int(stmt, 3); NSString *name1 = [NSString stringWithUTF8String:(const char *)name]; NSString *gender1 = [NSString stringWithUTF8String:(const char *)gender]; // NSLog(@"%d %@ %@ %d", ID, name1, gender1, age); person.ID = ID; person.name = name1; person.gender = gender1; person.age = age; [array addObject:person]; [person release]; } } else { NSLog(@"准備失敗:%d", result); } //釋放語句指針 sqlite3_finalize(stmt); [self closeDB]; return array; } @end
自定義一個PersonCell
關聯屬性
#import <UIKit/UIKit.h> @interface PersonCell : UITableViewCell @property (retain, nonatomic) IBOutlet UILabel *idLabel; @property (retain, nonatomic) IBOutlet UILabel *nameLabel; @property (retain, nonatomic) IBOutlet UILabel *genderLabel; @property (retain, nonatomic) IBOutlet UILabel *ageLabel; @end
RootTableViewController.m
#import "RootTableViewController.h" #import "DatabaseManager.h" #import "Person.h" #import "PersonCell.h" @interface RootTableViewController () @property (nonatomic, retain) NSMutableArray *personArray; @end @implementation RootTableViewController - (void)dealloc { [_personArray release]; [super dealloc]; } - (void)viewDidLoad { [super viewDidLoad]; self.tableView.rowHeight = 50; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. if (section == 0) { return 1; } return self.personArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 0) { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"topcell" forIndexPath:indexPath]; return cell; } PersonCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]; Person *person = self.personArray[indexPath.row]; cell.idLabel.text = [NSString stringWithFormat:@"%ld", person.ID]; cell.nameLabel.text = person.name; cell.genderLabel.text = person.gender; cell.ageLabel.text = [NSString stringWithFormat:@"%ld", person.age]; return cell; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.personArray = [[DatabaseManager sharedDatabaseManager] sellectAllPerson]; [self.tableView reloadData]; } // Override to support conditional editing of the table view. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the specified item to be editable. return YES; } // Override to support editing the table view. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { //刪除數據庫中的數據 [[DatabaseManager sharedDatabaseManager] deletePerson:[self.personArray[indexPath.row] ID]]; //刪除數組中的元素 [self.personArray removeObjectAtIndex:indexPath.row]; // Delete the row from the data source [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } }
AddViewController.m #import "AddViewController.h" #import "Person.h" #import "DatabaseManager.h" @interface AddViewController () @end @implementation AddViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)back:(UIBarButtonItem *)sender { [self dismissViewControllerAnimated:YES completion:nil]; } - (IBAction)done:(UIBarButtonItem *)sender { //創建person Person *person = [[Person alloc] init]; person.ID = [self.idTextField.text integerValue]; person.name = self.nameTextField.text; person.gender = self.genderTextField.text; person.age = [self.ageTextField.text integerValue]; //添加到數據庫 [[DatabaseManager sharedDatabaseManager] insertPerson:person]; //釋放 [person release]; [self dismissViewControllerAnimated:YES completion:nil]; } - (void)dealloc { [_idTextField release]; [_nameTextField release]; [_genderTextField release]; [_ageTextField release]; [super dealloc]; } @end
效果圖