声明变量并在查询 oracle 中使用它们

Posted

技术标签:

【中文标题】声明变量并在查询 oracle 中使用它们【英文标题】:Declare variables and use them in query oracle 【发布时间】:2020-10-10 11:43:37 【问题描述】:

我正在进行数据迁移,在 oracle 11g 中转换 Sybase 查询 从过去 2 天开始,我一直坚持这件事

@Declare @myDate Datetime
Select @myDate = workingDate from MyTable

然后很少有 sql 语句在 where 子句中使用变量 myDate

前任

Select * form table1 
join table1 on table1.id = table.id
join table1 on table1.id =  mytable.id
where mytable.workingDate = my_date

// 所以最后我想要声明一个变量,该变量将从 select 子句中获取其值,并在复杂查询中的进一步 sql 语句中使用它

我想在 Oracle 11g 中实现同样的目标,而不会增加任何复杂性

我是 Oracle 新手,需要您的帮助。

【问题讨论】:

可能类似这样:***.com/a/40360471/230471 结果将如何使用?对于数据迁移,您能否在不依赖 SQL*Plus 功能的情况下用 PL/SQL 编写整个内容? @WilliamRobertson 我正在寻找在 oracle 中声明 Sybase 的简单转换,我想在多个 where 子句中进一步使用 my_date 结果将如何使用?您只是要运行 SQL*Plus 脚本并让它打印出一些结果吗?或者既然你提到了迁移,会有insert into x select from y类型的逻辑吗?如果是这样,您可以在 PL/SQL 中完成所有操作,并且不需要任何 variableprint 等。 我们没有足够的上下文信息您是否只想使用 SQL 和匿名 PL/SQL 转换 SQL 脚本您是否希望将 Transact-SQL 转换为 PL/ SQL 过程、函数和包? 【参考方案1】:

您使用的是 SQLPlus:我认为您不能声明 SQLPlus TIMESTAMP 变量。

尝试使用 VARCHAR2 变量并转换为 TIMESTAMP:

SQL> select banner from v$version where rownum=1;

BANNER
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

SQL> variable ko timestamp;
Usage: VAR[IABLE] [ <variable> [ NUMBER | CHAR | CHAR (n [CHAR|BYTE]) |
            VARCHAR2 (n [CHAR|BYTE]) | NCHAR | NCHAR (n) |
            NVARCHAR2 (n) | CLOB | NCLOB | BLOB | BFILE
            REFCURSOR | BINARY_FLOAT | BINARY_DOUBLE ] ]
SQL> --
SQL> variable my_date varchar2(50) ;
SQL> begin
  2  select workingDate  into :my_date from MyTable;
  3  end;
  4  /

PL/SQL procedure successfully completed.

SQL> print my_date;

MY_DATE
------------------------------
20-JUN-20 10.55.55.264286 AM

SQL> print :my_date;

MY_DATE
------------------------------
20-JUN-20 10.55.55.264286 AM

SQL> --
SQL> select * from mytable;

WORKINGDATE
------------------------------
20-JUN-20 10.55.55.264286 AM

SQL> select workingDate  from MyTable where workingDate = to_timestamp(:my_date, 'DD-MON-YY HH.MI.SSXFF AM');

WORKINGDATE
------------------------------
20-JUN-20 10.55.55.264286 AM

SQL> 

【讨论】:

我正在使用 sql developer,这个 sql 脚本是从 java code hibernate 调用的 我不知道hibernate,也不知道它是调用SQLPlus还是只能执行SQL和PL/SQL语句。 它执行 sql 和 pl/sql 但是上面的事情在 sql 中是可能的? 它是 SQL,但它只能由 SQL*Plus 执行。 @Shelly - 你应该知道什么将在 SQL Developer 中运行,什么将在 SQL*Plus 中运行以及你可以从 Hibernate 中调用什么是三种不同的东西。您可能会花费大量时间让 SQL*Plus/SQL Developer 脚本按照您的意愿运行,然后发现它在 Hibernate 中没有用,您必须重新开始。【参考方案2】:

variable 不支持日期或时间戳。此外,您的最终查询应使用:my_date(表示主机变量),而不是my_date

如果目标是使用在上一步中填充的变量来填充表,您可以对整个任务使用 PL/SQL,例如

declare
    myDate date;
begin
    select some_col into myDate from wherever;

    insert into target_table (col1, col2, col2)
    select x, y, z
    from   source_table
    where  business_date = myDate;
end;

或者更好的是,定义PL/SQL packages 来封装您的处理逻辑。

关于您发布的代码,从 Oracle 12.1 开始,您可以在 PL/SQL 中声明一个引用游标,并让 SQL*Plus 等客户端简单地调用该块并打印结果:

declare
    my_date timestamp;
    results sys_refcursor;
begin
    select systimestamp into my_date
    from   dual;

    open results for
        select my_date as my_date from dual;
    
    dbms_sql.return_result(results);
end;
/
PL/SQL procedure successfully completed.

ResultSet #1

MY_DATE
---------------------------------------------------------------------------
20-JUN-20 10.02.29.130000000

1 row selected.

对于早期的 Oracle 版本,您仍然需要在 SQL*Plus 中将 ref 游标声明为宿主变量:

set autoprint on

var results refcursor

declare
    my_date timestamp;
begin
    select systimestamp into my_date
    from   dual;

    open :results for
        select my_date as my_date from dual;
end;
/

(或set autoprint off,然后明确print results。)

虽然我不懂 Java,所以我不知道上述任何方法是否适用于您的环境。

【讨论】:

以上是关于声明变量并在查询 oracle 中使用它们的主要内容,如果未能解决你的问题,请参考以下文章

在 oracle 的游标声明查询中使用变量

DBeaver,如何声明变量并使用它们?

在 Oracle 中通过 SELECT 查询声明变量并设置其值

查询oracle数据库时,如何定义变量进行查询

声明变量并从Oracle中的SELECT查询设置其值

在 where 子句中使用 Oracle SQL 变量时遇到问题