在Oracle PL SQL中存储变量

时间:2012-05-30 08:53:14

标签: sql oracle plsql

我希望你能提供帮助 - 我正在尝试为变量分配日期,然后在我的选择查询中调用该变量。我发布的代码只是我正在尝试做的事情的一部分,我将不止一次地调用该变量。 我试图谷歌寻求帮助,但我仍然坚持使用Select Into语句,因为我已经有很多选择。

DECLARE 
    CurrMonth DATE := '27 may 2012'; -- Enter 27th of current month  

BEGIN

SELECT 
    a.policynumber
    ,a.cifnumber
    ,a.phid
    ,a.policystartdate
    ,b.sistartdate
    ,c.dateofbirth
    ,'28/02/2013' AS TaxYearEnd
    --Complete tax year end in the SELECT statement (once for tax year end and once for the age at tax year end)
    ,round ((months_between('28 feb 2013',c.dateofbirth)/12),8) AS AgeAtTaxYearEnd 
    ,b.sifrequency AS CurrSIFrequ
    ,b.sivalue AS CurrentSIValue
    ,b.simode AS CurrentSIMode
    ,d.anniversarydate AS CurrentAnnDate
    ,d.anniversaryvalue AS CurrentAnnValue
    ,b.ruleeffectivedate
    ,b.sistatus AS CurrentSIStatus
    ,b.paymentbranchcode AS CurrSIBranchCode
    ,b.transferaccounttype AS CurrSIAccountType
    ,b.transferaccountnumber AS CurrSIAccountNo
    ,SUM(k.unitbalance) AS unitbalance
    ,a.latestrule
FROM fcislob.policytbl a
    ,fcislob.policysitbl b
    ,fcislob.unitholderdetailtbl c
    ,fcislob.policyanniversaryvaluetbl d
    ,fcislob.unitholderfundtbl k
WHERE a.policynumber = b.policynumber
    AND a.policynumber = d.policynumber
    AND b.policynumber = d.policynumber
    AND a.phid = c.unitholderid
    AND a.phid = k.unitholderid
    AND c.unitholderid = k.unitholderid
    AND a.ruleeffectivedate = b.ruleeffectivedate
    AND a.ruleeffectivedate = d.ruleeffectivedate
    AND b.ruleeffectivedate = d.ruleeffectivedate
    AND a.latestrule <> 0
    AND c.authrejectstatus = 'A'        
    AND a.phid LIKE 'AGLA%'
    AND b.sistatus <> 'C'
    AND k.unitbalance >0     
    AND b.transactiontype = '64'
    AND b.sistartdate <= CurrMonth                                              
    AND b.sifrequency = 'M'

GROUP BY a.policynumber, a.cifnumber, a.phid, a.policystartdate, b.sistartdate , c.dateofbirth,b.sifrequency, b.sivalue, b.simode, d.anniversarydate, d.anniversaryvalue, b.ruleeffectivedate,
    b.sistatus, b.paymentbranchcode, b.transferaccounttype, b.transferaccountnumber, b.policynumber, a.latestrule;
    END;

2 个答案:

答案 0 :(得分:3)

  1. 您有一个group by子句,因此您需要按所有未聚合的列进行分组。
  2. 您确定结果中只有一条记录吗?
  3. 正如@TonyAndrews所说,你需要into子句。您需要为每个collumn声明一个变量并插入其中,
  4. 即:

    DECLARE
      v_policynumber fcislob.policytbl.policynumber%TYPE;
      v_cifnumber    fcislob.policytbl.cifnumber%TYPE;
      v_phid         fcislob.policytbl.phid%TYPE;
      -- and so on ...
      v_sum          number;
    BEGIN
        SELECT SUM(k.unitbalance), a.policynumber, a.cifnumber, a.phid -- and so on ...
          INTO v_sum, v_policynumber, v_cifnumber, v_phid -- and so on ...
          FROM fcislob.policytbl a -- and so on ...
      GROUP BY a.policynumber, a.cifnumber, a.phid -- and so on ...
    END;
    
    1. 处理日期的方式并不“健康”,IMO最好使用to_date而不是依赖NLS参数

答案 1 :(得分:0)

如果你只是使用PL / SQL来保持几个普通select语句之间的日期值,那么它会使事情复杂化 - 如果你只是转换到select into并不简单想要显示查询结果,特别是如果有多行。

由于你提到你有很多选择,我猜你在脚本文件(example.sql)中有它们,并且正在通过SQL * Plus运行它们,如sqlplus user/password @example。如果是这样,您可以保留纯SQL语句并使用positional parameterssubstitution variablesbind variables来跟踪日期。

第一个选项是您希望在命令行上传递日期,例如sqlplus user/password @example 27-May-2012

set verify off
select 'Supplied date is ' || to_date('&1', 'DD-Mon-RRRR') from dual;

这使用第一个位置参数(引用为&1),并根据需要将其转换为查询中的日期。传递的日期必须采用to_date函数所期望的格式,在这种情况下我已经制作了DD-Mon-RRRR。请注意,您必须将变量括在单引号中,否则(除非它是一个数字)Oracle将尝试将其解释为列名而不是值。 (set verify off禁止SQL * Plus在使用替换变量时默认显示的消息。)

您可以在脚本中多次引用&1,但您可能会发现使用有意义的名称重新定义它更容易 - 当您有多个位置参数时尤其有用 - 然后在你的疑问。

define supplied_date = &1
select 'Supplied date is ' || to_date('&supplied_date', 'DD-Mon-RRRR') from dual;

如果您不想从命令行传递日期,则可以使用固定值。我在这里使用了不同的默认日期格式,这允许我使用日期文字语法或to_date函数。

define curr_date = '2012-05-31';
select 'Today is ' || date '&curr_date' from dual;
select 'Today is ' || to_date('&curr_date', 'YYYY-MM-DD') from dual;

您可能希望使用稍后查询中的一个查询的结果来派生日期值。您可以使用column ... new_value SQL * Plus命令来执行此操作;这将使用来自任何未来查询的curr_date列(别名)中的字符串值定义替换变量today,然后您可以以相同的方式使用它:

column today new_value curr_date
select to_char(sysdate, 'DD-Mon-YYYY') as today from dual;
select 'Today is ' || to_date('&curr_date', 'DD-Mon-YYYY') from dual;

您还可以使用使用var[iable]命令定义的绑定变量,并使用exec进行设置:

var curr_date varchar2(10);
exec :curr_date := '2012-05-31';
select 'Today is ' || to_date(:curr_date, 'YYYY-MM-DD') from dual;

exec实际上是匿名PL / SQL块的包装器,因此它意味着begin :curr_date := '2012-05-31'; end;,但是只有在出现错误时才能看到它。请注意,它知道绑定变量是一个字符串,因此将其括在单引号中。

您可以混合使用,因此如果您在命令行上传递了日期,则可以将其分配给exec :supplied_date := '&1'的绑定变量;或使用当前日期exec :curr_date := to_char(sysdate, 'YYYY-MM-DD')

可能有许多组合,因此您需要选择适合您尝试的内容以及您认为最简单的内容。大多数(如果不是全部)这些也应该在SQL Developer中工作,但不确定其他客户端。