我正在处理的一个函数遇到了问题.该函数旨在根据输入参数和该表的请求列名检索列值.但是,当我try 编译它的代码时,如下所示:

CREATE OR REPLACE FUNCTION FIND_TEST_TABLE_COLUMN(
    IN_COLUMN1 TEST_TABLE.COLUMN1 % TYPE,
    IN_COLUMN2 TEST_TABLE.COLUMN2 % TYPE,
    IN_COLUMN3 TEST_TABLE.COLUMN3 % TYPE,
    IN_COLUMN4 TEST_TABLE.COLUMN4 % TYPE,
    IN_REQUESTED_COLUMN VARCHAR2
) RETURN VARCHAR2 IS
    C_TEST_TABLE SYS_REFCURSOR;
    RESULT       VARCHAR2(255);
BEGIN
    IF IN_COLUMN4 IS NULL THEN
        OPEN C_TEST_TABLE FOR
            SELECT *
            FROM TEST_TABLE
            WHERE COLUMN1 = COLUMN1
              AND COLUMN2 = IN_COLUMN2
              AND COLUMN3 = IN_COLUMN3;
    ELSIF IN_COLUMN4 IS NOT NULL THEN
        OPEN C_TEST_TABLE FOR
            SELECT *
            FROM TEST_TABLE
            WHERE COLUMN1 = COLUMN1
              AND COLUMN2 = IN_COLUMN2
              AND COLUMN3 = IN_COLUMN3
              AND COLUMN4 = IN_COLUMN4;
    END IF;
    FOR C_TEST_TABLE_REC IN C_TEST_TABLE
        LOOP
            IF IN_REQUESTED_COLUMN = 'COLUMN1' THEN
                RESULT := C_TEST_TABLE_REC.COLUMN1;
                EXIT;
            ELSIF IN_REQUESTED_COLUMN = 'COLUMN2' THEN
                RESULT := C_TEST_TABLE_REC.COLUMN2;
                EXIT;
            ELSIF IN_REQUESTED_COLUMN = 'COLUMN3' THEN
                RESULT := C_TEST_TABLE_REC.COLUMN3;
                EXIT;
            END IF;
        END LOOP;
    RETURN RESULT;
END;

我收到以下错误:

[警告]ORA-24344:编译错误为19/27,成功-00221: ‘c_test_table’不是过程或未定义19/5 PL/SQL: 已忽略语句(1:0):警告:已编译,但已编译 错误

这表明C_TEST_TABLE不能在声明块之后使用

推荐答案

您不需要使用游标:

CREATE OR REPLACE FUNCTION FIND_TEST_TABLE_COLUMN(
    IN_COLUMN1 TEST_TABLE.COLUMN1 % TYPE,
    IN_COLUMN2 TEST_TABLE.COLUMN2 % TYPE,
    IN_COLUMN3 TEST_TABLE.COLUMN3 % TYPE,
    IN_COLUMN4 TEST_TABLE.COLUMN4 % TYPE,
    IN_REQUESTED_COLUMN VARCHAR2
) RETURN VARCHAR2 IS
    result VARCHAR2(255);
BEGIN
  SELECT CASE IN_REQUESTED_COLUMN
         WHEN 'COLUMN1' THEN column1
         WHEN 'COLUMN2' THEN column2
         WHEN 'COLUMN3' THEN column3
         END
  INTO   result
  FROM   TEST_TABLE
  WHERE  COLUMN1 = IN_COLUMN1
  AND    COLUMN2 = IN_COLUMN2
  AND    COLUMN3 = IN_COLUMN3
  AND    (IN_COLUMN4 IS NULL OR COLUMN4 = IN_COLUMN4)
  FETCH FIRST ROW ONLY;

  RETURN result;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    RETURN NULL;
END;
/

其中,对于样本数据:

CREATE TABLE test_table (column1, column2, column3, column4) AS
SELECT 'A', 'B', 'C', 'D' FROM DUAL UNION ALL
SELECT 'A', 'B', 'C', 'E' FROM DUAL;

然后:

SELECT FIND_TEST_TABLE_COLUMN('A', 'B', 'C', 'D', 'COLUMN1') AS result1,
       FIND_TEST_TABLE_COLUMN('A', 'B', 'C', NULL, 'COLUMN2') AS result2,
       FIND_TEST_TABLE_COLUMN('X', 'Y', 'Z', NULL, 'COLUMN3') AS result3
FROM   DUAL;

输出:

RESULT1 RESULT2 RESULT3
A B null

如果要修复代码,则需要声明变量C_TEST_TABLE_REC并使用FETCH(并且可以删除循环并将代码简化为):

CREATE OR REPLACE FUNCTION FIND_TEST_TABLE_COLUMN(
    IN_COLUMN1 TEST_TABLE.COLUMN1 % TYPE,
    IN_COLUMN2 TEST_TABLE.COLUMN2 % TYPE,
    IN_COLUMN3 TEST_TABLE.COLUMN3 % TYPE,
    IN_COLUMN4 TEST_TABLE.COLUMN4 % TYPE,
    IN_REQUESTED_COLUMN VARCHAR2
) RETURN VARCHAR2
IS
  C_TEST_TABLE     SYS_REFCURSOR;
  C_TEST_TABLE_REC TEST_TABLE%ROWTYPE;
BEGIN
  OPEN C_TEST_TABLE FOR
    SELECT *
    FROM   TEST_TABLE
    WHERE  COLUMN1 = IN_COLUMN1
      AND  COLUMN2 = IN_COLUMN2
      AND  COLUMN3 = IN_COLUMN3
      AND  (IN_COLUMN4 IS NULL OR COLUMN4 = IN_COLUMN4);

  FETCH C_TEST_TABLE INTO C_TEST_TABLE_REC;

  IF C_TEST_TABLE%NOTFOUND THEN
    RETURN NULL;
  END IF;

  IF IN_REQUESTED_COLUMN = 'COLUMN1' THEN
    RETURN C_TEST_TABLE_REC.COLUMN1;
  ELSIF IN_REQUESTED_COLUMN = 'COLUMN2' THEN
    RETURN C_TEST_TABLE_REC.COLUMN2;
  ELSIF IN_REQUESTED_COLUMN = 'COLUMN3' THEN
    RETURN C_TEST_TABLE_REC.COLUMN3;
  ELSE
    RETURN NULL;
  END IF;
END;
/

fiddle

Sql相关问答推荐

两个不同星期的销售额,不加成一行

在Postgres中合并相似的表

PATINDEX中与[A-Z]匹配(U除外)的正则表达式

改进的SQL子字符串提取

排除具有部分匹配条件的记录

其中使用表名作为;行值;记录?

在 Oracle 21c 中透视文本值

当 2 列具有静态值并且第 3 列使用运算符 IN 时,对 PostgreSQL 和 3 列上的复杂索引的最佳查询

递归 CTE 附加为行

Clickhouse:左连接表到外部数组

计算 BigQuery 中列的中值差 - 分析函数不能作为聚合函数的参数

Postgres存在限制问题「小值」

如何使用SQL将患者平均分配给他们所在地区的doctor

带有数组输入参数的Snowflake UDF优化

检索具有相同位置的最小和最大store 数量

根据是否存在值组合分组并 Select 行

MIN MAX 值与条件绑定

有没有一种方法可以将始终遵循序列的单个字段的值组合起来,以创建每个 ID 的所有移动?

Oracle SQL 查询自行运行,但在包装到select count(*) from ()时失败

Snowflake SQL group-by 的行为不同,具体取决于列是按位置引用还是按别名引用