我正在使用martini,golang和postgresql构建一个社交网络类型服务器,以帮助我发展这三种技能。我想到的几个关键事项是如何将用户表中的主键插入用户信息表的正确行(以将用户信息与特定用户连接)。我确信还有一种方法可以将这两个查询合并为一个更简洁的postgres脚本...
func CreateUser(ren render.Render, r *http.Request, db *sql.DB) {
_, err := db.Query("INSERT INTO users (first, last, email, password, karma, value) SELECT CAST ($3 AS VARCHAR), $1, $2, $4, $5, $6 WHERE NOT EXISTS (SELECT * FROM users WHERE email = $3)",
r.FormValue("first"),
r.FormValue("last"),
r.FormValue("email"),
r.FormValue("password"),
0,
0)
PanicIf(err)
_, err = db.Query("INSERT INTO userinfo (usr, dob, phonenum, bio, mates, bought, sold) VALUES ($1, $2, $3, $4, $5, $6, $7)",
0,
r.FormValue("dob"),
r.FormValue("phonenum"),
r.FormValue("bio"),
0,
0,
0)
PanicIf(err)
ren.Redirect("/")
}
以下是创建用户表的脚本:
DROP TABLE IF EXISTS "public"."users";
CREATE TABLE "public"."users" (
"id" serial NOT NULL,
"first" varchar(40) NOT NULL COLLATE "default",
"last" varchar(40) NOT NULL COLLATE "default",
"email" varchar(40) NOT NULL COLLATE "default",
"password" varchar(40) NOT NULL COLLATE "default",
"karma" int NOT NULL,
"value" int NOT NULL
)
WITH (OIDS=FALSE);
我意识到在生产级别代码中我不想像这样存储密码。我也有点被如何将非全局参数拉入数据库,因为它是由m.get&创建的。 m.post命令。
m.Post("/newuser", CreateUser)
m.Get("/user", NewUser)
任何关于将用户密钥合并并添加到userinfo中相应条目的建议都将非常感激......我意识到这些可能是非常愚蠢的问题,但请原谅我的天真。
答案 0 :(得分:0)
我是通过从第一个查询中返回插入的用户ID并在第二个查询中使用它来完成的,但我没有使用upsert。
因此,您可以尝试使用RETURNING返回新添加的用户的ID或通过电子邮件单独查询(因为在这种情况下,电子邮件看起来像每个用户唯一)。
然后将其用于第二次查询:
_, err = db.Query(`INSERT INTO userinfo (usr, dob, phonenum, bio, mates, bought, sold)
VALUES ($1, $2, $3, $4, $5, $6, $7)`,
id, // there
r.FormValue("dob"),
r.FormValue("phonenum"),
...
我认为usr
是用户ID(users.id
的外键)
示例源代码:
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
"log"
)
func main() {
db, err := sql.Open("postgres", "user=alex dbname=tmp sslmode=disable")
if err != nil {
log.Fatal(err)
}
rows, err := db.Query(`
INSERT INTO users (first, last, email, password, karma, value)
SELECT CAST ($3 AS VARCHAR), $1, $2, $4, $5, $6
WHERE NOT EXISTS (SELECT * FROM users WHERE email = $3)
RETURNING id`,
"first", "last", "email", "password", 0, 0)
defer rows.Close()
if err != nil {
log.Fatal(err)
}
if rows.Next() {
id := 0
rows.Scan(&id)
_, err = db.Exec(`INSERT INTO userinfo (user_id, info) VALUES ($1, $2)`, id, "info")
if err != nil {
log.Fatal(err)
}
fmt.Println("Inserted:", id)
}
}
我个人更喜欢使用QueryRow而不是查询,因为更明显的是返回一行,但它也适用于Query。
另外,我建议使用唯一索引来代替子查询。