Postgresql 仅使用Slick插入所有新记录

Postgresql 仅使用Slick插入所有新记录,postgresql,scala,slick,Postgresql,Scala,Slick,[PSQLException:错误:重复的键值违反了唯一约束 “dictionary\u word\u idx”详细信息:关键字(word)=(odirane)已存在。] 我有防止任何重复的唯一索引。我想知道如何插入一个包含数千个元素但只有新元素的数组?我正在使用Slick 1.0.1和Postgresql 9.1 编辑: 我正在尝试以下方法: def run = { val source = scala.io.Source.fromFile("/home/user/dev/

[PSQLException:错误:重复的键值违反了唯一约束 “dictionary\u word\u idx”详细信息:关键字(word)=(odirane)已存在。]

我有防止任何重复的唯一索引。我想知道如何插入一个包含数千个元素但只有新元素的数组?我正在使用Slick 1.0.1和Postgresql 9.1

编辑: 我正在尝试以下方法:

    def run = {
      val source = scala.io.Source.fromFile("/home/user/dev/txt/test1.txt")
      val lines = source.mkString
      source.close()

      val words = lines.split("[^\\p{Ll}]").distinct

      database withTransaction {

        val q = for {
            w <- words.toList
            row <- Dictionary if row.word != w  
        } yield w


        Dictionary.autoInc.insertAll(q: _*)
      }


      words.length
    }
def运行={
val source=scala.io.source.fromFile(“/home/user/dev/txt/test1.txt”)
val line=source.mkString
source.close()
val words=lines.split(“[^\\p{Ll}]”)。不同
带有事务的数据库{
val q=用于{
w概念上:

def insertAll[T](items: Seq[T]): Seq[Either[(T, Exception), (T, Int)]] = items.map { i =>
  try {
    // Perform an insert supposing returns and int representing the PK on the table
    val pk = …
    Right(i, pk)
  } catch {
    case e: Exception => Left(i, e)
  }
}
执行每个插入操作,然后根据结果返回一个左或右对象,该对象跟踪最终结果,并为您提供解释该操作的详细上下文

编辑

假设您的DAO对象如下所示:

object Dictionary extends Table[Word]("dictionary") {
   // ...
}
其中,
Word
是您的对象模型,而且您已经提供了螺母和螺栓(我可以从粘贴的代码推断),它应该是(其中
words
是一个
Seq[Word]
):

您得到的是一个
序列,它封装了用于进一步处理的结果

注意事项 me提供的解决方案尝试乐观地对DB执行操作,而无需根据DB的状态预过滤列表。 通常,在多用户应用程序中,预筛选是有问题的,前提是您不能假设在执行筛选后没有人在预筛选列表中添加单词。 更简单地说:唯一性约束是DBMS提供的一个健壮的特性,利用它比重新发明更好。
您在上面编辑的解决方案是无解决方案,因为您仍然需要面对可能的PK冲突异常。

另一种选择是编写原始SQL。Postgres没有默认的方法来忽略重复时的
,但您可以用几种不同的方法模拟它,如下所示

再加上

编辑:

这里有一个例子

def insert(c: String) =
    (Q.u + """INSERT INTO dictionary
        (word)
    SELECT""" +?  c + 
    """WHERE
        NOT EXISTS (
            SELECT word FROM dictionary WHERE word = """ +? c + ")"
    ).execute

val words = lines.split("[^\\p{Ll}]")

words.foreach(insert)
这就是你所说的“立刻”吗?我认为这将是最有效的方式,而不是发疯

如果速度太慢,还有一个建议是创建一个没有唯一约束的临时表,将当前表复制到临时表中,将新词插入临时表中,然后从该表中选择distinct。如下所示:


但我认为这太过分了。除非你有一些疯狂的要求或什么。

我不太理解你的答案。也许一个示例实现和使用会有所帮助。请提供你的字典DAO定义并查看我以前的评论。这种方法一个接一个地插入记录,速度非常慢。你可以吗请添加示例,说明如何在不存在的情况下构造一个插入,从Seq[String]一次插入(如果重复,则不插入)所有新值?
object Dictionary extends Table[Word]("dictionary") {
   // ...
}
words.map { w => 
  try {
    Right(w, Dictionary.autoInc.insert(w))
  } catch {
    case e: Exception => Left(w, e)
  }
}
def insert(c: String) =
    (Q.u + """INSERT INTO dictionary
        (word)
    SELECT""" +?  c + 
    """WHERE
        NOT EXISTS (
            SELECT word FROM dictionary WHERE word = """ +? c + ")"
    ).execute

val words = lines.split("[^\\p{Ll}]")

words.foreach(insert)