内存中的sqlite“没有这样的表”错误

时间:2018-09-13 05:55:18

标签: database sqlite go locking

我正在如下使用内存中的sqlite。

V.AngleTo(XYZ.BasisX)

在我的主函数中,创建表

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

然后我在http处理程序函数中转到“没有这样的表”。

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

启动程序时,我得到了

  

通过服务器名称获取代理时发生错误:无此类表:代理

db模式(省略属性)

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,
);

4 个答案:

答案 0 :(得分:1)

如果您使用与在此处发布的表相同的模式来创建表,则永远不会创建该表,因为该模式存在语法错误,应该是这样

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

答案 1 :(得分:1)

:memory:为每个连接打开一个单独的数据库。改用file::memory:?cache=shared

更新:使用上述代码也遇到了一些锁定问题,在我看来,在测试中使用:memory:db.DB().SetMaxOpenConns(1)是更好的解决方案。

答案 2 :(得分:0)

当我尝试使用有错误的事务时,发生“内存中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 {

此错误之后,使用过的表崩溃了。

答案 3 :(得分:0)

也许这会对某人有所帮助

我对“没有这样的桌子”也有同样的问题,并找到了确切的解释:

如果在下一次查询之前未关闭sql.Rows,则驱动程序在下一次查询时不返回此类表。仅内存存储存在问题,对文件支持的db的相同测试运行良好。

在那之后,我找到了我忘记做的rows.Close()代码部分,将其修复,现在可以正常使用了。

原始答案:https://github.com/mattn/go-sqlite3/issues/511#issuecomment-396290916