SQLite,Golang和联结表

时间:2016-02-15 13:22:43

标签: sql sqlite go sql-insert junction-table

我想使用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,但是我不确定这个想法是多么惯用。请注意,我要添加大量记录。

2 个答案:

答案 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)
}

但我仍在寻找更好的答案......