2012-07-30 68 views
2

我的應用程序使用SQLite,並且我已經完成了創建表語句。這個想法是,表A和B有一對多(或一個)關係,所以外鍵將在表B中。現在我知道創建主鍵的自動增量,但是如何爲外鍵工作?如果我爲表A添加一行併爲表B添加5行(理想情況下所有這些都鏈接到表A中的單行)?表B中的001-005不是自動增加嗎?iOS SQLite:如何自動設置外鍵?

+1

我更新了我的答案與示例如何以編程方式從iOS應用程序更新數據庫。 – Rob 2012-07-30 19:20:29

回答

8

是的,如果它是A和B之間的一對多關係,並且當你在B中添加記錄時,你將自動增加B的主鍵,但不是A的外鍵(假設你使它成爲一個普通的舊INTEGER沒有AUTOINCREMENT)。舉例來說,是的,B會有五條記錄,1-5,這些記錄都指向A中的記錄1.所以,當你在A中添加記錄時,你通過FMDB的lastInsertRowId(或者sqlite的sqlite3_last_insert_rowid())那麼在變量中,然後在B中填充外鍵時使用它。因此,簡而言之,您不會「自動」設置外鍵,而只是手動設置外鍵,但這並不難。

就如何配置表而言,如果我們看一下作者和書籍之間的一對多關係的例子(忽略共同作者的可能性,但着眼於一個作者可以寫多本書)。因此,您有兩個實體:author(A)實體和book(B)實體。 book.book_author_id是一個涉及author.author_id的外鍵。

因此,看起來像:

CREATE TABLE author 
(
    author_id INTEGER PRIMARY KEY AUTOINCREMENT, 
    author_last_name TEXT, 
    author_first_name TEXT 
); 

CREATE TABLE book 
(
    book_id INTEGER PRIMARY KEY AUTOINCREMENT, 
    title TEXT, 
    book_author_id INTEGER, 
    FOREIGN KEY (book_author_id) REFERENCES author (author_id) 
); 

INSERT INTO author (author_last_name, author_first_name) VALUES ('William', 'Shakespeare'); 

INSERT INTO book (title, book_author_id) VALUES ('Hamlet', 1); 
INSERT INTO book (title, book_author_id) VALUES ('Macbeth', 1); 
INSERT INTO book (title, book_author_id) VALUES ('Othello', 1); 
INSERT INTO book (title, book_author_id) VALUES ('King Lear', 1); 
INSERT INTO book (title, book_author_id) VALUES ('Henry V', 1); 

如果我們只看結果,它看起來像:

$ sqlite3 test.db 
SQLite version 3.7.12 2012-04-03 19:43:07 
Enter ".help" for instructions 
Enter SQL statements terminated with a ";" 
sqlite> .mode column 
sqlite> .headers on 
sqlite> 
sqlite> CREATE TABLE author 
    ...> (
    ...>  author_id INTEGER PRIMARY KEY AUTOINCREMENT, 
    ...>  author_last_name TEXT, 
    ...>  author_first_name TEXT 
    ...>); 
sqlite> 
sqlite> CREATE TABLE book 
    ...> (
    ...>  book_id INTEGER PRIMARY KEY AUTOINCREMENT, 
    ...>  title TEXT, 
    ...>  book_author_id INTEGER, 
    ...>  FOREIGN KEY (book_author_id) REFERENCES author (author_id) 
    ...>); 
sqlite> 
sqlite> INSERT INTO author (author_last_name, author_first_name) VALUES ('William', 'Shakespeare'); 
sqlite> 
sqlite> SELECT * FROM author; 
author_id author_last_name author_first_name 
---------- ---------------- ----------------- 
1   William   Shakespeare  
sqlite> 
sqlite> INSERT INTO book (title, book_author_id) VALUES ('Hamlet', 1); 
sqlite> INSERT INTO book (title, book_author_id) VALUES ('Macbeth', 1); 
sqlite> INSERT INTO book (title, book_author_id) VALUES ('Othello', 1); 
sqlite> INSERT INTO book (title, book_author_id) VALUES ('King Lear', 1); 
sqlite> INSERT INTO book (title, book_author_id) VALUES ('Henry V', 1); 
sqlite> 
sqlite> SELECT * FROM book; 
book_id  title  book_author_id 
---------- ---------- -------------- 
1   Hamlet  1    
2   Macbeth  1    
3   Othello  1    
4   King Lear 1    
5   Henry V  1    
sqlite> .quit 

或者,如果你想以編程方式做到這一點(我使用FMDB這使得這更簡單,但如果你正在做自己的sqlite3調用,顯然同樣的邏輯工作,但它只需要更多的代碼):

- (void)createAuthorTable 
{ 
    BOOL result = [_db executeUpdate: 
        @"CREATE TABLE IF NOT EXISTS author " 
         "(" 
          "author_id INTEGER PRIMARY KEY AUTOINCREMENT, " 
          "author_last_name TEXT, " 
          "author_first_name TEXT " 
         ");"]; 
    NSAssert(result, @"%s - Unable to create author table", __FUNCTION__); 
} 

- (void)createBookTable 
{ 
    BOOL result = [_db executeUpdate: 
        @"CREATE TABLE IF NOT EXISTS book " 
         "(" 
          "book_id INTEGER PRIMARY KEY AUTOINCREMENT, " 
          "title TEXT, " 
          "book_author_id INTEGER, " 
          "FOREIGN KEY (book_author_id) REFERENCES author (author_id) " 
         ");"]; 
    NSAssert(result, @"%s - Unable to create book table", __FUNCTION__); 
} 

- (sqlite_int64)createAuthorWithFirstName:(NSString *)firstName lastName:(NSString *)lastName 
{ 
    BOOL result = [_db executeUpdate:@"INSERT INTO author (author_first_name, author_last_name) VALUES (?, ?)", firstName, lastName]; 
    NSAssert(result, @"%s - Unable to insert author record", __FUNCTION__); 

    return [_db lastInsertRowId]; 
} 

- (sqlite_int64)createBookWithTitle:(NSString *)title authorId:(sqlite_int64)authorId 
{ 
    BOOL result = [_db executeUpdate:@"INSERT INTO book (title, book_author_id) VALUES (?, ?)", title, [NSNumber numberWithInt:authorId]]; 
    NSAssert(result, @"%s - Unable to insert book record", __FUNCTION__); 

    return [_db lastInsertRowId]; 
} 

- (void)testInsert 
{ 
    [self openDatabase]; 

    NSArray *bookTitles = [NSArray arrayWithObjects:@"Hamlet", @"Macbeth", @"Othello", @"King Lear", @"Henry V", nil]; 
    [self createAuthorTable]; 
    [self createBookTable]; 

    sqlite_int64 authorId = [self createAuthorWithFirstName:@"William" lastName:@"Shakespeare"]; 

    sqlite_int64 bookId; 
    for (NSString *bookTitle in bookTitles) 
     bookId = [self createBookWithTitle:bookTitle authorId:authorId]; 

    [self closeDatabase]; 
} 
+3

非常好,工作很好。非常感謝,我對接受這個答案的延誤表示歉意。 – 2012-08-08 16:59:11

0

具有外鍵約束的列通常不是自動增量值,而是指另一個表中的(預先存在的)鍵值。因此,如果您的AUTHORS表具有自動增量整數主鍵,則您的TITLES.AuthorID列將只是一個無自動增量功能的整數。

順便說一句,整數值做不是具有前導零:001-005 - 通常意味着零填充,它必須用文本/ varchar數據類型表示。

0

但是在設置外鍵之前,必須先將其打開。首先做到這一點,

PRAGMA foreign_keys=ON;