我的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/