我有一个表格,我有一个字段存储一个非常大的数字(math.big,比uint64大)。我将它存储在DECIMAL类型中:
difficulty NUMERIC NOT NULL,
那么,如何使用Go
库(PQ
)从github.com/lib/pq
代码插入此字段?
此代码不起作用:
me@desk:~/src/github.com/myapp/misc$ cat insertbig.go
package main
import (
"database/sql"
_ "github.com/lib/pq"
"os"
"log"
"math/big"
)
func main() {
var err error
var db *sql.DB
std_out:=log.New(os.Stdout,"",0)
conn_str:="user='testuser' dbname='testdb' password='testpasswd'";
db,err=sql.Open("postgres",conn_str);
if (err!=nil) {
log.Fatal(err);
}
_,err=db.Exec("CREATE TABLE bigtable(difficulty NUMERIC)");
difficulty:=big.NewInt(0);
difficulty.SetString("1111111111111111111111111111111111111111111111111111111111111111111111",10);
_,err=db.Exec("INSERT INTO bigtable(difficulty) VALUES(?)",difficulty);
if (err!=nil) {
log.Fatal(err);
} else {
std_out.Println("record was inserted");
}
}
me@desk:~/src/github.com/myapp/misc$
它给了我这个错误:
2018/02/05 17:00:25 sql: converting argument $1 type: unsupported type big.Int, a struct
答案 0 :(得分:3)
首先,您应该对PostgreSQL使用数字占位符($1
,$2
,...),因为它是本机使用的。至于将bignum放入数据库中的numeric
列,快速浏览文档和源表明您最好的选择是使用字符串(PostgreSQL将其视为“未知”类型的值)然后让PostgreSQL解析它并根据列的(已知)类型进行转换。
这样的事情:
difficulty := "1111111111111111111111111111111111111111111111111111111111111111111111"
_, err = db.Exec("INSERT INTO bigtable (difficulty) VALUES ($1)", difficulty)
类似的方法适用于驱动程序本身无法理解的任何其他PostgreSQL类型;总会有一个字符串表示,你可以使用它来实现它。
您还可以type SQLBigInt big.Int
并实施driver.Valuer
的{{1}}界面:
database/sql/driver
然后可能type SQLBigInt big.Int
func (i *SQLBigInt) Value() (driver.Value, error) {
return (*big.Int)(i).String(), nil
}
// Or
type SQLBigInt struct {
big.Int
}
func (i *SQLBigInt) Value() (driver.Value, error) {
return i.String(), nil
}
来自sql.Scanner
进行阅读,但这可能会变得很丑陋,可能不值得付出努力,因为无论如何你总是要打包和解包。
答案 1 :(得分:0)
您可以实现评估器和扫描仪界面
//BigInt big.Int alias
type BigInt struct {
big.Int
}
// Value implements the Valuer interface for BigInt
func (b *BigInt) Value() (driver.Value, error) {
if b != nil {
return b.String(), nil
}
return nil, nil
}
// Scan implements the Scanner interface for BigInt
func (b *BigInt) Scan(value interface{}) error {
var i sql.NullString
if err := i.Scan(value); err != nil {
return err
}
if _, ok := b.SetString(i.String, 10); ok {
return nil
}
return fmt.Errorf("Could not scan type %T into BigInt", value)
}
答案 2 :(得分:0)
我遇到了类似的问题并尝试构建 this 包:
示例使用:
import (
"github.com/d-fal/bigint"
)
type TableWithBigint struct {
Id uint64
Name string
Deposit *bigint.Bigint
}