0

为避免 DRY,我试图创建一个带有可变列名的 sql INSERT 语句和通过 ScalikeJDBC 的 sql 插值填充这些列的数据:

case class MySQLInsertMessage(tableName:String, columns:List[String], values:List[String])
def depositMessage(msg: MySQLInsertMessage): Unit = {
      NamedDB('MySQLMsgDepositor) localTx { implicit session =>
        val sqlStmt = sql"INSERT INTO ${msg.tableName} (${msg.columns}) VALUES (${msg.values})"
        println("The sql statement is: " + sqlStmt.statement)
        println("The parameters are: " + sqlStmt.parameters)
        sqlStmt.update().apply()
      }
    }

当我用以下方式调用它时:

depositMessage(MySQLInsertMessage("My_Table", List("key", "email"), List("42", "user@email.com")))

生成的控制台打印输出是:

sql语句为: INSERT INTO ? (?, ?) 值 (?, ?)

参数为:List(My_Table, key, email, 42, user@email.com)

您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取在 ''My_Table' ('key', 'email') VALUES ('42', 'user@emai' at line 1 java.sql.SQLSyntaxErrorException:您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本相对应的手册,了解在 ''My_Table' ('key', 'email') VALUES ('42', 'user@emai' 附近使用的正确语法在第 1 行

我尝试将其包装sql"..."为:sql"""...""",但这似乎没有什么区别。我可以在我的 MySQL 工作台 GUI 中很好地执行预期的语句。知道我的语法错误是什么吗?

4

1 回答 1

0

源于@scaisEdge 的提示,似乎 ScalikeJDBC 在使用其语法时,总是会在任何参数化值周围放置单引号。从这里判断 - https://github.com/scalikejdbc/scalikejdbc/issues/320 - 这是一个已知问题。

使用 MySQLINSERT语句(或其他语句),您的表名或列值可能没有单引号,尽管它们可以有反引号。

您可以使用他们的SQLSyntax.createUnsafely(str:String)方法,或者,如果我想像上面那样做,而不是使用sql"...",我可以使用旧的方法SQL(s"INSERT INTO ${msg.tableName} (${msg.columns.mkString(",")})")

注意 - 我相信这两种情况都会让您容易受到注入攻击。因为,对我来说,这是一个本地 API,无论使用它,你都必须拥有数据库的用户名和密码,所以我将采用createUnsafely做事的方式,用一点正则表达式“清理器”来处理一些不雅的部分心意:

def depositMessage(msg: MySQLInsertMessage): Unit = {
      NamedDB('MySQLMsgDepositor) localTx { implicit session =>
        val unsafeSQLRegex = "[`'\"]".r
        val table = SQLSyntax.createUnsafely(s"`${unsafeSQLRegex.replaceAllIn(msg.tableName, "")}`")
        val columns = SQLSyntax.createUnsafely(msg.columns.map(value => unsafeSQLRegex.replaceAllIn(value, "")).mkString("`", "`, `", "`"))
        val sqlStmt = sql"INSERT INTO $table ($columns) VALUES (${msg.values})".update().apply()
      }
    }
  }
于 2018-03-28T22:04:58.410 回答