Oracle:使用多个变量表达式是错误的类型

时间:2014-04-01 20:46:44

标签: sql oracle plsql

我试图对我之前编码的现有PL / SQL包进行修改。有问题的原始块看起来像这样(工作正常)

FUNCTION GEN_COLUMN_TYPE ( DTYPE IN VARCHAR2,  --DATATYPE OF THE COLUMN
                            PRCISION IN NUMBER, --PRECISION OF THE COLUMN
                            SCLE IN NUMBER,    --PRECISION OF THE COLUMN
                            DATA_LENGTH IN NUMBER, --DATA LENGTH OF THE COLUMN
                            CHAR_LENGTH IN NUMBER, --CHARACTER LENGTH OF THE COLUMN
                            APP_CODE IN VARCHAR2     -- DATABASE TYPE
                            )RETURN STRING IS

  V_COLUMNTYPE  STRING(40) := NULL;
  BEGIN
             V_COLUMNTYPE := DTYPE;
             BEGIN
              SELECT TARGET_DATATYPE  INTO V_COLUMNTYPE  FROM DDL_DATATYPE_MAP  DDM
              INNER JOIN DDL_SOURCE_APPLICATION DSA ON DDM.TARGET_DBMS=DSA.TARGET_DBMS AND DDM.SOURCE_DBMS=DSA.SOURCE_DBMS
              AND  DSA.APPLICATION_CODE=APP_CODE
              WHERE DDM.SOURCE_DATATYPE=DTYPE;
             END;

我现在修改它看起来像这样。我做的唯一改变是将2个新变量添加到定义中,并且" SELECT INTO"语句,所以我可以在代码的后面基于相同的连接标准使用它们。

FUNCTION GEN_COLUMN_TYPE ( DTYPE IN VARCHAR2,  --DATATYPE OF THE COLUMN
                            PRCISION IN NUMBER, --PRECISION OF THE COLUMN
                            SCLE IN NUMBER,    --PRECISION OF THE COLUMN
                            DATA_LENGTH IN NUMBER, --DATA LENGTH OF THE COLUMN
                            CHAR_LENGTH IN NUMBER, --CHARACTER LENGTH OF THE COLUMN
                            APP_CODE IN VARCHAR2,     --APPLICATION CODE
                            DBMS_TYPE VARCHAR2,    --DATABASE TYPE
                            VAR_LENGTH_IND VARCHAR2  --WHETHER THE FIELD NEEDS PARENS OR NOT
                            )RETURN STRING IS

  V_COLUMNTYPE  VARCHAR2(40) := NULL;
  BEGIN
             V_COLUMNTYPE := DTYPE;

              BEGIN
              SELECT TARGET_DATATYPE, SOURCE_DBMS, TARGET_VARIABLE_LEN_IND  INTO V_COLUMNTYPE, DBMS_TYPE, VAR_LENGTH_IND FROM DDL_DATATYPE_MAP  DDM
              INNER JOIN DDL_SOURCE_APPLICATION DSA ON DDM.TARGET_DBMS=DSA.TARGET_DBMS AND DDM.SOURCE_DBMS=DSA.SOURCE_DBMS
              AND  DSA.APPLICATION_CODE=APP_CODE
              WHERE DDM.SOURCE_DATATYPE=DTYPE;
             END;

我得到了太常见的" PL-00382:表达式类型错误"在" SELECT ... INTO"最后的声明。所有三个变量和列数据类型都是varchar2。我倾注了这一点,看不出有什么不对劲。我错过了什么?

编辑: 共享此尝试以使用局部变量并重写命名以提高可读性。但是我在"' V_DBMS_TYPE'上收到错误必须声明"

FUNCTION GEN_COLUMN_TYPE ( P_DTYPE IN VARCHAR2,  --DATATYPE OF THE COLUMN
                            P_PRCISION IN NUMBER, --PRECISION OF THE COLUMN
                            P_SCLE IN NUMBER,    --PRECISION OF THE COLUMN
                            P_DATA_LENGTH IN NUMBER, --DATA LENGTH OF THE COLUMN
                            P_CHAR_LENGTH IN NUMBER, --CHARACTER LENGTH OF THE COLUMN
                            P_APP_CODE IN VARCHAR2
                            )RETURN STRING IS

  V_COLUMNTYPE  VARCHAR2(40) := NULL;
  BEGIN
             V_COLUMNTYPE := P_DTYPE;
             DECLARE
             V_DBMS_TYPE VARCHAR2(30) := NULL;    --DATABASE TYPE
             V_VAR_LENGTH_IND VARCHAR2(30) := NULL;  --WHETHER THE FIELD NEEDS PARENS OR NOT
              BEGIN
              SELECT TARGET_DATATYPE, SOURCE_DBMS, TARGET_VARIABLE_LEN_IND  INTO V_COLUMNTYPE, V_DBMS_TYPE, V_VAR_LENGTH_IND FROM DDL_DATATYPE_MAP  DDM
              INNER JOIN DDL_SOURCE_APPLICATION DSA ON DDM.TARGET_DBMS=DSA.TARGET_DBMS AND DDM.SOURCE_DBMS=DSA.SOURCE_DBMS
              AND  DSA.APPLICATION_CODE=P_APP_CODE
              WHERE DDM.SOURCE_DATATYPE=P_DTYPE;

1 个答案:

答案 0 :(得分:3)

您为函数添加了两个参数。您没有指定参数模式(INOUTIN OUT),因此默认值为ININ参数不能是SELECT INTO的目标,因为该参数在函数内是只读的。

我不清楚你是否真的想要声明两个新的局部变量,而不是两个额外的参数,或者你是否真的想要将两个新参数声明为OUTIN OUT参数。如果您将参数声明为OUTIN OUT,则它们可能是作业的目标。但是你的函数将不再可以从SQL调用。如果声明两个新的局部变量,该函数仍然可以从SQL调用,但是您无法传入(或传回)从SELECT语句中收集的值。

作为一般性建议,我更倾向于看到用于区分参数与局部变量和列名的通用命名约定 - 这使得读取代码变得更加容易。例如,如果您的参数使用标准的P_前缀,则会在SELECT语句中立即明确您的某些目标是局部变量,而某些目标变量是参数。

根据注释,您需要声明其他局部变量而不是添加参数。这看起来像

CREATE OR REPLACE FUNCTION GEN_COLUMN_TYPE ( 
                           DTYPE IN VARCHAR2,  --DATATYPE OF THE COLUMN
                           PRCISION IN NUMBER, --PRECISION OF THE COLUMN
                           SCLE IN NUMBER,    --PRECISION OF THE COLUMN
                           DATA_LENGTH IN NUMBER, --DATA LENGTH OF THE COLUMN
                           CHAR_LENGTH IN NUMBER, --CHARACTER LENGTH OF THE COLUMN
                           APP_CODE IN VARCHAR2     --APPLICATION CODE
                         )
  RETURN VARCHAR2
IS
  V_DBMS_TYPE      VARCHAR2(100);    --DATABASE TYPE
  V_VAR_LENGTH_IND VARCHAR2(100);  --WHETHER THE FIELD NEEDS PARENS OR NOT
  V_COLUMNTYPE     VARCHAR2(40) := NULL;
BEGIN
  V_COLUMNTYPE := DTYPE;

  SELECT TARGET_DATATYPE, SOURCE_DBMS, TARGET_VARIABLE_LEN_IND  
    INTO V_COLUMNTYPE, V_DBMS_TYPE, V_VAR_LENGTH_IND 
    FROM DDL_DATATYPE_MAP  DDM
         INNER JOIN DDL_SOURCE_APPLICATION DSA ON DDM.TARGET_DBMS=DSA.TARGET_DBMS AND  
                                                  DDM.SOURCE_DBMS=DSA.SOURCE_DBMS AND
                                                  DSA.APPLICATION_CODE=APP_CODE
   WHERE DDM.SOURCE_DATATYPE=DTYPE;

  <<more code>>
END;