如何从 SQL 查询中获取表名?

sri*_*ala 6 scala apache-spark apache-spark-sql

我想使用 Scala 从 Spark 中的 sql 查询中获取所有表名称。

假设用户发送一个 SQL 查询,它看起来像:

select * from table_1 as a left join table_2 as b on a.id=b.id
Run Code Online (Sandbox Code Playgroud)

我想获得所有表格列表,如table_1table_2

正则表达式是唯一的选择吗?

Jac*_*ski 7

非常感谢@Swapnil Chougule的回答。这启发了我提供一种在结构化查询中收集所有表的惯用方法。

scala> spark.version
res0: String = 2.3.1

def getTables(query: String): Seq[String] = {
  val logicalPlan = spark.sessionState.sqlParser.parsePlan(query)
  import org.apache.spark.sql.catalyst.analysis.UnresolvedRelation
  logicalPlan.collect { case r: UnresolvedRelation => r.tableName }
}

val query = "select * from table_1 as a left join table_2 as b on a.id=b.id"
scala> getTables(query).foreach(println)
table_1
table_2
Run Code Online (Sandbox Code Playgroud)

  • 这并不完整,CTE 中的表被忽略,“WIth”类型的子项需要另外访问 (3认同)

Swa*_*ule 6

希望它会帮助你

使用 spark sql 解析器解析给定的查询(spark 内部也这样做)。您可以从会话的状态中获取 sqlParser。它将给出查询的逻辑计划。迭代查询的逻辑计划并检查它是否是 UnresolvedRelation 的实例(叶逻辑运算符表示尚未解析的逻辑查询计划中的表引用)并从中获取表。

def getTables(query: String) : Seq[String] ={
    val logical : LogicalPlan = localsparkSession.sessionState.sqlParser.parsePlan(query)
    val tables = scala.collection.mutable.LinkedHashSet.empty[String]
    var i = 0
    while (true) {
      if (logical(i) == null) {
        return tables.toSeq
      } else if (logical(i).isInstanceOf[UnresolvedRelation]) {
        val tableIdentifier = logical(i).asInstanceOf[UnresolvedRelation].tableIdentifier
        tables += tableIdentifier.unquotedString.toLowerCase
      }
      i = i + 1
    }
    tables.toSeq
}
Run Code Online (Sandbox Code Playgroud)