我有一个Play / Slick应用程序,我需要在单个事务中运行多个普通的sql查询,检索上一个查询的结果,如下所示:
val id: Future[Int] = db.run {
sql"""
DECLARE @T TABLE (id INTEGER)
INSERT INTO Foo (name) OUTPUT INSERTED.id INTO @T VALUES ('bar')
SELECT id FROM @T
""".as[Int].head
}
上面的问题是它总是返回1
,它是声明临时表的顶级查询的结果。如何获取最后一个查询的结果呢?有问题的数据库是MS SQL Server。播放2.5.4,Slick 3.1.1。
答案 0 :(得分:9)
Slick Action
的一个最重要的功能是它们是可组合的,类似于Scala Future
。恕我直言,文档并没有像它那样对待它......这是一个例子:
val createAction = sqlu"""DECLARE @T TABLE (id INTEGER)"""
val insertAction = sqlu"""INSERT INTO Foo (name) OUTPUT INSERTED.id INTO @T VALUES ('bar')"""
val selectAction = sql"""SELECT id FROM @T""".as[Int].head
val composedAction = for {
createRes <- createAction
insertRes <- insertAction
selectRes <- selectAction
} yield selectRes
val id = db.run(composedAction.transactionally) // Future[...]
如果您觉得更容易,可以用for
和flatMap
替换map
理解。
Slick还有两个方便的助手,即DBIO.seq
(按顺序运行查询,丢弃结果,返回Unit
)和DBIO.sequence
(相同但保留所有单个操作的结果。)
答案 1 :(得分:0)
如何使用DBIO.seq()。由于DBIO.seq返回Unit,因此selectAction后跟byThen()。
val createAction = sqlu"""DECLARE @T TABLE (id INTEGER)"""
val insertAction = sqlu"""INSERT INTO Foo (name) OUTPUT INSERTED.id INTO @T VALUES ('bar')"""
val selectAction = sql"""SELECT id FROM @T""".as[Int].head
val id = db.run(DBIO.seq(createAction, insertAction) andThen selectAction)
答案 2 :(得分:0)
为了扩展现有的答案,提供的查询可以通过省略 INTO clause
作为单个查询运行。相反:
DECLARE @T TABLE (id INTEGER)
INSERT INTO Foo (name) OUTPUT INSERTED.id INTO @T VALUES ('bar')
SELECT id FROM @T
可以使用以下内容:
INSERT INTO Foo (name) OUTPUT INSERTED.id VALUES ('bar')