Ich bin mit Oracle 10g und ich habe die folgende gespeicherte Prozedur:Dynamische Vergleichsoperator in einer where-Klausel ungültig ist (PL/SQL Oracle)
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;
Und ich bekomme die folgende Fehlermeldung, wenn diese in SQL-Eingabe Plus :
ungültig relationalen Operator
Was zu tun, ich versuche: ich diese gespeicherte Prozedur, die mit dem REF CURSOR eine secordset meiner asp.net Anwendung zurückgibt. Ich gebe es 2 Eingabeparameter. 1 ist ein Datum (IN_DATE) und 1 ist ein Operator (IN_DATE_OPERATOR). Das Programm funktioniert wenn "|| IN_DATE_OPERATOR ||" ist ersetzt mit entweder = oder> = genau so wie ich es will. Das Problem basiert darauf, was in der .Net-Anwendung passiert. Ich möchte, dass der Operator, den es in der where-Klausel verwendet, entweder "> =" oder "=" ist und ich bis zur Laufzeit nicht wissen werde.
Ich weiß, dass ich das falsch mache, aber ich weiß nicht, wie man oracle bekommt, um zu bestätigen, dass IN_DATE_OPERATOR ein relationaler Operator ist. Ich bin offen für andere Methoden, um einen dynamischen Operator zu haben (ich habe versucht, CASE WHEN IN_DATE_OPERATOR = '=' THEN '=' ELSE '> =' ENDE ohne Erfolg), aber ich möchte nicht eine ganze separate gespeicherte Prozedur erstellen I Zusätzlich zu dieser oder einer komplett dynamischen Where-Klausel muss zusätzlich noch Meine ideale Lösung würde so wenig Änderungen wie möglich an dieser Abfrage vornehmen. Irgendwelche Vorschläge?
Edit: ok Ich habe meine Anfrage bearbeitet seien die folgenden:
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;/
aber ich bekomme die folgende Fehlermeldung:
LINE/COL ERROR
32/3 PL/SQL: Anweisung ignoriert 32/21 PLS-00382: Ausdruck ist vom falschen Typ
In Ihrer Bearbeitung fügen Sie den String 'IN_DATE' hinzu. Beachten Sie, dass ich das in meinem Beispiel durch Bindevariablen (': 1' und': 2') ersetze und dann das 'IN_DATE' als Bindevariablenwert übergebe, wenn Sie den Cursor öffnen. Der Parameter 'IN_DATE' ist für die von Ihnen erstellte dynamische SQL-Anweisung nicht sichtbar. Während Sie debuggen, ist es wahrscheinlich eine gute Idee, eine 'dbms_output.put_line (sql_statement)' vor dem 'OPEN' hinzuzufügen. Dadurch wird die von Ihnen erstellte SQL-Anweisung ausgedruckt. Sie können die Zeichenfolge dann entweder visuell auf Fehler prüfen oder sie manuell ausführen, um bessere Fehler zu erhalten. –
Entschuldigung, '|| IN_DATE_OPERATOR || 'IN_DATE)' sollte lauten: '|| IN_DATE_OPERATOR || "" || IN_DATE || 'und so weiter – Adamantine
Sie möchten auch' IN_DATE_OPERATOR 'nicht als Bindevariable übergeben. Das muss tatsächlich Teil der SQL-Anweisung sein, die Sie erstellen.Es sieht so aus, als würden Sie die SQL-Anweisung korrekt erstellen, Sie müssten nur '' USING' 'zweimal' IN_DATE 'angeben (vorausgesetzt, Sie ersetzen 'IN_DATE', wenn Sie die SQL-Anweisung mit Bind-Variablen-Platzhaltern erstellen). –