【问题标题】:Conditional drop of tables in slick有条件地删除表格
【发布时间】:2015-04-21 12:40:56
【问题描述】:

知道如何在 Slick 3.0 中进行有条件的删除,以防止 An exception or error caused a run to abort: Unknown table 'MY_TABLE' 因某种原因不存在吗?

def clear = {
    val operations = DBIO.seq(
      myTable.schema.drop,
      // other table definitions
      ...
    )
    db.run(operations)
  }

【问题讨论】:

    标签: mysql scala slick-3.0


    【解决方案1】:

    我走的是 MTable 路线,但至少在 Postgres 中这是一个很大的麻烦。

    试试

    def qDropSchema = sqlu"""drop table if exists your-table-name;""";
    

    注意表名是否区分大小写。我在那里的 postgres 遇到了奇怪的问题 - 不知道 mysql。

    【讨论】:

      【解决方案2】:

      让我尝试回答您的问题,我认为您可以先使用MTable 检查表的可用性,然后如果存在则将其删除。或多或少像下面这样:

      import scala.slick.jdbc.meta._
      if (MTable.getTables("table_name").list().isEmpty) {
          //do something here..
      }
      

      【讨论】:

      • 这个例子不能在 slick 3.0 中编译
      【解决方案3】:

      我这样做了:

      val personQuery = TableQuery[PersonTable]
      val addressQuery = TableQuery[AddressTable]
      ...
      val setupAction = DBIO.seq(
        sqlu"SET FOREIGN_KEY_CHECKS = 0",
        sqlu"DROP TABLE IF EXISTS #${personQuery.baseTableRow.tableName}",
        sqlu"DROP TABLE IF EXISTS #${addressQuery.baseTableRow.tableName}",
        sqlu"SET FOREIGN_KEY_CHECKS = 1",
      )
      val setupFuture = db.run(setupAction)
      

      注意你需要如何使用 #${} 而不是 ${} 否则 slick 会触发类似:

      DROP TABLE IF EXISTS 'PERSON'
      

      这行不通

      【讨论】:

        【解决方案4】:

        我目前正在使用 3.2.0 版本的 Slick 框架。 我给出的解决方案可能适用于框架的早期版本,但我没有验证这一点。

        如果唯一的问题是删除表(如果它存在)不抛出异常,您可以为此使用 Actions 的组合器。

        我有一系列测试,我为内存数据库中的 H2 上的每个测试运行 create/populate/drop 语句。 我想你有两个表 CanalSubCanal (SubCanal 在 Canal 上有一个外键,所以如果它存在,你想先删除它)因为你已经声明了 TableQuery 变量,例如:

        lazy val canals = TableQuery[CanalTable]
        lazy val subcanals = TableQuery[SubCanalTable]
        
        // we don't put SubCanals to check if no exeption is produced and then 
        // add it for further testing.
        lazy val ddl = canals.schema // ++ subcanals.schema
        

        ...我提供的辅助方法如下:

        def create: DBIO[Unit] = ddl.create
        def drop: DBIO[Unit] = ddl.drop
        
        def popCanal = canals ++= Seq(
            Canal("Chat"),
            Canal("Web"),
            Canal("Mail"))
        

        以上只是创建动作,但很酷的是 Slick 将尝试删除 SubCanal 表和 Canal 表,但会将异常封装在 Try[...] 中。所以这将顺利运行:

        val db = Database.forConfig("yourBaseConfig")
        val res = db.run(drop)
        

        这也将运行:

        val db = Database.forConfig("yourBaseConfig")
        val res1 = db.run(
          create >>
            popCanal >>
            canals.result        
        )
        
        .... some interesting computation ...
        
        val res2 = db.run(drop)
        

        注意:SubCanal 方案仍处于注释状态,因此目前从未执行过,但是应用了丢弃并失败到此表,但不会引发异常。

        更多关于组合动作(combinator):

        【讨论】:

          猜你喜欢
          • 2016-01-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-09-26
          • 2014-08-25
          • 2017-12-15
          • 1970-01-01
          相关资源
          最近更新 更多