Postgresql 仅使用Slick插入所有新记录
[PSQLException:错误:重复的键值违反了唯一约束 “dictionary\u word\u idx”详细信息:关键字(word)=(odirane)已存在。] 我有防止任何重复的唯一索引。我想知道如何插入一个包含数千个元素但只有新元素的数组?我正在使用Slick 1.0.1和Postgresql 9.1 编辑: 我正在尝试以下方法: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/
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)