如何在查询中调用oracle存储过程?

时间:2019-12-23 12:43:56

标签: apache-spark apache-spark-sql

在我的spark项目中,我正在使用spark-sql-2.4.1v。

作为我的代码的一部分,我需要在我的spark作业中调用oracle存储的proc。

我们正在将一个旧项目转换为基于Oracle存储的proc具有很多逻辑的spark。我们正在转换为spark的中间件逻辑...因此要保持procs逻辑不变,因为还有其他应用程序在使用它们...因此需要在spark代码中调用现有的proc。

如何调用oracle存储过程?

3 个答案:

答案 0 :(得分:0)

Spark SQL可用于在Oracle表中读写数据,换句话说,您可以执行selectinsertdelete。您可以通过执行delete+insert来进行更新。您也可以在SQL中调用function。但是我认为您不能使用Spark SQL调用stored procedure,但是可以使用普通的旧Java / scala / python语法来实现。我使用的策略是使用Spark SQL填充表,然后使用标准JDBC连接和Java代码基于该表运行stored procedure。驱动程序将在单个线程中执行此存储过程,显然您在这里不会期望可伸缩性。

    spark.write.mode(SaveMode.append).jdbc(jdbcURL, tableName, jdbcProperties)
    val con = DriverManager.getConnection(jdbcURL)
    //execute the stored procedure using JDBC connection
    con.close()

答案 1 :(得分:0)

python 中的 cx_Oracle 模块可用于从 python / pyspark 脚本调用 oracle 存储过程。 文档在这里 - https://cx-oracle.readthedocs.io/en/latest/user_guide/plsql_execution.html

如果由于某种原因,cx_Oracle 在 hadoop 环境中不起作用(因为它需要安装 oracle 客户端二进制文件),我们可以使用下面的 Spark JDBC 方法。

在 PySpark JDBC 选项中,有一个名为 sessionInitStatement 的属性,可用于在 JDBC 进程开始读取数据之前执行自定义 SQL 语句或 PL/SQL 块。 spark JDBC 读取中的此选项可用于调用存储过程,如下所示。

这里首先我们使用 sessionInitStatement 执行 PL/SQL proc,然后使用 spark/jdbc read 从存储的 proc 读取最终数据集。

from pyspark.sql import SparkSession, HiveContext

spark = (SparkSession.builder.enableHiveSupport().getOrCreate())


# Provide PL/SQL code here - call the stored proc within BEGIN and END block. 

plsql_block = """
BEGIN
      SCHEMA.STORED_PROC_NAME;
END;
"""

# Read the final table that is created / updated within the stored proc. 
count_query = """
(    
select count(*) from SCHMA.TABLE_NAME

) t1
"""

df = spark.read \
    .format("jdbc") \
    .option("url", "JDBC_URL") \
    .option('driver', 'oracle.jdbc.driver.OracleDriver') \
    .option("oracle.jdbc.timezoneAsRegion", "false") \
    .option("sessionInitStatement", plsql_block) \
    .option("dbtable", count_query) \
    .option("user", "USER_ID") \
    .option("password", "PASSWORD") \
    .load()

print("Total Records")
df.show(10, False)   

答案 2 :(得分:-1)

您可以尝试执行类似的操作,尽管我从未在任何实现中亲自进行过尝试

query = "exec SP_NAME"

empDF = spark.read \
    .format("jdbc") \
    .option("url", "jdbc:oracle:thin:username/password@//hostname:portnumber/SID") \
    .option("dbtable", query) \
    .option("user", "db_user_name") \
    .option("password", "password") \
    .option("driver", "oracle.jdbc.driver.OracleDriver") \
    .load()