問題

私はScalaのSlickとPostgreSQLを使用しています。 私は単一のPKを持つテーブルでうまくいっています。 今私は複数のPKでテーブルを使用する必要があります:

 case class Report(f1: DateTime,
    f2: String,
    f3: Double)

class Reports(tag: Tag) extends Table[Report](tag, "Reports") {
    def f1 = column[DateTime]("f1")
    def f2 = column[String]("f2")
    def f3 = column[Double]("f3")

    def * = (f1, f2, f3) <> (Report.tupled, Report.unapply)
    def pk = primaryKey("pk_report", (f1, f2))
}

val reports = TableQuery[Reports]
 

空のテーブルがあり、reports.insert(report)を使用するとうまくいきます。 しかし、reports.insertOrUpdate(report)を使用すると、受信して例外が発生します。

 Exception in thread "main" org.postgresql.util.PSQLException: ERROR: syntax error at end of input
  Position: 76
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:500)
    at ....
 

私は間違って何をしていますか?それを修正するには?

前もって感謝します。


PS。私は回避策を試しました - "存在する場合は、else insert"ロジックを実装しようとしました:

   val len = reports.withFilter(_.f1 === report.f1).withFilter(_.f2 === report.f2).length.run.toInt
                    if(len == 1) {
                        println("Update: " + report)
                        reports.update(report)
                    } else {
                        println("Insert: " + report)
                        reports.insert(report)
                    }
 

しかし、私はまだ更新時に例外が発生します:

 Exception in thread "main" org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "pk_report"
  Detail: Key ("f1", f2)=(2014-01-31 04:00:00, addon_io.aha.connect) already exists.
 

  ベストアンサー

あなたの最初の質問に関して、複合キーを持つテーブルのinsertorupdateはSlick(少なくともpgSQLで)で壊れているので、エラーはあなたの側にはありません。バグレポートを参照してください。例えば、ここ: https://github.com/slick/slick/issues/966

したがって、回避策を設計する必要がありますが、「upsert」操作は競合状態になりやすく、PostgreSQLがこれを実行するためのネイティブ機能を提供しないため、適切に設計するのは非常に難しいです。例えば、 http://www.depesz.com/2012/06/10/why-is-upsert-so-complicated/

とにかく、競合状態が少ない操作を実行する別の方法は、最初に更新することです(行が存在しない場合は何もしません)。行が存在しない場合にのみ挿入される "insert select"クエリを実行します。

  同じタグがついた質問を見る

postgresqlscalaslickcomposite-primary-keyupsert