2012-05-10 25 views
5

Tôi đang cố gắng tạo tệp cơ sở dữ liệu SQLite3 thông qua Objective-C khi chạy. Tôi đang cố tạo một bảng có tên là "tblStore". Tôi muốn các tên trường được gọi là "strStoreNumber" và "strStoreReg". Tôi mới sử dụng iOS và SQLite, vì vậy tôi đang gặp khó khăn khi tìm cú pháp để thực hiện việc này. Ngoài việc tạo bảng, tôi muốn bảng được tạo để cư trú KHÔNG trong gói ứng dụng, mà là nó sẽ cư trú/được lưu trữ ở đâu đó trên điện thoại. Bảng cần phải có thể đọc/ghi được. Tôi đã thực hiện một số đọc trên "sandbox người dùng" và cũng là một "thư mục tài liệu". Tôi không chắc tôi hiểu sự khác biệt giữa hai người. Lý tưởng nhất, ứng dụng của tôi sẽ sử dụng nút để nhập liệu từ Trường văn bản. Sau khi đầu vào từ các trường văn bản được đưa vào chuỗi, một kiểm tra sẽ được thực hiện để xem bảng SQLite "tblStore" của tôi có tồn tại hay không và nếu không, bảng sẽ được tạo.Tạo tệp cơ sở dữ liệu SQLite3 thông qua Objective-C

Tóm tắt: 1. Cú pháp cho Obj-C/SQLite là gì để tạo bảng có tên "tblStore" với các trường "strStoreNumber" và "strStoreReg"? 2. Tệp db nằm ở đâu? Tôi cần đọc và ghi vào tệp db tblStore. 3. Sự khác nhau giữa "sandbox của người dùng" và "thư mục tài liệu" là gì?

Đây là những gì tôi hiện có:

-(IBAction)setInput:(id)sender 
{ 
    NSString *strStoreNumber; 
    NSString *strRegNumber; 
    NSString *tableName = @"tblStore"; 
    NSString *dbStrStore = @"strStore"; 
    NSString *dbStrReg = @"strReg"; 


    strStoreNumber = StoreNumber.text; 
    strRegNumber = RegNumber.text; 

    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString* documentsDirectory = [paths lastObject]; 
    NSString* databasePath = [documentsDirectory stringByAppendingPathComponent:@"tblStore.sqlite"]; 
// NSString* databasePath = [[NSBundle mainBundle] pathForResource:@"tblStore" ofType:@"sqlite"]; 

    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) 
    { 
     NSLog(@"Opened sqlite database at %@", databasePath); 

     char *err; 
     NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS '%@' ('%@' TEXT PRIMARY KEY, '%@' TEXT);", tableName, dbStrStore, dbStrReg]; 
     if (sqlite3_exec(database, [sql UTF8String], NULL, NULL, &err) != SQLITE_OK) 
     { 
      sqlite3_close(database); 
      NSAssert(0, @"Table failed to create."); 
     } 
     //...stuff 
    } 
    else 
    { 
     NSLog(@"Failed to open database at %@ with error %s", databasePath, sqlite3_errmsg(database)); 
     sqlite3_close (database); 
    } 

    NSString *querystring; 

    // create your statement 
    querystring = [NSString stringWithFormat:@"SELECT strStore, strReg FROM tblStore WHERE strStore = %@ AND strReg = %@;", strStoreNumber, strRegNumber]; 

    const char *sql = [querystring UTF8String]; 

    NSString *szStore = nil; 
    NSString *szReg = nil; 

    sqlite3_stmt *statement = nil; 
    if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL)!=SQLITE_OK) //queryString = Statement 
    { 
     NSLog(@"sql problem occured with: %s", sql); 
     NSLog(@"%s", sqlite3_errmsg(database)); 
    } 
    else 
    { 
     // you could handle multiple rows here 
     while (sqlite3_step(statement) == SQLITE_ROW) 
     {    
      szStore = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 0)]; 
      szReg = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 1)]; 
     }   
    } 

    sqlite3_finalize(statement); 

    lblStoreNumber.text = szStore; 
    lblRegNumber.text = szReg; 
} 

Khi tôi chạy ứng dụng của tôi, tôi nhận được các lỗi sau đây:

2012-05-10 14:58:38.169 CCoDBTry[355:f803] Opened sqlite database at /Users/Matt****/Library/Application Support/iPhone Simulator/5.1/Applications/5DB7A218-A0F6- 485F-B366-91FD2F9BC062/Documents/tblStore.sqlite 
2012-05-10 14:58:38.307 CCoDBTry[355:f803] sql problem occured with: SELECT strStore, strReg FROM tblStore WHERE strStore = 8053 AND strReg = 4; 
2012-05-10 14:58:38.308 CCoDBTry[355:f803] no such column: strStore 

Tôi đánh giá cao bất cứ ai mất thời gian ra để giải thích một số điều này công cụ, như tôi rất mới và đã không thành công trong việc hoàn thành một số trong những điều tôi đã cố gắng. Cảm ơn rất nhiều vì sự giúp đỡ!

Trả lời

2

sqlite là một nỗi đau nếu bạn không biết mình đang làm gì. Tôi cũng đã có một số vấn đề với các chức năng sqlite c nhưng sau đó tôi quyết định sử dụng wrapper sqlite.

FMDBBWDB là các trình bao bọc sqlite tốt và dễ sử dụng cho mục tiêu c. Tôi đề nghị bạn sử dụng một trong số đó.

Lưu ý rằng BWDB nằm trong hướng dẫn lynda.com (this one) và nếu bạn không tìm thấy nó trên web ... để lại nhận xét và tôi sẽ tải nó lên một nơi nào đó.

chỉnh sửa: nơi duy nhất bạn có thể viết nội dung trong ứng dụng của mình nằm trong thư mục tài liệu ... do đó ... các thuật ngữ đơn giản ... nếu db không nằm trong thư mục tài liệu của bạn..và chỉ đọc .. cũng .. khi bạn đọc/ghi vào hệ điều hành db..the của bạn sao chép db trong thư mục tài liệu..và thực hiện tất cả việc đọc và ghi ở đó để bạn có thể có một db trong gói ứng dụng của mình nhưng bạn không thể chỉnh sửa nó ... vì vậy bạn sẽ kết thúc với 2 db.I có cùng một vấn đề bản thân mình..và tôi đã sửa nó bằng cách hợp nhất 2 db khi tôi cập nhật ứng dụng

edit2: i đã tải lên dự án cuối cùng BWDB (bạn có wrapper đó và dự án để xem nó hoạt động như thế nào)

+0

Điều này thực sự hữu ích, nhưng tôi đã hy vọng tránh được bất kỳ loại trình bao bọc hoặc thư viện bên ngoài nào. Tôi sẽ giữ các câu trả lời khác để xem liệu có ai có thể cung cấp một số thông tin chi tiết về cú pháp tạo bảng thuần túy sẽ trông như thế nào không. Bất cứ điều gì tôi đã diễn ra trong ứng dụng của tôi không ổn, haha. Cảm ơn bạn đã trả lời nhanh chóng! – Skizz

+0

cũng là quyết định của bạn .. nhưng hãy nhớ rằng sử dụng trình bao bọc, bạn sẽ chỉ phải sử dụng các cuộc gọi c mục tiêu ... như [self getRow: 2]. Đó là A LOT dễ dàng hơn so với tất cả các cuộc gọi sql: mở db, thực hiện một tuyên bố, exec các tuyên bố, sau đó xem nếu nó không nil, xử lý lỗi, xử lý dữ liệu, và sau đó đóng. Đó là một nỗi đau chỉ để viết. – skytz

0

bạn có thể mở terminal và cd tới/Users/Matt * */Library/Application Support/iPhone Simulator/5.1/Applications/5DB7A218-A0F6-485F-B366-91FD2F9BC062/Documents/

sau đó sqlite3 tblStore.sqlite

sau đó sử dụng .schema tblStore sẽ hiển thị bảng của bạn giản đồ và bạn có thể xem liệu nó có được xây dựng đúng hay không.

Cơ sở dữ liệu của bạn cần nằm trong thư mục tài liệu để có quyền ghi. Nếu cơ sở dữ liệu của bạn chỉ được đọc, không bao giờ được ghi vào cơ sở dữ liệu có thể nằm trong gói ứng dụng của bạn.Một cách để hoàn thành điều này là tạo tệp database.sqlite của bạn và thêm nó vào gói và sao chép nó vào thư mục tài liệu (nếu nó chưa tồn tại ở đó) khi khởi động.

0

Có lý do cụ thể nào bạn muốn sử dụng SQLLite trực tiếp, trái ngược với việc sử dụng CoreData không? CoreData sử dụng một cơ sở dữ liệu SQLLite nhưng chính nó là một API cấp cao hơn, và đặc biệt là với các khung nhìn bảng và như vậy, bạn nhận được rất nhiều chức năng và các phương thức mẫu đã được thiết lập cho nó trong Xcode. Xác định các mô hình dữ liệu là tầm thường, bạn nhận được rất nhiều mã soạn sẵn, và tất cả đều được tối ưu hóa.

http://www.raywenderlich.com/934/core-data-on-ios-5-tutorial-getting-started

CoreData đôi khi được mô tả là có đường cong học tập dốc. Tôi không đồng ý. Nếu bạn đang xem xét việc viết SQL cho chính mình trong ứng dụng của mình, bạn sẽ không gặp bất kỳ rắc rối nào với CoreData.

Thuật ngữ "sandbox" là thuật ngữ trừu tượng cho phần hệ thống tệp của thiết bị mà ứng dụng của bạn có quyền truy cập đọc/ghi. Thư mục "Documents" là một thư mục cụ thể trong sandbox của ứng dụng của bạn. Có các tệp khác trong sandbox của bạn chứ không chỉ là thư mục tài liệu, nhưng hầu hết các ứng dụng lưu dữ liệu vào hệ thống tệp trong iOS làm như vậy trong thư mục tài liệu.

+0

Chủ lao động của tôi quan tâm đến việc sử dụng SQLite vì nó được hỗ trợ bởi iOS. Tôi không có nhiều đầu vào về vấn đề đó. Tuy nhiên, giải thích của bạn về Sandbox/Documents đã được phát hiện cho tôi. Tôi đã thực sự thiếu hiểu biết trong khu vực đó. Nếu bạn không phiền, bạn có thể đi vào chi tiết hơn (hoặc chỉ cho tôi một tài nguyên) giải thích cách truy cập vào sandbox của tôi và cụ thể hơn là thư mục tài liệu nằm trong sandbox của tôi. Tôi thực sự đánh giá cao phản ứng nhanh chóng. Cám ơn rất nhiều! – Skizz

2

Bạn có thể sử dụng mã sau để lấy cơ sở dữ liệu được tạo trong thư mục Tài liệu. Chỉ cần vượt qua một đường dẫn trong thư mục tài liệu và chức năng sẽ sao chép cơ sở dữ liệu sqlite trong thư mục tài liệu tại đường dẫn nhất định nếu cần thiết. Sau đó bạn có thể sử dụng đường dẫn này để tạo và truy vấn các bảng cơ sở dữ liệu.

+ (NSString*) createDatabaseIfRequiredAtPath:(NSString*)databasePath { 

    if (databasePath == nil) 
     return nil; 


    NSString *path = [NSString stringWithFormat:@"%@/%@", databasePath, kMainDBName]; 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSError *error = nil; 

    if ([fileManager fileExistsAtPath:path] == NO) 
    { 
    // The writable database does not exist, so copy the default to the appropriate location. 
     NSString *defaultDBPath = [[NSBundle mainBundle] pathForResource:kMainDBName 
                   ofType:nil]; 
     BOOL success = [fileManager copyItemAtPath:defaultDBPath 
             toPath:path 
             error:&error]; 
     if (!success) 
     { 
     NSCAssert1(0, @"Failed to create writable database file with message '%@'.", [ error localizedDescription]); 
     return nil; 
    } 
} 

return path; 
+0

Nếu tôi tạo đường dẫn theo cách này: Đường dẫn NSArray * = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); NSString * documentsDirectory = [paths lastObject]; Sau đó, tôi chỉ có thể chuyển "documentsDirectory" sang phương thức, đúng không? – Skizz

+0

Đúng vậy. –

11

// Tạo DB

-(NSString *) filePath 
{ 
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentDirectory=[paths objectAtIndex:0]; 
return [documentDirectory stringByAppendingPathComponent:@"LoginDatabase.sql"]; 
} 

// Mở DB

-(void)openDB 
{ 
if(sqlite3_open([[self filePath]UTF8String], &db) !=SQLITE_OK) 
{ 
    sqlite3_close(db); 
    NSAssert(0, @"Database failed to Open"); 
} 
} 

// Tạo Bảng

-(void) createTableNamed:(NSString*)tableName withField1:(NSString*) field1 withField2:(NSString*) field2 

{ 
    char *err; 
    NSString *sql=[NSString stringWithFormat:@" CREATE TABLE IF NOT EXISTS '%@'('%@' TEXT PRIMARY KEY,'%@' TEXT);",tableName,field1,field2]; 

    if(sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err) !=SQLITE_OK) 
    { 
    sqlite3_close(db); 
    NSAssert(0, @"Table failed to create"); 
    } 
} 

// hồ sơ Chèn

-(void)insertrecordIntoTable:(NSString*) tableName withField1:(NSString*) field1 field1Value:(NSString*)field1Vaue andField2:(NSString*)field2 field2Value:(NSString*)field2Value 
{ 

    NSString *sqlStr=[NSString stringWithFormat:@"INSERT INTO '%@'('%@','%@')VALUES(?,?)",tableName,field1,field2]; 
const char *sql=[sqlStr UTF8String]; 

sqlite3_stmt *statement1; 

if(sqlite3_prepare_v2(db, sql, -1, &statement1, nil)==SQLITE_OK) 
{ 
    sqlite3_bind_text(statement1, 1, [field1Vaue UTF8String], -1, nil); 
    sqlite3_bind_text(statement1, 2, [field2Value UTF8String], -1, nil); 
} 
if(sqlite3_step(statement1) !=SQLITE_DONE) 
    NSAssert(0, @"Error upadating table"); 
sqlite3_finalize(statement1); 
} 

// Lấy dữ liệu từ bảng

-(void)getAllRowsFromTableNamed:(NSString *)tableName 
{ 
    NSString *field1Str,*field2Str; 

    NSString *qsql=[NSString stringWithFormat:@"SELECT * FROM %@",tableName]; 
    sqlite3_stmt *statement; 
    if(sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, nil)==SQLITE_OK) 
    { 
    while(sqlite3_step(statement) ==SQLITE_ROW) 
    { 
    char *field1=(char *) sqlite3_column_text(statement, 0); 
    char *field2=(char *) sqlite3_column_text(statement, 1); 

    field1Str=[[NSString alloc]initWithUTF8String:field1]; 
    field2Str=[[NSString alloc] initWithUTF8String:field2]; 

    NSString *str=[NSString stringWithFormat:@"%@ - %@",field1Str,field2Str]; 
    NSLog(@"%@",str); 
    } 
} 

}

Trong viewDidLoad gọi các phương pháp

- (void)viewDidLoad 
{ 

    [self openDB]; 
    [self createTableNamed:@"Login" withField1:@"USERNAME" withField2:@"PASSWORD"]; 
    [self insertrecordIntoTable:@"Login" withField1:@"USERNAME" field1Value:username andField2:@"PASSWORD" field2Value:password]; 

} 

đâu tên truy cập và mật khẩu được NSString giá trị;

+0

bạn không phải là craeting cơ sở dữ liệu, bạn đang tạo một bảng trong một db hiện tại – OMGPOP

+3

mã không chính xác (bạn đã không tạo tệp .sqlite trong thư mục tài liệu. – OMGPOP

+0

Một số phương pháp có thể được xem xét với hướng dẫn sau: http: // www .appcoda.com/sqlite-database-ios-app-tutorial/ –

0

có thể bạn đã quên Bảng chèn. Đã tạo Cơ sở dữ liệu và Bảng nhưng bảng trống của nó. bạn đang cố gắng đọc các bản ghi từ Bảng trống.

+0

Hãy thử chèn một số bản ghi và Đọc.hope nó sẽ giải quyết vấn đề của bạn. – Baalu

Các vấn đề liên quan