如何在一个单独的事务中运行多个普通的SQL查询?

时间:2016-07-29 12:58:57

标签: sql-server scala jdbc playframework slick

我有一个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。

3 个答案:

答案 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[...]

如果您觉得更容易,可以用forflatMap替换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')

db<>fiddle demo