SELECT 中某些函数的布尔值 return

Boolean return value of some function inside SELECT

我正在 PL/SQL 中开发一个包。

这是我的规格:

TYPE outrec IS RECORD(
    tw_m_id                         NUMBER,
    tw_m_dealer_id                  NUMBER,
    tw_number                       NUMBER,
    check_uid                       NUMBER);
  TYPE outrecset IS TABLE OF outrec;

  FUNCTION report
  (
    p_watermark           IN NUMBER,
    p_param               IN NUMBER,
    p_index               IN NUMBER
  ) RETURN outrecset
    PIPELINED;

这是我的 body:

FUNCTION func
  (
    p_watermark           => p_watermark,
    p_param               => p_param,
    p_index               => p_index
  )
  
   RETURN outrecset
    PIPELINED IS
    temp outrec;
  
  BEGIN
    before_report(p_watermark           => p_watermark,
                  p_param               => p_param,
                  p_index               => p_index);
  
    FOR c_rec IN (SELECT tw_m_id,
                         tw_m_dealer_id,
                         tw_number,
                         package_name.somefunction(tw_number) AS check_uid

                    FROM table1
                    JOIN table2 rk ON id1 = rk.id2
                    WHERE 1 = 1
                    AND id1 = rk.id2
                    AND id1 = p_param)
    
    LOOP
      temp.tw_m_tw_rechnungskopf_id       := c_rec.tw_m_tw_rechnungskopf_id;
      temp.tw_m_haendler_id_rechnung      := c_rec.tw_m_haendler_id_rechnung;
      temp.check_uid                      := c_rec.check_uid;
      PIPE ROW(temp);
    END LOOP;
  END;

我正在尝试从 package_name.somefunction(tw_number) AS check_uid 获取值。问题是 somefunction returns BOOLEAN 值。 当我将 check_uid 设置为 BOOLEAN 时,出现错误:PLS-00382:表达式类型错误,因为 SQL 当然不支持 BOOLEAN。我试过了:

CASE 
WHEN package_name.somefunction(tw_number) THEN true 
else false
END as check_uid

在 SELECT 中然后我得到错误:PL/SQL:ORA-00920:无效的关系运算符。

有人能告诉我怎么做吗PL/SQL 不是我最强的一面:(

通常您会在包中创建一个 returns 1/0 或 Y/N 的重载函数。但是由于您无权访问该包,您可以在 sql 查询中使用内联函数来为您执行此操作。

create or replace function func (parameter_i VARCHAR2) RETURN BOOLEAN
AS
BEGIN
  return true;
END;
/

WITH
  FUNCTION func_yn(parameter_i VARCHAR2)
  RETURN NUMBER
  IS
    l_return_value BOOLEAN;
  BEGIN
    l_return_value :=func(parameter_i => parameter_i);
    RETURN CASE l_return_value WHEN TRUE THEN 1 WHEN FALSE THEN 0 END;
  END func_yn;
SELECT 
  func_yn('test')
FROM dual;

编写一个简单的包装函数将 PL/SQL BOOLEAN 转换为 NUMBER 在 SQL 中有效且符合您的记录类型的数据类型,您可以将函数调用移到 SQL.

之外
CREATE FUNCTION MAP_BOOLEAN( truthy IN BOOLEAN ) RETURN NUMBER DETERMINISTIC
IS
BEGIN
  RETURN CASE truthy
         WHEN TRUE  THEN 1
         WHEN FALSE THEN 0
         ELSE NULL
         END;
END map_boolean;
/

所以您的规格是:

CREATE PACKAGE package_name IS
  TYPE outrec IS RECORD(
    tw_m_id        NUMBER,
    tw_m_dealer_id NUMBER,
    tw_number      NUMBER,
    check_uid      NUMBER
  );

  TYPE outrecset IS TABLE OF outrec;

  -- Note: This may be in another package but is here for convenience.
  FUNCTION somefunction(value IN NUMBER) RETURN BOOLEAN;

  FUNCTION report
  (
    p_watermark IN NUMBER,
    p_param     IN NUMBER,
    p_index     IN NUMBER
  ) RETURN outrecset PIPELINED;
END;
/

对应的正文是:

CREATE PACKAGE BODY package_name IS
  FUNCTION somefunction(value IN NUMBER) RETURN BOOLEAN
  IS
  BEGIN
    RETURN TRUE;
  END;

  PROCEDURE before_report(
    p_watermark IN NUMBER,
    p_param     IN NUMBER,
    p_index     IN NUMBER
  )
  IS
  BEGIN
    NULL;
  END;


  FUNCTION report(
    p_watermark IN NUMBER,
    p_param     IN NUMBER,
    p_index     IN NUMBER
  ) RETURN outrecset PIPELINED
  IS
    temp outrec;
  BEGIN
    before_report(
      p_watermark => p_watermark,
      p_param     => p_param,
      p_index     => p_index
    );

    FOR c_rec IN (
      SELECT tw_m_id,
             tw_m_dealer_id,
             tw_number
      FROM   table1
             JOIN table2 rk ON id1 = rk.id2
      WHERE  id1 = p_param
    )
    LOOP
      temp.tw_m_id        := c_rec.tw_m_id;
      temp.tw_m_dealer_id := c_rec.tw_m_dealer_id;
      temp.check_uid      := MAP_BOOLEAN(
                               PACKAGE_NAME.SOMEFUNCTION( c_rec.tw_number )
                             );
      PIPE ROW(temp);
    END LOOP;
  END;
END;
/

(注意:您还需要更新游标循环,因为您选择的值与记录的字段不匹配。)

db<>fiddle here