我想使用Go和sqlite创建一个小型图书数据库。我从这个建议SQLite foreign key examples中获取了主要内容并重新开发了一些。
package main
import (
"database/sql"
...
_ "github.com/mattn/go-sqlite3"
)
...
db, err := sql.Open("sqlite3", "./foo.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
sqlStmt := `
create table books (
id integer primary key autoincrement,
title text
);
create table booksauthors (
bookid integer references books(id),
uthorid integer references authors(id) ON DELETE CASCADE ON UPDATE CASCADE
);
create table authors (
id integer primary key autoincrement,
fname text,
mname text,
lname text,
unique (fname, mname, lname) on conflict ignore
);
`
所以,我想保留唯一作者的列表并保持与书籍表的多对多连接(一本书可能有一个以上的作者,作者可能会写一本以上的书)。
然后我只是在循环中添加书籍,获取LastIndexID并将其放到联结表中(代码是为了说明而减少,b是书籍结构):
tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}
res, err := db.Exec("Insert into books(title) values(?)", b.Title)
if err != nil {
log.Fatal(err)
}
b_id, _ := res.LastInsertId()
for _, a := range b.Authors {
res, err = db.Exec("Insert into authors(fname, mname, lname) values(?, ?, ?)", a.Fname, a.Mname, a.Lname)
if err != nil {
log.Fatal(err)
}
a_id, _ := res.LastInsertId()
fmt.Println(a_id, b_id, a)
res, err = db.Exec("Insert into booksauthors(bookid, authorid) values(?, ?)", b_id, a_id)
if err != nil {
log.Fatal(err)
}
}
tx.Commit()
麻烦 - 如果我添加一本同一作者的书,a_id会增加,但是联结表包含它的旧值。 例如:
Books:
id | Title
---|--------------------
1 | Atlas Shrugged pt.1
2 | Atlas Shrugged pt.2
3 | Atlas Shrugged pt.3
Authors:
id | Fname | Mname | Lname
---|-------|-------|------
702| Ayn | | Rand
Junction table:
BookId | AuthorID
-------|---------
1 | 700
2 | 701
3 | 702
What I want - Junction table:
BookId | AuthorID
-------|---------
1 | 702
2 | 702
3 | 702
如何修复它以便正确的AuthorId会反映在桌面上?我不想使用GORM或任何ORM工具,并试图使用纯(好,或多或少)SQL来解决它。
我现在看到的解决方案之一我可以先选择SELECT,然后INSERT如果找不到任何内容然后再次选择SELECT,但是我不确定这个想法是多么惯用。请注意,我要添加大量记录。
答案 0 :(得分:0)
我的建议是SELECT
您的作者列表和INSERT
遗漏的作者。解决方案是天真的,但它的工作原理很简单。
我不是最新的SQLite关系功能,但使用它们并不总是处理外键的最简单的方法......
现在,如果要处理大量数据,请执行相同的操作,但首先要合并您的图书作者,这样您就只能有一个SELECT
然后只需INSERT
个。{/ p>
答案 1 :(得分:0)
作为一个快速的黑客,我在添加作者后做了一个选择:
err = db.QueryRow("select id from authors where fname = ? and mname = ? and lname = ?", a.Fname, a.Mname, a.Lname).Scan(&a_id)
if err != nil {
log.Fatal(err)
}
res, err = db.Exec("Insert into booksauthors(bookid, authorid) values(?, ?)", b_id, a_id)
if err != nil {
enter code herelog.Fatal(err)
}
但我仍在寻找更好的答案......