在不创建存储过程的情况下将 PL/SQL 发送到 Oracle

Posted

技术标签:

【中文标题】在不创建存储过程的情况下将 PL/SQL 发送到 Oracle【英文标题】:Send PL/SQL to Oracle without creating a stored procedure 【发布时间】:2017-01-02 09:46:39 【问题描述】:

我是 PL/SQL Oracle 的新手。我习惯于使用 JDBC 框架和标准 SQL。

例如下一个PL/SQL:

IF EXISTS (SELECT * FROM Table1 WHERE Column1=’SomeValue’)
    UPDATE Table1 SET (…) WHERE Column1=’SomeValue’
ELSE
    INSERT INTO Table1 VALUES (…)

这句话必须从oracle中的存储过程中执行,所以你必须在数据库中创建一个过程并调用它,但为什么我不能像“select”语句那样将这句话发送到数据库并且没有执行必须先创建一个存储过程?

【问题讨论】:

您实际上并不需要 PL/SQL,您可以使用 MERGE。或者使用匿名 PL/SQL 块。不需要存储过程。 我知道,谢谢。我的意思是为什么我不能像选择语句一样向数据库发送 pl/sql。 因为您要求它执行一个不完整的 PL/SQL 块。至少,您需要将其转换为有效的匿名 PL/SQL 块:begin <insert_pl_sql_code_here> end; 您没有向我们展示您的实际代码,因此我们无法说明它失败的原因。 【参考方案1】:

实际上,您可以使用客户端直接对数据库执行 PL/SQL,并将您的代码嵌入到“begin ... end”结构中。

例如使用sqlplus 这将如下所示(永远不要忘记以/ 结束plsql 语句 - 最后一行/第一个字符):

begin
  IF EXISTS (SELECT * FROM Table1 WHERE Column1=’SomeValue’) 
  THEN
    UPDATE Table1 SET (…) WHERE Column1=’SomeValue’
    ;
  ELSE
    INSERT INTO Table1 VALUES (…) 
    ;
  END IF;
end;
/

(我为您的if / else 结构添加了正确的语法)

【讨论】:

OP 中的 if exists (implicit cursor) 构造实际上并不是 PL/SQL。可能他正在考虑其他一些语言。【参考方案2】:

您可以使用可调用语句执行匿名 PL/SQL 块。您需要使用准备好的语句,因为它可以提高 Oracle 的性能并防止 SQL 注入。

PL/SQL 块使用 BEGIN 和 END 嵌套,或者如果您有局部变量,则使用 DECLARE / BEGIN / END。

String plsqlBlock =
    "begin " +
    "  update Table1 " +
    "    set val1 = :v1, val2 = :v2 " +
    "    where primary_key = :pk; " +
    "  if sql%rowcount = 0 then " +
    "    insert into Table1 (primary_key, val1, val2) " +
    "      values (:pk, :v1, :v2); " +
    "  end if; " +
    "end;";

CallableStatement cs = connection.prepareCall(plsqlBlock);
cs.setInt("pk", 12345);
cs.setString("v1", "abc");
cs.setString("v2", "def");
cs.execute();

【讨论】:

以上是关于在不创建存储过程的情况下将 PL/SQL 发送到 Oracle的主要内容,如果未能解决你的问题,请参考以下文章

在不使用 out 参数的情况下将存储过程输出捕获到变量中

PL/SQL 过程和 Toad 执行?

如何在不刷新页面的情况下将数据从 Android 发送到 PHP 并显示

如何在不创建 IAM 用户的情况下将文件从 EKS 上传到 S3 存储桶?

如何在不将 csv 保存到磁盘的情况下将 csv 格式的数据从内存发送到数据库?

如何在不编写自己的程序的情况下将某些文件上传到 Azure Blob 存储?