iOS SQLite : How to automatically set foreign key?

标签 ios sqlite foreign-keys auto-increment

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

最佳答案

是的,如果 A 和 B 之间是一对多的,并且当你在 B 中添加记录时,你将自动增加 B 的主键,而不是 A 的外键(假设你将它设为普通的 INTEGER,没有 AUTOINCREMENT)。给定你的例子,是的,B 将有五个记录,1-5,它们都指向 A 中的记录 1。因此,当你在 A 中添加记录时,你通过 FMDB 的 lastInsertRowId 获取它的 id (或 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];
}

关于iOS SQLite : How to automatically set foreign key?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11718944/

相关文章:

java - Hibernate外键映射?

ios - 手机间隙 : Calling an action when an app is opened after clicking the home button (iOS)

ios - .reloadData() 和 .setNeedsDisplay() 被忽略

c++ - 如何使用C++在Qt中的sqlite数据库中获取行

c++ - SQLite - Windows 平台的首选编码

mysql - 为什么存在外键时为 'foreign key constraint fails'?

ios - Swift % 计算不正确

ios - 核心数据与中间表的多对多关系(Swift 2)

c# - 如果我使用 SQLite 创建 C# 桌面应用程序,数据库会与安装程序捆绑在一起吗?

mysql - Django 模型访问