iOS SQLite:如何自动设置外键?

Mo *_*osa 2 sqlite foreign-keys auto-increment ios

我的应用程序使用SQLite,我已经整理出create table语句.这个想法是表A和B具有一对多(或一个)关系,因此外键将在表B中.现在我知道用于创建主键的自动增量但是如何为外键工作?如果我为表A添加一行,为表B添加5行(理想情况下所有这些行都链接到表A中的那一行),该怎么办?它不会只是从表B中的001-005自动增量吗?

Rob*_*Rob 8

是的,如果它是A和B之间的一对多,并且当您在B中添加记录时,您将自动增加B的主键,但不会自动增加A的外键(假设您将其设为INTEGER无旧的AUTOINCREMENT).给出你的例子,是的,B将有五个记录,1-5,这将全部指向A中的记录1.因此,当你在A中添加记录时,你通过FMDB lastInsertRowId(或sqlite sqlite3_last_insert_rowid())获取它的id ,存储在一个变量,然后在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);
Run Code Online (Sandbox Code Playgroud)

如果我们查看结果,它看起来像:

$ 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
Run Code Online (Sandbox Code Playgroud)

或者,如果你想以编程方式进行(我使用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];
}
Run Code Online (Sandbox Code Playgroud)

  • 优秀,工作精美.非常感谢,我为接受这个答案的延迟道歉. (3认同)