Golang数据库行扫描与动态列数处理的插入记录实现
Golang数据库行扫描与动态列数处理的插入记录实现 我正在尝试编写一个程序,用于从数据库检索数据、修改数据并将数据插入到另一个表中。我只能在运行时获知列名和表名。以下是我目前已经实现的部分代码。唯一还没解决的部分是如何修改检索到的值。任何帮助都将不胜感激。
func ETL() {
dbconn, err := sql.Open("mssql", "server=localhost;user id=[gouser];password=[password];database=test;Trusted_Connection=yes;connection timeout=30;")
if err != nil {
log.Fatal(err)
}
rows, err := dbconn.Query("select name, address1, email from t_people")
cols, err := rows.Columns()
vals := make([]interface{}, len(cols))
for i := range cols {
var ii interface{}
vals[i] = &ii
}
for rows.Next() {
err = rows.Scan(vals...)
}
// vals["name"] = "New Name" ??????????
// vals["address1"] = "New Address" ??????????
// vals["email"] = "New Email" ??????????
tx, _ := dbconn.Begin()
stmt, txerr := tx.Prepare("insert into t_people_new(name, address1, email) values (?,?,?)")
if txerr != nil {
log.Fatal(txerr)
}
_, err = stmt.Exec(vals...)
if err != nil {
log.Fatal(err)
}
}
更多关于Golang数据库行扫描与动态列数处理的插入记录实现的实战教程也可以访问 https://www.itying.com/category-94-b0.html
本杰明,
今晚下班回家后(等孩子们睡着后)我会尝试一下。感谢你抽时间回复我的帖子,我真的很感激。
我会从另一个表或初始化文件中读取这些信息。在这个示例中,我认为将SQL硬编码在字符串中会更简单。
我还有一个问题要请教您。我应该如何处理blob字段?它们通常以[]byte数组的形式返回。
另外,你是每次只检索一条记录还是多条记录?如果是单条记录,你可以使用映射而不是接口。(多条记录也适用,但没那么直接)
我将获取多条记录。
radovskyb:
tx, err := dbconn.Begin() if err != nil { log.Fatalln(err) }
感谢,这个方法有效。
哦,明白了。在你的示例中,你正在从 t_people 表中选择数据,并试图更改 t_people 表的列。在运行时你将如何知道要选择哪些字段和从哪个表进行选择?
radovskyb:
) type Person struct {
你好本杰明,
我正在尝试构建一个供企业使用的工具。在编码过程中我不会知道表的名称,只有在运行时才能获知。
type Person struct {
}
我建议为表格类型设置一个特定的结构体。以下是我认为您想要实现的示例:
package main
import (
"database/sql"
"log"
)
type Person struct {
Name string
Addr string
Email string
}
func main() {
dbconn, err := sql.Open("mssql", "server=localhost;user id=[gouser];password=[password];database=test;Trusted_Connection=yes;connection timeout=30;")
if err != nil {
log.Fatal(err)
}
var people []*Person
rows, err := dbconn.Query("select name, address1, email from t_people")
if err != nil {
// 处理错误
}
for rows.Next() {
var p Person
err := rows.Scan(&p.Name, &p.Addr, &p.Email)
if err != nil {
// 处理错误
}
// 在此处或下方更新结构体中的属性
// p.Name = "新姓名"
people = append(people, &p)
}
if err := rows.Err(); err != nil {
// 处理错误
}
// 如果未在上方更改,在此处更新人员或个人的值
people[0].Name = "返回的第一个人员的新姓名"
// 在此处执行插入操作
}
你可以使用一些映射,如下所示…我在我的电脑上修改了一些内容,创建了一个实际可运行的示例:
package main
import (
"database/sql"
"log"
_ "github.com/mattn/go-sqlite3"
)
func main() {
dbconn, err := sql.Open("sqlite3", "dbtest.db")
if err != nil {
log.Fatal(err)
}
rows, err := dbconn.Query("select name, email from users")
if err != nil {
log.Fatalln(err)
}
cols, err := rows.Columns()
if err != nil {
log.Fatalln(err)
}
// 列名到值的映射。
var maps = []map[string]interface{}{}
for rows.Next() {
vals := make([]interface{}, len(cols))
for i := range cols {
var ii interface{}
vals[i] = &ii
}
err := rows.Scan(vals...)
if err != nil {
log.Fatalln(err)
}
m := map[string]interface{}{}
for i, colName := range cols {
val := vals[i].(*interface{})
m[colName] = *val
}
// 在此处或下方更新映射中的属性。
m["name"] = "New name"
maps = append(maps, m)
}
if err := rows.Err(); err != nil {
log.Fatalln(err)
}
// 在此处插入。
}
如果你不需要像我的示例那样将记录实际保存在内存中,这里有一个完整的可运行示例,用于更新记录和插入数据。
我展示了一个使表和字段动态化的示例,但我的示例实际上并不具备SQL注入防护功能,仅供参考 :)
package main
import (
"database/sql"
"fmt"
"log"
"strings"
_ "github.com/mattn/go-sqlite3"
)
func main() {
tableName := "users"
fields := []string{"name", "email"}
dbconn, err := sql.Open("sqlite3", "dbtest.db")
if err != nil {
log.Fatal(err)
}
rows, err := dbconn.Query("select name, email from " + tableName)
if err != nil {
log.Fatalln(err)
}
cols, err := rows.Columns()
if err != nil {
log.Fatalln(err)
}
// tx for inserting.
tx, err := dbconn.Begin()
if err != nil {
log.Fatalln(err)
}
query := fmt.Sprintf("insert into %s_new(%s) values (%s)",
tableName,
strings.Join(fields, ", "),
strings.TrimSuffix(strings.Repeat("?,", len(fields)), ","),
)
stmt, txerr := tx.Prepare(query)
if txerr != nil {
log.Fatal(txerr)
}
for rows.Next() {
vals := make([]interface{}, len(cols))
for i := range cols {
var ii interface{}
vals[i] = &ii
}
err := rows.Scan(vals...)
if err != nil {
log.Fatalln(err)
}
m := map[string]interface{}{}
for i, colName := range cols {
val := vals[i].(*interface{})
m[colName] = *val
}
var args []interface{}
for _, field := range fields {
if _, found := m[field]; !found {
continue
}
// Update attributes in map here or further down below.
m[field] = fmt.Sprintf("%s (New)", m[field])
args = append(args, m[field])
}
_, err = stmt.Exec(args...)
if err != nil {
log.Fatal(err)
}
}
if err := rows.Err(); err != nil {
log.Fatalln(err)
}
// Save commits.
if err := tx.Commit(); err != nil {
log.Fatalln(err)
}
}


