0

Oracle 10gを使用しており、次のストアドプロシージャがあります。

CREATE OR REPLACE PACKAGE BODY RF_PKG_STFCA_PositivePay
AS
PROCEDURE RF_SP_STFCA_PositivePay(IN_DATE IN NUMBER, IN_DATE_OPERATOR IN NVARCHAR2, OUT_DATA OUT CUR_DATA)
IS
/* this procedure returns a Ref Cursor with all the requested parameters
calling the stored procedure from an asp page (and anywhere else)
does not require posting a predefined number of records */
    PaymentBatchNumber      NVARCHAR2(4);
    CurrencyCode            NVARCHAR2(3);
    TransactionCode         NVARCHAR2(3);
    Transit_BranchNumber        NVARCHAR2(5);
    BankAccountNumber       NVARCHAR2(7);
    ChequeNumber            NVARCHAR2(8);
    ChequeAmount            NVARCHAR2(10);
    ClientReference         NVARCHAR2(19);
    IssueDate           NVARCHAR2(8);
    PayeeName1          NVARCHAR2(60);
    AddressLine1            NVARCHAR2(60);
    AddressLine2            NVARCHAR2(60);
    AddressLine4            NVARCHAR2(60);
    AddressLine5            NVARCHAR2(60);
    DateCreated         NVARCHAR2(25);
    DateVoided          NVARCHAR2(25);
BEGIN
OPEN OUT_DATA FOR
    SELECT LPAD(NVL(CD.PAYMENT_BATCH_NO, '0'), 4, '0') AS PaymentBatchNumber, 
    SUBSTR(NVL(CD.CURRENCY_ID, ' '), 1, 1) AS CurrencyCode,
    NVL(CD.STATUS, ' ') AS TransactionCode,
    LPAD(NVL(BA.BRANCH_ID, '0'), 5, '0') AS Transit_BranchNumber,
    LPAD(NVL(BA.ACCOUNT_NO, '0'), 7, '0') AS BankAccountNumber,
    LPAD(NVL(CD.CHECK_NO, '0') , 8, '0') AS ChequeNumber,
    LPAD(TO_CHAR(NVL(CD.AMOUNT, 0)), 10, '0') AS ChequeAmount,
    LPAD(NVL(CD.CONTROL_NO, '0'), 19, '0') AS ClientReference,
    TO_CHAR(NVL(CD.CHECK_DATE, LPAD(' ', 8, ' ')), 'YYYYMMDD') AS IssueDate,
    RPAD(NVL(CD.NAME, ' '), 60, ' ') AS PayeeName1,
    RPAD(NVL(CD.ADDR_1, ' '), 60, ' ') AS AddressLine1,
    RPAD(NVL(CD.ADDR_2, ' '), 60, ' ') AS AddressLine2,
    RPAD(NVL(CD.CITY, '') || CASE WHEN CD.CITY IS NULL OR CD.STATE IS NULL THEN ' ' ELSE ', ' END || NVL(CD.STATE, ''), 60, ' ') AS AddressLine4,
    RPAD(NVL(CD.ZIPCODE, ' '), 60, ' ') AS AddressLine5,
    TO_CHAR(CD.CREATE_DATE, 'YYYYMMDDHH24MISS') AS DateCreated,
    CASE WHEN CD.VOID_DATE IS NULL THEN ' ' ELSE TO_CHAR(CD.VOID_DATE, 'YYYYMMDDHH24MISS') END AS DateVoided
    INTO PaymentBatchNumber, CurrencyCode, TransactionCode, Transit_BranchNumber, BankAccountNumber, ChequeNumber, 
    ChequeAmount, ClientReference, IssueDate, PayeeName1, AddressLine1, AddressLine2, AddressLine4, AddressLine5,
    DateCreated, DateVoided
    FROM BANK_ACCOUNT BA 
    INNER JOIN CASH_DISBURSEMENT CD ON BA.ID = CD.BANK_ACCOUNT_ID 
    WHERE BA.ACCOUNT_NO IS NOT NULL AND CD.CHECK_NO > 0 AND CD.STATUS != 'X' AND CD.AMOUNT != 0 AND ((TO_NUMBER(TO_CHAR(CD.CREATE_DATE, 'YYYYMMDDHH24MISS')) || IN_DATE_OPERATOR || IN_DATE) OR 
    (CASE WHEN CD.VOID_DATE IS NULL THEN 0 ELSE TO_NUMBER(TO_CHAR(CD.VOID_DATE, 'YYYYMMDDHH24MISS')) END || IN_DATE_OPERATOR || IN_DATE)) 
    ORDER BY BA.BRANCH_ID, BA.ACCOUNT_NO;
END RF_SP_STFCA_PositivePay;
END RF_PKG_STFCA_PositivePay;

そして、これをSQL plusに入力すると、次のエラーが発生します。

無効な関係演算子

私がやろうとしていること:REFCURSORを使用してasp.netアプリケーションにsecordsetを返すこのストアドプロシージャがあります。2つの入力パラメーターを指定します。1は日付(IN_DATE)で、1は演算子(IN_DATE_OPERATOR)です。プログラムは「||IN_DATE_OPERATOR||」の場合に機能します は、=または>=のいずれかに置き換えられます。この問題は、where句で使用する演算子を">="または"="にする.Netアプリケーションで何が発生するかに基づいており、実行時までどちらかわかりません。

私はこれが間違っていることを知っていますが、IN_DATE_OPERATORが関係演算子であることをOracleに再認識させる方法がわかりません。動的演算子を使用する他のメソッドを使用できます(CASE WHEN IN_DATE_OPERATOR ='=' THEN'=' ELSE'> ='ENDも使用できません)が、個別のストアドプロシージャ全体を作成したくありません。これに加えて、または完全に動的なwhere句を維持する必要があります。私の理想的な解決策は、このクエリへの変更をできるだけ少なくすることです。助言がありますか?

編集:わかりました。クエリを編集しました。次のようになります。

CREATE OR REPLACE PACKAGE BODY RF_PKG_STFCA_PositivePay
AS
PROCEDURE RF_SP_STFCA_PositivePay(IN_DATE IN NUMBER, IN_DATE_OPERATOR IN VARCHAR2, OUT_DATA OUT CUR_DATA)
IS
/* this procedure returns a Ref Cursor with all the requested parameters
calling the stored procedure from an asp page (and anywhere else)
does not require posting a predefined number of records */
    SQL_Statement       VARCHAR2(8000);
BEGIN
    SQL_Statement := 'SELECT LPAD(NVL(CD.PAYMENT_BATCH_NO, ''0''), 4, ''0'') AS PaymentBatchNumber, ' ||
    ' SUBSTR(NVL(CD.CURRENCY_ID, '' ''), 1, 1) AS CurrencyCode, ' ||
    ' NVL(CD.STATUS, '' '') AS TransactionCode, ' ||
    ' LPAD(NVL(BA.BRANCH_ID, ''0''), 5, ''0'') AS Transit_BranchNumber, ' ||
    ' LPAD(NVL(BA.ACCOUNT_NO, ''0''), 7, ''0'') AS BankAccountNumber, ' ||
    ' LPAD(NVL(CD.CHECK_NO, ''0'') , 8, ''0'') AS ChequeNumber, ' ||
    ' LPAD(TO_CHAR(NVL(CD.AMOUNT, 0)), 10, ''0'') AS ChequeAmount, ' ||
    ' LPAD(NVL(CD.CONTROL_NO, ''0''), 19, ''0'') AS ClientReference, ' ||
    ' TO_CHAR(NVL(CD.CHECK_DATE, LPAD('' '', 8, '' '')), ''YYYYMMDD'') AS IssueDate, ' ||
    ' RPAD(NVL(CD.NAME, '' ''), 60, '' '') AS PayeeName1, ' ||
    ' RPAD(NVL(CD.ADDR_1, '' ''), 60, '' '') AS AddressLine1, ' ||
    ' RPAD(NVL(CD.ADDR_2, '' ''), 60, '' '') AS AddressLine2, ' ||
    ' RPAD(NVL(CD.CITY, '''') || CASE WHEN CD.CITY IS NULL OR CD.STATE IS NULL THEN '' '' ELSE '', '' END || NVL(CD.STATE, ''''), 60, '' '') AS AddressLine4, ' ||
    ' RPAD(NVL(CD.ZIPCODE, '' ''), 60, '' '') AS AddressLine5, ' ||
    ' TO_CHAR(CD.CREATE_DATE, ''YYYYMMDDHH24MISS'') AS DateCreated, ' ||
    ' CASE WHEN CD.VOID_DATE IS NULL THEN '' '' ELSE TO_CHAR(CD.VOID_DATE, ''YYYYMMDDHH24MISS'') END AS DateVoided ' ||
    ' FROM BANK_ACCOUNT BA ' ||
    ' INNER JOIN CASH_DISBURSEMENT CD ON BA.ID = CD.BANK_ACCOUNT_ID ' ||
    ' WHERE BA.ACCOUNT_NO IS NOT NULL AND CD.CHECK_NO > 0 AND CD.STATUS != ''X'' AND CD.AMOUNT != 0 ' ||
    ' AND ((TO_NUMBER(TO_CHAR(CD.CREATE_DATE, ''YYYYMMDDHH24MISS'')) ' || IN_DATE_OPERATOR || ' :1) ' ||
    ' OR (CASE WHEN CD.VOID_DATE IS NULL THEN 0 ELSE TO_NUMBER(TO_CHAR(CD.VOID_DATE, ''YYYYMMDDHH24MISS'')) END ' || IN_DATE_OPERATOR || ' :2)) ' ||
    ' ORDER BY BA.BRANCH_ID, BA.ACCOUNT_NO ';       
    OPEN OUT_DATA FOR SQL_Statement USING IN_DATE, IN_DATE;     
END RF_SP_STFCA_PositivePay;
END RF_PKG_STFCA_PositivePay;/

しかし、次のエラーが発生します。

LINE/COLエラー


32/3 PL / SQL:ステートメントが無視されました32/21 PLS-00382:式のタイプが間違っています

4

1 に答える 1

1

SQLステートメントを文字列に動的にアセンブルしてから、その文字列を使用してカーソルを開く必要があります。以下の手順に沿って、バインド変数のプレースホルダーを含むget_curローカルVARCHAR2変数でSQLステートメントをアセンブルし、アセンブルしたSQLステートメントと渡したバインド変数を使用してカーソルを開く必要があります。

SQL> create or replace procedure get_cur( p_date in date, p_operator in varchar2, p_cur out sys_refcursor )
  2  as
  3    l_sql_stmt varchar2(1000);
  4  begin
  5    l_sql_stmt := 'select * from emp where hiredate ' || p_operator || ' :1';
  6    open p_cur for l_sql_stmt using p_date;
  7  end;
  8  /

Procedure created.

SQL> var rc refcursor;
SQL> exec get_cur( date '2001-01-01', '>=', :rc );

PL/SQL procedure successfully completed.

SQL> print rc;

no rows selected

SQL> exec get_cur( date '2001-01-01', '<=', :rc );

PL/SQL procedure successfully completed.

SQL> print rc;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM
---------- ---------- --------- ---------- --------- ---------- ----------
    DEPTNO
----------
      7369 SMITH      CLERK           7902 17-DEC-80        801
        20

      7499 ALLEN      SALESMAN        7698 20-FEB-81       1601        300
        30

      7521 WARD       SALESMAN        7698 22-FEB-81       1251        500
        30


     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM
---------- ---------- --------- ---------- --------- ---------- ----------
    DEPTNO
----------
      7566 JONES      MANAGER         7839 02-APR-81       2976
        20

      7654 MARTIN     SALESMAN        7698 28-SEP-81       1251       1400
        30

      7698 BLAKE      MANAGER         7839 01-MAY-81       2851
        30


     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM
---------- ---------- --------- ---------- --------- ---------- ----------
    DEPTNO
----------
      7782 CLARK      MANAGER         7839 09-JUN-81       2451
        10

      7788 SCOTT      ANALYST         7566 19-APR-87       3001
        20

      7839 KING       PRESIDENT            17-NOV-81       5001
        10


     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM
---------- ---------- --------- ---------- --------- ---------- ----------
    DEPTNO
----------
      7844 TURNER     SALESMAN        7698 08-SEP-81       1501          0
        30

      7876 ADAMS      CLERK           7788 23-MAY-87       1101
        20

      7900 JAMES      CLERK           7698 03-DEC-81        951
        30


     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM
---------- ---------- --------- ---------- --------- ---------- ----------
    DEPTNO
----------
      7902 FORD       ANALYST         7566 03-DEC-81       3001
        20

      7934 MILLER     CLERK           7782 23-JAN-82       1301
        10


14 rows selected.

私の推測では、あなたはこのようなものが欲しいと思います(明らかに、私はあなたのテーブルやタイプを持っていないので、これが実際にコンパイルされることをテストできないので、タイプミスを修正する必要があります)

CREATE OR REPLACE PACKAGE BODY RF_PKG_STFCA_PositivePay
AS
PROCEDURE RF_SP_STFCA_PositivePay(IN_DATE IN NUMBER, IN_DATE_OPERATOR IN NVARCHAR2, OUT_DATA OUT CUR_DATA)
IS
/* this procedure returns a Ref Cursor with all the requested parameters
calling the stored procedure from an asp page (and anywhere else)
does not require posting a predefined number of records */
  l_sql_stmt VARCHAR2(4000);
BEGIN
  l_sql_stmt := q'[SELECT LPAD(NVL(CD.PAYMENT_BATCH_NO, '0'), 4, '0') AS PaymentBatchNumber, ]' ||
    q'[SUBSTR(NVL(CD.CURRENCY_ID, ' '), 1, 1) AS CurrencyCode, ]' ||
    q'[NVL(CD.STATUS, ' ') AS TransactionCode, ]' ||
    q'[LPAD(NVL(BA.BRANCH_ID, '0'), 5, '0') AS Transit_BranchNumber, ]' ||
    q'[LPAD(NVL(BA.ACCOUNT_NO, '0'), 7, '0') AS BankAccountNumber, ]' ||
    q'[LPAD(NVL(CD.CHECK_NO, '0') , 8, '0') AS ChequeNumber, ]' ||
    q'[LPAD(TO_CHAR(NVL(CD.AMOUNT, 0)), 10, '0') AS ChequeAmount, ]' ||
    q'[LPAD(NVL(CD.CONTROL_NO, '0'), 19, '0') AS ClientReference, ]' ||
    q'[TO_CHAR(NVL(CD.CHECK_DATE, LPAD(' ', 8, ' ')), 'YYYYMMDD') AS IssueDate, ]' ||
    q'[RPAD(NVL(CD.NAME, ' '), 60, ' ') AS PayeeName1, ]' ||
    q'[RPAD(NVL(CD.ADDR_1, ' '), 60, ' ') AS AddressLine1, ]' ||
    q'[RPAD(NVL(CD.ADDR_2, ' '), 60, ' ') AS AddressLine2, ]' ||
    q'[RPAD(NVL(CD.CITY, '') || CASE WHEN CD.CITY IS NULL OR CD.STATE IS NULL THEN ' ' ELSE ', ' END || NVL(CD.STATE, ''), 60, ' ') AS AddressLine4, ]' ||
    q'[RPAD(NVL(CD.ZIPCODE, ' '), 60, ' ') AS AddressLine5, ]' ||
    q'[TO_CHAR(CD.CREATE_DATE, 'YYYYMMDDHH24MISS') AS DateCreated, ]' ||
    q'[CASE WHEN CD.VOID_DATE IS NULL THEN ' ' ELSE TO_CHAR(CD.VOID_DATE, 'YYYYMMDDHH24MISS') END AS DateVoided ]' ||
    q'[FROM BANK_ACCOUNT BA  ]' ||
    q'[INNER JOIN CASH_DISBURSEMENT CD ON BA.ID = CD.BANK_ACCOUNT_ID  ]' ||
    q'[WHERE BA.ACCOUNT_NO IS NOT NULL AND CD.CHECK_NO > 0  ]' ||
    q'[AND CD.STATUS != 'X'  ]' ||
    q'[AND CD.AMOUNT != 0  ]' ||
    q'[AND ((TO_NUMBER(TO_CHAR(CD.CREATE_DATE, 'YYYYMMDDHH24MISS'))]' || IN_DATE_OPERATOR || ':1') OR  ' ||
    q'[(CASE WHEN CD.VOID_DATE IS NULL THEN 0 ELSE TO_NUMBER(TO_CHAR(CD.VOID_DATE, 'YYYYMMDDHH24MISS')) END]' || IN_DATE_OPERATOR || ':2'))  ' ||
    q'[ORDER BY BA.BRANCH_ID, BA.ACCOUNT_NO ]';
  OPEN out_data
   FOR l_sql_stmt
   USING in_date, in_date;
END RF_SP_STFCA_PositivePay;
END RF_PKG_STFCA_PositivePay;
于 2012-04-04T17:32:38.643 に答える