使用Go查询sqlite数据库,但是没有将任何行扫描到变量中。

huangapple go评论85阅读模式
英文:

Querying sqlite db with Go but none of the rows are being scanned into variables

问题

我正在使用Go通过以下代码运行一个查询:

stmt, err := db.Prepare(sqlstring)
if err != nil{
    log.Fatal(err)
}
defer stmt.Close()

这是带有'安'的SQL字符串:

select
  k_ele.value as kanji,  id as k_ele_id,
  NULL as r_ele_id, NULL as r_ele_val,
  NULL as gloss_id, NULL as gloss_val
from k_ele where value like ?
UNION ALL
select
  k_ele.value as kanji,  NULL as k_ele_id,
  r_ele.id as r_ele_id, r_ele.value as r_ele_val,
  NULL as gloss_id, NULL as gloss_val
from
  r_ele, k_ele where k_ele.value like ? and k_ele.fk = r_ele.fk
UNION ALL
select
  k_ele.value as kanji,  NULL as k_ele_id,
  NULL as r_ele_id, NULL as r_ele_val,
  gloss.id as gloss_id, gloss.value as gloss_val
from
  sense, gloss, k_ele
where
  k_ele.value like ? and
  k_ele.fk = sense.fk and
  gloss.fk = sense.id;

这个查询在控制台的sqlite3和DB Browser for SQLite中可以正常使用,并返回8行数据,甚至在Go代码中的for循环中循环了8次。

问题是在rows.Scan()期间,除了每行都出现的kanji之外,没有任何列值存储在变量中,而且在log.Println()中只打印出kanji。

rows, err := stmt.Query(parameter,parameter,parameter)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
    var kanji, r_ele_val, gloss_val string
    var k_ele_id, r_ele_id, gloss_id int

    rows.Scan(&kanji,&k_ele_id,&r_ele_id,&r_ele_val,&gloss_id,&gloss_val)
    log.Println(kanji,k_ele_id, r_ele_id,r_ele_val,gloss_id,gloss_val)
}

以下是输出结果(由于我的命令行无法打印日语字符,所以显示为?):

2015/02/11 22:18:42 ? 105921 0  0
2015/02/11 22:18:42 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0

奇怪的是,如果我改变列的顺序,例如将gloss_id和gloss_val放在select语句的最前面,每个变量都被存储为0,即使在gloss_id之前,kanji也有一个值。(这些是相同的数据集)

2015/02/11 22:23:12  0 0  0
2015/02/11 22:23:12  0 0  0
2015/02/11 22:23:13 ? 0 0  197326 cheap
2015/02/11 22:23:13 ? 0 0  197327 rash
2015/02/11 22:23:13 ? 0 0  197328 thoughtless
2015/02/11 22:23:13 ? 0 0  197329 careless
2015/02/11 22:23:13 ? 0 0  197330 indiscreet
2015/02/11 22:23:13 ? 0 0  197331 frivolous

这个SQL在sqlite3中完全正常工作,Go的for循环也正确运行了相应的次数。以下是数据应该是什么样子的。

使用Go查询sqlite数据库,但是没有将任何行扫描到变量中。

我不确定这是一个错误还是我做错了什么?我怀疑这是UNION ALL的问题,但我不确定如何使其正常工作。

编辑: 这次我让rows.Scan返回错误,并打印出列:

err := rows.Scan(&kanji,&k_ele_id,&r_ele_id,&r_ele_val,&gloss_id,&gloss_val)
if err != nil {
    log.Print("rows.Column(): ")
    log.Println(rows.Columns())
    log.Println(kanji,k_ele_id, r_ele_id,r_ele_val,gloss_id,gloss_val)
    log.Fatal(err)
}

以下是输出结果:

2015/02/12 22:38:56 rows.Column():
2015/02/12 22:38:56 [kanji k_ele_id r_ele_id r_ele_val gloss_id gloss_val] <nil>

2015/02/12 22:38:56 ? 105921 0  0
2015/02/12 22:38:56 sql: Scan error on column index 2: converting string "<nil>" to a int: strconv.ParseInt: parsing "<nil>": invalid syntax

错误消息说在列索引2(r_ele_id)尝试将字符串<nil>转换为int,但是r_ele_id不是已经是int类型了吗(如我的模式图中所示)?由于需要在此查询中使用UNION ALL,每行都会有NULL值,我认为我需要使用NullInt64类型而不是int类型。现在尝试一下并报告结果。

英文:

I am running a query through Go using

stmt, err := db.Prepare(sqlstring)
if err != nil{
	log.Fatal(err)
}
defer stmt.Close()

this is the sql string with ? being '安'

select
  k_ele.value as kanji,  id as k_ele_id,
  NULL as r_ele_id, NULL as r_ele_val,
  NULL as gloss_id, NULL as gloss_val
from k_ele where value like ?
UNION ALL
select
  k_ele.value as kanji,  NULL as k_ele_id,
  r_ele.id as r_ele_id, r_ele.value as r_ele_val,
  NULL as gloss_id, NULL as gloss_val
from
  r_ele, k_ele where k_ele.value like ? and k_ele.fk = r_ele.fk
UNION ALL
select
  k_ele.value as kanji,  NULL as k_ele_id,
  NULL as r_ele_id, NULL as r_ele_val,
  gloss.id as gloss_id, gloss.value as gloss_val
from
  sense, gloss, k_ele
where
  k_ele.value like ? and
  k_ele.fk = sense.fk and
  gloss.fk = sense.id;

This query can be used fine through sqlite3 on console and DB Browser for SQLite and returns 8 rows and even the for loop in the go code loops 8 times.

The problem is that during

rows.Scan()

none of the column values are being stored in the variables except kanji which appears in every row (since it is in every row) but nothing but kanji is printed out in log.Println().

	rows, err := stmt.Query(parameter,parameter,parameter)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()
	for rows.Next() {
		var kanji, r_ele_val, gloss_val string
		var k_ele_id, r_ele_id, gloss_id int

		rows.Scan(&amp;kanji,&amp;k_ele_id,&amp;r_ele_id,&amp;r_ele_val,&amp;gloss_id,&amp;gloss_val)
		log.Println(kanji,k_ele_id, r_ele_id,r_ele_val,gloss_id,gloss_val)
    }

Here is the output (It is ? because my cmd can't print the japanese characters (if the ? is sent to my browser, it will properly show the character)

2015/02/11 22:18:42 ? 105921 0  0
2015/02/11 22:18:42 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0
2015/02/11 22:18:43 ? 0 0  0

The strange thing is if I change the order of the columns for example putting gloss_id, gloss_val first in the select statement. Every variable gets 0 stored, even kanji before a gloss_id has a value. (These are the same sets of data)

2015/02/11 22:23:12  0 0  0
2015/02/11 22:23:12  0 0  0
2015/02/11 22:23:13 ? 0 0  197326 cheap
2015/02/11 22:23:13 ? 0 0  197327 rash
2015/02/11 22:23:13 ? 0 0  197328 thoughtless
2015/02/11 22:23:13 ? 0 0  197329 careless
2015/02/11 22:23:13 ? 0 0  197330 indiscreet
2015/02/11 22:23:13 ? 0 0  197331 frivolous

The sql works perfectly fine in sqlite3, the Golang for loop runs the correct number of times as well. Here is what the data should look like.

使用Go查询sqlite数据库,但是没有将任何行扫描到变量中。

I'm not sure if this is a bug or is there something wrong with what I'm doing? I suspect it is a problem with UNION ALL but I'm not sure how to get this working.

EDIT: I made rows.Scan return err this time as well as printout the columns

		err := rows.Scan(&amp;kanji,&amp;k_ele_id,&amp;r_ele_id,&amp;r_ele_val,&amp;gloss_id,&amp;gloss_val)
		if err != nil {
			log.Print(&quot;rows.Column(): &quot;)
			log.Println(rows.Columns())
			log.Println(kanji,k_ele_id, r_ele_id,r_ele_val,gloss_id,gloss_val)
			log.Fatal(err)
		}

2015/02/12 22:38:56 rows.Column():
2015/02/12 22:38:56 [kanji k_ele_id r_ele_id r_ele_val gloss_id gloss_val] &lt;nil&gt;

2015/02/12 22:38:56 ? 105921 0  0
2015/02/12 22:38:56 sql: Scan error on column index 2: converting string &quot;&lt;nil&gt;&quot;
 to a int: strconv.ParseInt: parsing &quot;&lt;nil&gt;&quot;: invalid syntax

The error message says that there is an attempt to convert string <nil> to int in column index 2 (r_ele_id) but isn't r_ele_id an int already (as can be seen in the picture of my schema)? Because of the need to use UNION ALL for this query there are going to be NULLs in every row, I believe I need to use type NullInt64 instead of int for the *id types. Will try this now and report back

答案1

得分: 0

Rows.Scan在不抛出错误的情况下,无法将值<nil>扫描到int和string类型中。正确的类型应该是sql.NullInt64和sql.NullString,这些类型将正确地保存值,并具有用于检查它是否为nil的bool值。

英文:

Rows.Scan will not scan value <nil> to types int and string without throwing an error. The correct type to use was sql.NullInt64 and sql.NullString, these types will hold the value properly and have a bool val that is used to check whether it is nil or not.

huangapple
  • 本文由 发表于 2015年2月12日 10:42:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/28468372.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定