PostgreSQL插入多个表和行

时间:2017-02-25 21:42:52

标签: sql postgresql go

我有2个结构,一个公司是另一个服务。他们有一个has-many关系公司来服务。我正在尝试编写一个SQL查询,该查询将在一个查询中插入公司和附加到该公司的多个服务。

RAW 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');

我试图使用go的sql包来模仿这个。这是我迄今为止的尝试:为了清晰起见,我在顶部添加了结构

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
}

我不知道怎么回事,但是这个方法我得到了这个错误:

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

有意义的是,当准备好的语句" 1"时,我将5个参数传递给exec。我猜测的第二个只需要3.但是如何在不必将其分成多个查询的情况下执行查询?

1 个答案:

答案 0 :(得分:0)

正如您的错误消息所示,您的SQL语句仅使用3个绑定变量:

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

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

您只需为每一行重复$1$2$3。因此,您构造的查询将类似于:

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),

显然,这不是你想要的。您需要在循环中每次迭代时增加绑定变量编号。

我的方法可能是:

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
}