Go语言 内存中数据库出现“无此表”错误

w6mmgewl  于 2023-08-01  发布在  Go
关注(0)|答案(5)|浏览(95)

我正在使用内存中的SQLite数据库:

func init() {
    global.ConductorConfig = readConfig()
    log.Println(utils.GetCurrentDir() + global.ConductorConfig.DbFile)
    //db = sqlx.MustConnect("sqlite3", utils.GetCurrentDir()+global.ConductorConfig.DbFile)
    db = sqlx.MustConnect("sqlite3", ":memory:")
    db.Exec(schema)
    task:=model.Task{}
    SaveTask(&task)
    db.MapperFunc(func(s string) string {
        return s
    })
}

字符串
在我的main函数中,我创建了一个表:

if global.ConductorConfig.DevMode {
    db.CreateTables()
}
go job.HeartbeatJob()
go job.TaskClearJob()
app.Action = func(c *cli.Context) error {
    ListenAndServe()
    return nil
}


我在HTTP handler函数中得到“no such table”:

existed, err := db.GetAgentByServerName(agent.ServerName)
if err != nil {
    c.JSON(http.StatusBadRequest, err)
    log.Println("[conductor] error occurred when get agent by server name: " + err.Error())
    return err
}

func GetAgentByServerName(name string) (*model.Agent, error) {
    agent := &model.Agent{}
    err := db.Get(agent, "select * from agent where ServerName=$1", name)

    if err == sql.ErrNoRows {
        err = nil
        agent = nil
    }

    return agent, err
}


当我启动程序时,我得到:
按服务器名称获取代理时出错:无此表:代理人
数据库架构(省略属性):

var schema = `
DROP TABLE IF EXISTS agent;
CREATE TABLE agent (
    Id                  INTEGER PRIMARY KEY,
);

DROP TABLE IF EXISTS task;
CREATE TABLE task (
    Id                  INTEGER PRIMARY KEY,
);


重现错误的最小示例。

package main
    
    import (
        "github.com/jmoiron/sqlx"
        _ "github.com/mattn/go-sqlite3"
        "log"
    )
    
    var db *sqlx.DB
    
    func init() {
        db = sqlx.MustConnect("sqlite3", ":memory:")
        db.Exec("CREATE TABLE agent (Id  INTEGER PRIMARY KEY,);")
    }
    
    func main()  {
        _, err:=db.Exec("insert into agent values (1)")
        if err!=nil{
            log.Println(err)
        }

}

yr9zkbsy

yr9zkbsy1#

:memory:为每个连接打开一个单独的数据库。使用file::memory:?cache=shared代替。
更新:我在使用上面的代码时也遇到了一些锁问题,在我看来,在测试中使用:memory:db.DB().SetMaxOpenConns(1)是一个更好的解决方案。

lx0bsm1f

lx0bsm1f2#

也许这能帮上忙

我也遇到了同样的问题,“没有这样的表”,并找到了一个确切的解释:

  • 如果sql.Rows在下一个查询之前没有关闭,则驱动程序在下一个查询中不返回这样的表。仅内存存储存在问题,对文件备份数据库的相同测试运行正常。*

在那之后,我找到了忘记执行rows.Close()的代码部分,修复了它,现在它可以正常工作了。
原文回答:https://github.com/mattn/go-sqlite3/issues/511#issuecomment-396290916

ttygqcqt

ttygqcqt3#

如果您使用相同的模式来创建表,您张贴在这里,那么表是永远不会创建,因为模式有语法错误,它应该是这样的

var schema = `
  DROP TABLE IF EXISTS agent;
  CREATE TABLE agent (
    Id                  INTEGER PRIMARY KEY
 );

  DROP TABLE IF EXISTS task;
  CREATE TABLE task (
    Id                  INTEGER PRIMARY KEY
);
`

字符串
我猜您的代码与示例代码相同,因此在init函数中,您跳过了db.Exec(schema)的错误检查(您永远不应该对Go中的任何函数进行错误检查)。由于未检查错误,并且执行模式时出错,因此表从未创建,但程序继续,请更正模式并检查错误,然后重试。在你的init函数中试试这个:

_, err := db.Exec(schema)

if err != nil {
    log.Fatal(err)
}

vmjh9lq9

vmjh9lq94#

我有““没有这样的表”错误与内存中的sqlite”发生时,我试图使用错误的交易。范例:

tx, err = DB.Begin()
if err != nil {
    ErrorStatus = true
    goto ErrorLabel
}
tempQuery = "INSERT INTO msg_to_like (msg_id, user_id) " +
    "VALUES ('" + nmbr + "', " + usr + ");"
fmt.Println(tempQuery)
if _, err = DB.Exec(tempQuery); err != nil {
    ErrorStatus = true
    goto ErrorLabel
}
...

字符串
但这是必要的:

if _, err = tx.Exec(tempQuery); err != nil {


出现此错误后,使用的表崩溃。

d4so4syb

d4so4syb5#

我之所以出现这个错误是因为一个编程错误,在一行中我引用了tx事务,在另一行中我引用了r.db
错误:

err = r.db.Transaction(func(tx *gorm.DB) error {
result := tx.Where(...
...
result = r.db.Create
return nil
})

字符串
正确:

err = r.db.Transaction(func(tx *gorm.DB) error {
result := tx.Where(...
...
result = tx.Create
return nil
})

相关问题