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

Sql Oracle:使用多个变量的表达式类型错误,sql,oracle,plsql,Sql,Oracle,Plsql,我正在尝试对我不久前编写的现有PL/SQL包进行修改。所讨论的原始块看起来像这样(工作正常) 我现在已经修改成这样了。我所做的唯一更改是将2个新变量添加到定义和“SELECT into”语句中,以便我可以在代码后面基于相同的连接条件使用它们 FUNCTION GEN_COLUMN_TYPE ( DTYPE IN VARCHAR2, --DATATYPE OF THE COLUMN PRCISION IN NUMBER, --PRECISI

我正在尝试对我不久前编写的现有PL/SQL包进行修改。所讨论的原始块看起来像这样(工作正常)

我现在已经修改成这样了。我所做的唯一更改是将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;
我在末尾的“SELECT…INTO”语句中得到了非常常见的“PL-00382:表达式的类型错误”。所有三个变量和列数据类型都是varchar2。我已经倾注了这一切,看不出有什么不对劲。我错过了什么

编辑: 共享此尝试以使用局部变量并重写命名以提高可读性。但是,我在“必须声明'V_DBMS_TYPE'时出错”


您在函数中添加了两个参数。您没有指定参数模式(
IN
OUT
IN-OUT
),因此默认值为
IN
中的
参数不能成为
选择进入的目标,因为该参数在函数中是只读的

我不清楚您是否真的想声明两个新的局部变量,而不是两个附加参数,或者您真的想将这两个新参数声明为
OUT
IN-OUT
参数。如果将参数声明为
OUT
IN-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;
创建或替换函数GEN\u列类型(
VARCHAR2中的数据类型,--列的数据类型
数字精度,--列的精度
SCLE的数量,--列的精度
数据长度(以数字表示),-列的数据长度
字符长度(以数字表示),-列的字符长度
VARCHAR2中的应用程序代码——应用程序代码
)
返回VARCHAR2
是
V_DBMS_型VARCHAR2(100)--数据库类型
V_VAR_LENGTH_IND VARCHAR2(100)--该领域是否需要帕伦斯
V_COLUMNTYPE VARCHAR2(40):=NULL;
开始
V_COLUMNTYPE:=DTYPE;
选择目标\u数据类型、源\u DBMS、目标\u变量\u LEN\u IND
分为V_COLUMNTYPE、V_DBMS_TYPE、V_VAR_LENGTH_IND
来自DDL_数据类型_映射DDM
DDM.TARGET\u DBMS=DSA.TARGET\u DBMS和
DDM.SOURCE_DBMS=DSA.SOURCE_DBMS和
DSA.应用程序代码=应用程序代码
其中DDM.SOURCE_DATATYPE=DTYPE;
结束;

您在函数中添加了两个参数。您没有指定参数模式(
IN
OUT
IN-OUT
),因此默认值为
IN
中的
参数不能成为
选择进入的目标,因为该参数在函数中是只读的

我不清楚您是否真的想声明两个新的局部变量,而不是两个附加参数,或者您真的想将这两个新参数声明为
OUT
IN-OUT
参数。如果将参数声明为
OUT
IN-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;
创建或替换函数GEN\u列类型(
VARCHAR2中的数据类型,--列的数据类型
数字精度,--列的精度
SCLE的数量,--列的精度
数据长度(以数字表示),-列的数据长度
字符长度(以数字表示),-列的字符长度
VARCHAR2中的应用程序代码——应用程序代码
)
返回VARCHAR2
是
V_DBMS_型VARCHAR2(100)--数据库类型
V_VAR_LENGTH_IND VARCHAR2(100)--该领域是否需要帕伦斯
V_COLUMNTYPE VARCHAR2(40):=NULL;
开始
V_COLUMNTYPE:=DTYPE;
选择目标\u数据类型、源\u DBMS、目标\u变量\u LEN\u IND
分为V_COLUMNTYPE、V_DBMS_TYPE、V_VAR_LENGTH_IND
从DDL_数据类型_M
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;