从表中选择所有的 Oracle 函数

Posted

技术标签:

【中文标题】从表中选择所有的 Oracle 函数【英文标题】:Oracle function with select all from tables 【发布时间】:2018-04-06 10:15:36 【问题描述】:
SELECT DISTINCT L.* FROM LABALES L , MATCHES M 
WHERE M.LIST LIKE '%ENG' 
ORDER BY L.ID

我需要用这个选择创建函数,我试过了,但它不起作用。

CREATE OR REPLACE FUNCTION getSoccerLists
RETURN varchar2  IS 
list varchar2(2000);
BEGIN
   SELECT DISTINCT L.* FROM LABALES L , MATCHES M 
   WHERE M.LIST LIKE '%ENG' 
   ORDER BY L.ID
   return list;
END;

我将如何创建从表 L 中返回所有内容的函数。

谢谢

【问题讨论】:

没有加入条件?该查询没有多大意义...... 它给出了什么错误?? @jarlh 当我运行选择时,我得到了结果,所以选择很好。但我想要它的功能.. @NishantGupta sql 语句被忽略,qouted 标识符行尾,缺少双引号 抱歉,以下链接不是来自 SO,但绝对可以帮助您解决问题-sqljana.wordpress.com/2017/01/22/… 【参考方案1】:

您可以在使用游标查询的过程中使用DBMS_SQL.RETURN_RESULT(Oracle12c 及更高版本)的隐式结果。

CREATE OR REPLACE PROCEDURE getSoccerLists 
AS
x SYS_REFCURSOR;
BEGIN
  OPEN x FOR SELECT DISTINCT L.* FROM LABALES L 
   JOIN  MATCHES M  ON ( 1=1 ) -- join condition
       WHERE M.LIST LIKE '%ENG' 
       ORDER BY L.ID; 
   DBMS_SQL.RETURN_RESULT(x);
END;
/

然后简单地调用过程

EXEC getSoccerLists;

对于较低版本(Oracle 11g),您可以使用打印命令显示光标的o/p,将ref cursor 作为out 参数传递。

CREATE OR REPLACE PROCEDURE getSoccerLists (x OUT SYS_REFCURSOR) 
AS
BEGIN
  OPEN x FOR SELECT DISTINCT L.* FROM LABALES L 
   JOIN  MATCHES M  ON ( 1=1 ) -- join condition
       WHERE M.LIST LIKE '%ENG' 
       ORDER BY L.ID; 
END;
/

然后,在 SQL* Plus 中或在 SQL developer 和 Toad 中作为脚本运行,您可以使用它获得结果。

VARIABLE r REFCURSOR;
EXEC  getSoccerLists (:r);

PRINT r;

另一种选择是通过在包中定义结果记录类型的集合来使用 TABLE 函数。

参考Create an Oracle function that returns a table

【讨论】:

DBMS_SQL.RETURN_RESULT 仅适用于 Oracle 12c。 @Kaushik Nayak 当我像你写的那样我得到错误请 00302 必须声明组件 Return_result @civesuas_sine:你应该使用 11g 吗?请参阅我的更新答案。【参考方案2】:

我猜这个问题是对您之前提出的问题的重复,您希望在其中获取表格的所有列但放入单独的列中。我已经回答说如果您通过SELECT 语句调用您的函数,您将无法做到这一点。如果你在匿名块中调用你的函数,你可以在单独的列中显示它。

这里Oracle function returning all columns from tables

或者,您可以得到用逗号(,)或管道(|)分隔的结果,如下所示:

CREATE OR REPLACE
  FUNCTION getSoccerLists
    RETURN VARCHAR2
  IS
    list VARCHAR2(2000);
  BEGIN
    SELECT col1
      ||','
      ||col2
      ||','
      ||col2
    INTO LIST
    FROM SOCCER_PREMATCH_LISTS L ,
      SOCCER_PREMATCH_MATCHES M
    WHERE M.LIST LIKE '%' || (L.SUB_LIST)  || '%'
    AND (TO_TIMESTAMP((M.M_DATE      || ' '      || M.M_TIME), 'DD.MM.YYYY HH24:MI') >
      (SELECT SYSTIMESTAMP AT TIME ZONE 'CET' FROM DUAL
      ))
    ORDER BY L.ID");
  Return list;
  End;

请注意,如果列大小增加了 2000 个字符,那么您将再次丢失数据。

编辑:

来自你的 cmets

我希望它返回一组结果。

然后您需要创建一个varchar 的表,然后从函数中返回它。见下文:

CREATE TYPE var IS  TABLE OF VARCHAR2(2000);
/

CREATE OR REPLACE
FUNCTION getSoccerLists
  RETURN var
IS
  --Initialization
  list VAR :=var();
BEGIN
  SELECT NSO ||',' ||NAME BULK COLLECT INTO LIST FROM TEST;
  RETURN list;
END;

执行:

select * from table(getSoccerLists);

注意:在函数中,我使用了一个名为 test 的表及其列。你用它的列名替换你的表。

编辑 2:

--Create a object with columns same as your select statement
CREATE   TYPE v_var IS  OBJECT
(
col1 NUMBER,
col2 VARCHAR2(10)
)
/
--Create a table of your object
CREATE OR REPLACE TYPE var IS TABLE OF v_var;
/

CREATE OR REPLACE FUNCTION getSoccerLists
  RETURN var
IS
  --Initialization
  list VAR :=var();
BEGIN
   --You above object should have same columns with same data type as you are selecting here 
  SELECT v_var( NSO ,NAME) BULK COLLECT INTO LIST FROM TEST;
  RETURN list;
END;

执行:

select * from table(getSoccerLists);

【讨论】:

@civesuas_sine。您需要放置实际的列。我不会为您提供现成的代码。这只是一个帮助您解决问题的演示。只需替换表的所有列,通过,| 将其分隔。 精确提取返回的行数超过了请求的行数 @civesuas_sine 这意味着您的查询在您的过滤子句中返回多行。如果是这种情况,那么您需要确保您的查询返回单行,或者您需要使用sys_refcursor 或贴花object 来返回结果集表 ORA-00955:名称已被现有对象使用,当我尝试运行语句时 @civesuas_sine 不确定您执行的是什么以及如何执行。我向您展示了一个工作演示。同样如前所述,您不能像图片中显示的那样做。最多可以使用,| 分隔结果并在单个列中显示结果,因为您要返回一个varchar 表。或者您需要创建一个表类型的对象然后使用它。见编辑2【参考方案3】:

这不是关于如何为此构建函数的答案,因为我建议将其设为视图:

CREATE OR REPLACE VIEW view_soccer_list AS
  SELECT * 
  FROM soccer_prematch_lists l
  WHERE EXISTS
  (
    SELECT *
    FROM soccer_prematch_matches m 
    WHERE m.list LIKE '%' || (l.sub_list) || '%' 
      AND TO_TIMESTAMP((m.m_date || ' ' || m.m_time), 'DD.MM.YYYY HH24:MI') > 
            (SELECT SYSTIMESTAMP AT TIME ZONE 'CET' FROM DUAL)
  );

然后在查询中调用它:

SELECT * FROM view_soccer_list ORDER BY id;

(将ORDER BY 子句放在视图中是没有意义的,因为您像访问表一样访问视图,并且表数据被认为是无序的,因此您不能依赖该顺序。对于您可以使用FROM TABLE (getSoccerLists) 访问流水线函数。始终将ORDER BY 子句放在最终查询中。)

【讨论】:

@ThorstenKettnerDont need view,你能用这个选择创建函数吗? 好吧,我只是觉得让一个函数做同样的事情是没有意义的。视图的唯一区别是它的速度较慢。如果你还是想写一个函数,你可能想查找流水线函数:oracle-base.com/articles/misc/pipelined-table-functions

以上是关于从表中选择所有的 Oracle 函数的主要内容,如果未能解决你的问题,请参考以下文章

如何从表中选择所有列,以及 ROWNUM 等其他列?

SQL 从表中选择条目,其中属性等于参数,否则选择 * 条目

如果存在则从表中选择,否则从oracle中的另一个表中选择

通过只知道没有时间的日期从表中选择 (ORACLE)

通过在Oracle中分组一列从表中选择数据

如何从表中选择带有 oracle sql 中的 group by 子句的嵌套 json 对象?