Използване на променливи в оператора PLSQL SELECT

Имам заявка, която прави заявки за ReportStartDate и ReportEndDate, така че реших да използвам променливи в PLSQL. Не съм сигурен какво пропускам тук, но получавам грешка:

CLEAR;
DECLARE
    varReportStartDate Date := to_date('05/01/2010', 'mm/dd/yyyy');
    varReportEndDate Date := to_date('05/31/2010', 'mm/dd/yyyy');
BEGIN

    SELECT 
          'Value TYPE', 
          1 AS CountType1, 
          2 AS CountType2, 
          3 AS CountType3 
    FROM DUAL;

    SELECT COUNT (*) 
    FROM CDR.MSRS_E_INADVCH

    WHERE 1=1
    AND ReportStartDate = varReportStartDate 
    AND ReportEndDate = varReportEndDate 
    ;
END;
/

Грешката е:

Error starting at line 2 in command:
Error report:
ORA-06550: line 6, column 5:
PLS-00428: an INTO clause is expected in this SELECT statement
ORA-06550: line 8, column 5:
PLS-00428: an INTO clause is expected in this SELECT statement
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:

Това се случва в Toad, както и в SQL Developer.

Какъв е правилният начин за използване на променливите в моята клауза WHERE?


person Raj More    schedule 29.11.2010    source източник


Отговори (2)


Не можете да използвате SQL изрази директно в PL/SQL блок (освен ако не използвате EXECUTE IMMEDIATE). Колоните ще трябва да бъдат извлечени в променливи (което PL/SQL ви казва с грешка PLS-00428: an INTO clause is expected in this SELECT statement). Така че ще трябва да пренапишете изявленията си, както е показано по-долу.

SELECT 
      'Value TYPE', 
      1 AS CountType1, 
      2 AS CountType2, 
      3 AS CountType3 
INTO 
     V_VALUE_TYPE,
     V_CountType1,
     V_CountType2,
     V_CountType3
FROM DUAL;

SELECT COUNT(*) 
   INTO V_COUNT    
FROM CDR.MSRS_E_INADVCH
WHERE 1=1
AND ReportStartDate = varReportStartDate 
AND ReportEndDate = varReportEndDate 

Не забравяйте да добавите манипулатори на изключения, тъй като PL/SQL очаква да бъде върнат само 1 ред. Ако операторът не върне нито един ред, ще постигнете NO_DATA_FOUND изключение - и ако операторът извлече твърде много редове, ще ударите TOO_MANY_ROWS изключение.

person Sathyajith Bhat    schedule 29.11.2010

Въпросът, на който трябва да отговорите, е какво искате да правите с избраните данни?

Sathya ви даде един подход - декларирайте променливи във вашия PL/SQL блок и изберете колоните INTO тези променливи. Обърнете внимание, че това изисква операторът SELECT да върне точно един ред - повече или по-малко редове ще изведат грешка. Друг начин е да декларирате типове колекции с помощта на опцията BULK COLLECT: http://oracletoday.blogspot.com/2005/11/bulk-collect_15.html

Още една възможност е процедурата да върне курсор. Това е полезно в случай, когато извикващият код очаква да може да извлече данните, които процедурата е избрала:

PROCEDURE GET_MY_REPORT( varReportStartDate in date,  varReportEndDate in date, cur out sys_refcursor) is
begin
   OPEN cur FOR SELECT * 
     FROM CDR.MSRS_E_INADVCH
     WHERE 1=1
     AND ReportStartDate = varReportStartDate 
     AND ReportEndDate = varReportEndDate;
END GET_MY_REPORT;
person Dan    schedule 29.11.2010