对行的唯一约束冲突会导致整个 pq。CopyIn postgresql 导入失败

我正在尝试使用 pq。CopyIn 执行批量导入,如下所述:


https://godoc.org/github.com/lib/pq


导入比我尝试过的其他方法快得多,但我发现仅在一条记录中发生唯一约束冲突将导致整个导入失败。


有没有办法设置冲突 不使用pq不做任何事情.文案。


这是我的表格结构的副本


CREATE TABLE test (

    id serial PRIMARY KEY,

    unique_token VARCHAR ( 10 ) UNIQUE NOT NULL,

    frequency INT DEFAULT 0

);

我尝试在下面使用@mkopriva答案,但我得到错误:pq:列“id”中的空值违反了非空约束


下面的代码示例


tx, _ := db.Begin()


_, err = tx.Exec(`CREATE TEMP TABLE token_temp ON COMMIT DROP AS 

   SELECT id, unique_token FROM test WITH NO DATA`)

if err != nil {

    return err

}


stmt, err := tx.Prepare(pq.CopyIn("token_temp", "unique_token"))

if err != nil {

    fmt.Println("error here")

    return err

}


for _, token := range tokenList {

    _, err = stmt.Exec(token)


    if err != nil {

        return err

    }


}


_, err = stmt.Exec()

if err != nil {

    log.Fatal(err)

}


err = stmt.Close()

if err != nil {

    log.Fatal(err)

}


_, err = tx.Exec(`INSERT INTO test SELECT id, unique_token FROM 

  token_temp   ON CONFLICT(unique_token) DO UPDATE SET frequency= 

   test.frequency + 1 `)

if err != nil {

    fmt.Println("Error")

    return err

}


err = tx.Commit()

if err != nil {

    log.Fatal(err)

}


牧羊人nacy
浏览 121回答 1
1回答

MM们

pq.CopyIn内部使用 COPY FROM,它不支持该子句。ON CONFLICT但是,您可以做的是创建一个没有约束的临时表,将数据复制到该临时表中,然后使用您的子句在目标表中执行 操作,使用临时表作为要插入的数据源。INSERTON CONFLICT一个例子应该更清楚地说明这一点,假设你有一个看起来像这样的表:usersCREATE TABLE users (    id serial PRIMARY KEY    , name text    , email text UNIQUE);假设你有一部分用户像这样:var users = []User{    {Name: "John Doe", Email: "jdoe@example.com"},    {Name: "Joe Blow", Email: "jblow@example.com"},    {Name: "Jane Doe", Email: "jdoe@example.com"}, // duplicate email!    {Name: "Foo Bar", Email: "fbar@example.com"},}这样,您可以执行以下操作:_, err = txn.Exec(`CREATE TEMP TABLE users_tempON COMMIT DROPAS SELECT * FROM usersWITH NO DATA`)if err != nil {    panic(err)}stmt, err := txn.Prepare(pq.CopyIn("users_temp", "name", "email"))if err != nil {    panic(err)}for _, u := range users {    if _, err := stmt.Exec(u.Name, u.Email); err != nil {        panic(err)    }}if _, err := stmt.Exec(); err != nil {    panic(err)}if err := stmt.Close(); err != nil {    panic(err)}_, err = txn.Exec(`INSERT INTO users (name, email)SELECT name, email FROM users_tempON CONFLICT DO NOTHING`)if err != nil {    panic(err)}if err := txn.Commit(); err != nil {    panic(err)}运行上述操作后,您可以这样做,您将获得以下内容:SELECT * FROM users; id |   name   |       email----+----------+-------------------  1 | John Doe | jdoe@example.com  2 | Joe Blow | jblow@example.com  4 | Foo Bar  | fbar@example.com(3 rows)对于特定的示例和要求,您可以在查询中执行如下操作:INSERT ... SELECT ..._, err = txn.Exec(`INSERT INTO test (unique_token, frequency)SELECT unique_token, COUNT(*) FROM token_tempGROUP BY unique_token`)if err != nil {    panic(err)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go