Oracle — оператор IF в предложении WHERE

Я должен перевести код C# в хранимую процедуру в Oracle.

Я написал хранимую процедуру с случаем, когда не возвращаются нужные данные. Где я не прав?

Проблема заключается в управлении IF входных параметров.

Оракул:

CREATE OR REPLACE PROCEDURE SP_S_RICCFEMESSE 
(
    NUMEROCV        IN VARCHAR2,
    PROFILO         IN NUMBER,
    SALAES          IN NUMBER,
    DATAINIZIO      IN VARCHAR2,
    DATAFINE        IN VARCHAR2,
    ric_carteemesse OUT SYS_REFCURSOR
)
AS 
BEGIN
    OPEN ric_carteemesse FOR
       SELECT DISTINCT A.*
                ,DESCARDPRFCFR AS TIPO_CARTA
                ,TO_CHAR(DATNAS,'DD/MM/YYYY') AS DATA_DI_NASCITA 
                ,TO_CHAR(A.DATIVOPSA,'DD/MM/YYYY HH24:MI:SS') AS DATA_EMISSIONE 
                ,TO_CHAR(DATINIVALRTA,'DD/MM/YYYY') AS INIZIO_VALIDITA_CARTA 
                ,TO_CHAR(DATFINIVALRTA,'DD/MM/YYYY') AS FINE_VALIDITA_CARTA 
                ,C.S_DENOMINAZIONE AS SALA_ES 
                ,CASE 
                    WHEN NVL(SCDUP,0) = '0' 
                    THEN 'NO' 
                    WHEN SCDUP > 0 
                    THEN 'SI' 
                END AS DUPLICATO 
FROM 
DEMIRTAFRC A 
INNER JOIN SMART_CARD B 
    ON A.CODSRE = B.COD_SM 
LEFT JOIN RIVENDITA C 
    ON B.S_POSTAZIONE_UM = TO_CHAR(C.COD_RIVENDITA) 
INNER JOIN DANACARDPRFCFR D ON A.CODPRF= D.CARDPRFCFR 
WHERE 
    (B.D_ELETTRIFICAZIONE BETWEEN TO_DATE(DATAINIZIO,'DD/MM/YYYY') AND TO_DATE(DATAFINE,'DD/MM/YYYY') 
    AND A.MDLCSG = 'CBM' AND CODSRE IS NOT NULL)
    AND NUMEROCV = (CASE WHEN NUMEROCV <> '' 
                         THEN A.CODRTA
                         ELSE null 
                    END)
    AND PROFILO = (CASE WHEN PROFILO <> 0 
                        THEN B.COD_REQUISITI
                        ELSE null 
                   END)
    AND SALAES = (CASE WHEN SALAES <> 999
                       THEN B.S_POSTAZIONE_UM
                       ELSE null 
                  END)
ORDER BY A.DATETR DESC;

END SP_S_RICCFEMESSE;

Это код С# для замены:

if (_NumCV.ToString().Trim() != "")
                _cmd.CommandText += " AND A.CODRTA = '" + _NumCV + "' ";

            if (_Profilo != 0)
                _cmd.CommandText += " AND B.COD_REQUISITI = " + _Profilo;

            if (_SalaES != 999)
                _cmd.CommandText += " AND B.S_POSTAZIONE_UM = '" + _SalaES + "' ";
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
100
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

У вас есть нулевое значение в столбцах PROFILO, SALES, NUMERO CV. Если да, то вы должны установить nvl в этих столбцах, где часть.

Поскольку вы С# говорите, что у вас может быть нуль, попробуйте это:

 CREATE OR REPLACE PROCEDURE SP_S_RICCFEMESSE 
(
    NUMEROCV        IN VARCHAR2,
    PROFILO         IN NUMBER,
    SALAES          IN NUMBER,
    DATAINIZIO      IN VARCHAR2,
    DATAFINE        IN VARCHAR2,
    ric_carteemesse OUT SYS_REFCURSOR
)


AS 
BEGIN

OPEN ric_carteemesse FOR
SELECT DISTINCT A.*
                ,DESCARDPRFCFR AS TIPO_CARTA
                ,TO_CHAR(DATNAS,'DD/MM/YYYY') AS DATA_DI_NASCITA 
                ,TO_CHAR(A.DATIVOPSA,'DD/MM/YYYY HH24:MI:SS') AS DATA_EMISSIONE 
                ,TO_CHAR(DATINIVALRTA,'DD/MM/YYYY') AS INIZIO_VALIDITA_CARTA 
                ,TO_CHAR(DATFINIVALRTA,'DD/MM/YYYY') AS FINE_VALIDITA_CARTA 
                ,C.S_DENOMINAZIONE AS SALA_ES 
                ,CASE 
                    WHEN NVL(SCDUP,0) = '0' 
                    THEN 'NO' 
                    WHEN SCDUP > 0 
                    THEN 'SI' 
                END AS DUPLICATO 
FROM 
DEMIRTAFRC A 
INNER JOIN SMART_CARD B 
    ON A.CODSRE = B.COD_SM 
LEFT JOIN RIVENDITA C 
    ON B.S_POSTAZIONE_UM = TO_CHAR(C.COD_RIVENDITA) 
INNER JOIN DANACARDPRFCFR D ON A.CODPRF= D.CARDPRFCFR 
WHERE 
    (B.D_ELETTRIFICAZIONE BETWEEN TO_DATE(DATAINIZIO,'DD/MM/YYYY') AND TO_DATE(DATAFINE,'DD/MM/YYYY') 
    AND A.MDLCSG = 'CBM' AND CODSRE IS NOT NULL)
    AND nvl(NUMEROCV, ' ') = (CASE WHEN nvl(NUMEROCV, ' ') <> ' ' 
                         THEN A.CODRTA
                         ELSE null 
                    END)
    AND nvl(PROFILO, 0) = (CASE WHEN nvl(PROFILO, 0) <> 0 
                        THEN B.COD_REQUISITI
                        ELSE null 
                   END)
    AND NVL(SALAES, 0) = (CASE WHEN NVL(SALAES, 0) <> 999
                       THEN B.S_POSTAZIONE_UM
                       ELSE null 
                  END)
ORDER BY A.DATETR DESC;

END SP_S_RICCFEMESSE;
Ответ принят как подходящий

NULL никогда не равен NULL. Таким образом, если какой-либо из операторов CASE перейдет в ветвь ELSE, оператор будет оценен как FALSE. Кроме того, в Oracle пустая строка — это то же самое, что и NULL (да, это спорно, но Oracle был таким уже почти сорок лет, так оно и есть), что означает, что это всегда будет ЛОЖЬ: NUMEROCV <> ''.

Простое решение: не используйте CASE в предложении WHERE. Это намного понятнее:

AND (NUMEROCV is null or NUMEROCV = A.CODRTA)
AND (PROFILO = 0 or PROFILO = B.COD_REQUISITI)
AND (SALAES = 999 or SALAES = B.S_POSTAZIONE_UM))

Если у вас много критериев, вы можете динамически создавать sql

Объявить sql_statement

sql_statement VARCHAR2(...);

sql_statement := 'SELECT .... WHERE ' // your select

IF PROFILO <> 0 THEN // your criteria here
    sql_statement := sql_statement || ' AND B.COD_REQUISITI = ' || PROFILO // your criteria here;

EXECUTE IMMEDIATE(sql_statement);

Другие вопросы по теме