我试图对我之前编码的现有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;
答案 0 :(得分:3)
您为函数添加了两个参数。您没有指定参数模式(IN
,OUT
或IN OUT
),因此默认值为IN
。 IN
参数不能是SELECT INTO
的目标,因为该参数在函数内是只读的。
我不清楚你是否真的想要声明两个新的局部变量,而不是两个额外的参数,或者你是否真的想要将两个新参数声明为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;