【问题标题】:Oracle - IF Statement into WHERE ClauseOracle - 将 IF 语句转换为 WHERE 子句
【发布时间】:2019-04-26 23:56:13
【问题描述】:

我应该将 C# 代码翻译成 Oracle 中的存储过程。

我在 where 中写了一个带有大小写的存储过程,但没有返回正确的数据。我哪里错了?

问题是管理输入参数的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;

这是要替换的 C# 代码:

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 + "' ";

【问题讨论】:

    标签: c# oracle if-statement


    【解决方案1】:

    NULL 从不等于 NULL。因此,如果任何 CASE 语句进入 ELSE 分支,则该语句将评估为 FALSE。此外,在 Oracle 中,空字符串与 NULL 相同(是的,这是有争议的,但 Oracle 已经这样做了将近 40 年,就是这样),这意味着这总是 FALSE:NUMEROCV &lt;&gt; ''

    简单的解决方案是,不要在 WHERE 子句中使用 CASE。这更清楚:

    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))
    

    【讨论】:

      【解决方案2】:

      您在 PROFILO、SALAES、NUMEROCV 列中是否有空值。 如果是,那么您必须在 where 部分的此列上设置 nvl。

      因为你 c# 说你可能有 null 试试这个:

       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;
      

      【讨论】:

        【解决方案3】:

        如果你有很多条件,你可以动态构建 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);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-04-09
          • 1970-01-01
          • 2023-04-08
          • 2013-03-02
          • 1970-01-01
          • 1970-01-01
          • 2014-10-08
          • 1970-01-01
          相关资源
          最近更新 更多