简体   繁体   English

PostgreSQL插入多个表和行

[英]PostgreSQL inserting multiple tables and rows

I have 2 structs one Company the other Service. 我有2个结构,一个公司,另一个服务。 They have a has-many relationship company to service. 他们有has-many关系公司要服务。 I'm trying to write an SQL query that will insert a company and multiple services attached to that company in one query. 我正在尝试编写一个SQL查询,该查询将在一个查询中插入公司和附加到该公司的多个服务。

RAW SQL: 原始SQL:

WITH company AS ( INSERT INTO companies(id, name) VALUES('1', 'acme') RETURNING id)
INSERT INTO services(id, company_id, name) VALUES
('1', (select company.id from company), 'cool service'),
('2', (select company.id from company), 'cooler service');

I'm trying to imitate this using go's sql package. 我正在尝试使用go的sql包来模仿它。 This is my attempt thus far: I've added the structs at the top just for clarity 到目前为止,这是我的尝试:为了清楚起见,我在顶部添加了结构

c := &Company{
    ID: uuid.NewV4().String(),
    Name: "test comp",
}

s := []*Service{
    &Service{
        ID: uuid.NewV4().String(),
        CompanyID: c.ID,
        Name: "test svc",
    },
}

c.Service = s

values := []interface{}{
    c.ID,
    c.Name,
}

q := `
    WITH company as (INSERT INTO companies(id, name) VALUES ($1, $2)) INSERT INTO services(id, company_id, name) VALUES
`

for _, row := range c.Services {
    q += "($1, $2, $3),"
    values = append(values, row.ID, row.CompanyID)
}

q = strings.TrimSuffix(q, ",")

stmt, err := s.DB.Prepare(q)
if err != nil {
    return err
}

if _, err := stmt.Exec(values...); err != nil {
    return err
}

I'm not sure how else to go about this but with this method I get this error: 我不确定该如何处理,但是使用这种方法会出现以下错误:

ERROR #08P01 bind message supplies 5 parameters, but prepared statement "1" requires 3

Which makes sense I'm passing 5 parameters to exec when prepared statement "1" which I'm guessing is the second one only requires 3. But how can I perform my query without having to split it up into more than 1 query? 当准备好的语句“ 1”(我猜是第二个)仅需要3时,我将5个参数传递给exec是有意义的。但是如何执行我的查询而不必将其拆分为多个查询?

Just as your error message says, your SQL statement only uses 3 bind variables: 就像您的错误消息所述,您的SQL语句仅使用3个绑定变量:

   WITH company as (INSERT INTO companies(id, name) VALUES ($1, $2)) INSERT INTO services(id, company_id, name) VALUES

and: 和:

    q += "($1, $2, $3),"

You're simply repeating $1 , $2 , and $3 for each of your rows. 您只需为每个行重复$1$2$3 So your constructed query will look something like: 因此,您构造的查询将类似于:

WITH company as (INSERT INTO companies(id, name) VALUES ($1, $2)) INSERT INTO services(id, company_id, name) VALUES
($1, $2, $3),($1, $2, $3),($1, $2, $3),($1, $2, $3),

Clearly that's not what you want. 显然,这不是您想要的。 You need to increment your bind variable numbering with each iteration through the loop. 您需要在循环中的每次迭代中增加绑定变量编号。

My approach would probably be something like: 我的方法可能是这样的:

var i int = 3
for _, row := range c.Services {
    q += fmt.Sprintf("($%d, $%d, $%d),", i, i+1, i+2)
    values = append(values, row.ID, row.CompanyID)
    i += 3
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM