在存储函数中组合多行的结果

问题描述 投票:0回答:1

我们知道,存储函数返回单个值,但我想知道如何在单个结果中显示多个结果。

我用的是northwind数据库。

这是我的函数,它只返回一个值:

CREATE OR REPLACE FUNCTION FN_PRODUCTOS_REGISTRADOS_EN_FECHAS(
    FN_ORDER_DATE IN ORDERS.ORDER_DATE%TYPE)
    RETURN VARCHAR2
    IS
    NOMBRE VARCHAR2 (500);
BEGIN
    SELECT COMPANY_NAME|| ' ' ||COUNTRY|| ' ' ||PRODUCT_NAME|| ' ' ||ORDER_DATE 
    AS NOMBRE_DE_COMPAÑIA_PAIS_NOMBRE_PRODUCTO_FECHA_DE_ORDEN
    INTO NOMBRE
    FROM SUPPLIERS S
    INNER JOIN PRODUCTS P ON S.SUPPLIER_ID=P.SUPPLIER_ID
    INNER JOIN ORDER_DETAILS OD ON P.PRODUCT_ID=OD.PRODUCT_ID
    INNER JOIN ORDERS O ON OD.ORDER_ID=O.ORDER_ID
    WHERE ORDER_DATE=FN_ORDER_DATE;
    RETURN NOMBRE;
END;

SELECT FN_PRODUCTOS_REGISTRADOS_EN_FECHAS(TO_DATE('07/16/1996','MM/DD/YYYY')) FROM DUAL;

查询如下:

SELECT COMPANY_NAME|| ' ' ||COUNTRY|| ' ' ||PRODUCT_NAME|| ' ' ||ORDER_DATE 
AS NOMBRE_DE_COMPAÑIA_PAIS_NOMBRE_DE_PRODUCTO_FECHA_DE_ORDEN
FROM SUPPLIERS S
INNER JOIN PRODUCTS P ON S.SUPPLIER_ID=P.SUPPLIER_ID
INNER JOIN ORDER_DETAILS OD ON P.PRODUCT_ID=OD.PRODUCT_ID
INNER JOIN ORDERS O ON OD.ORDER_ID=O.ORDER_ID
WHERE ORDER_DATE=TO_DATE('07/16/1996','MM/DD/YYYY');

查询返回3行,仅使用查询返回的结果如下:

COMPANY_NAME                             COUNTRY         PRODUCT_NAME                             NOMBRE_D
---------------------------------------- --------------- ---------------------------------------- --------
Heli Süßwaren GmbH & Co. KG              Germany         Schoggi Schokolade                       16/07/96
Plutzer Lebensmittelgroßmärkte AG        Germany         Original Frankfurter grüne Soße          16/07/96
Aux joyeux ecclésiastiques               France          Chartreuse verte                         16/07/96

但是使用该函数会返回错误 ORA-01422,我想知道是否可以合并之前的 3 个结果,以便在调用该函数而不是显示错误时它会在单个结果中显示 3 个结果专门使用存储函数进行查询。

我尝试了以下 usando for loop end loop:

CREATE OR REPLACE FUNCTION FN_PRODUCTOS_REGISTRADOS_EN_FECHAS(
    FN_ORDER_DATE IN ORDERS.ORDER_DATE%TYPE)
    RETURN VARCHAR
    IS
    NOMBRE VARCHAR (500);
    CURSOR LISTA IS
    SELECT COMPANY_NAME|| ' ' ||COUNTRY|| ' ' ||PRODUCT_NAME|| ' ' ||ORDER_DATE 
    AS NOMBRE_DE_COMPAÑIA_PAIS_NOMBRE_PRODUCTO_FECHA_DE_ORDEN
    INTO NOMBRE
    FROM SUPPLIERS S
    INNER JOIN PRODUCTS P ON S.SUPPLIER_ID=P.SUPPLIER_ID
    INNER JOIN ORDER_DETAILS OD ON P.PRODUCT_ID=OD.PRODUCT_ID
    INNER JOIN ORDERS O ON OD.ORDER_ID=O.ORDER_ID
    WHERE ORDER_DATE=FN_ORDER_DATE;
BEGIN
    FOR NOMBRE IN LISTA 
    LOOP
    RETURN NOMBRE;
    END LOOP;
END;

我得到的错误如下:

LINE/COL  ERROR
--------- -------------------------------------------------------------
18/5      PL/SQL: Statement ignored
18/12     PLS-00382: the type of expression is not correct
Errors: check compiler log

好吧,现在我真的迷失了试图找到这个错误的解决方案或替代解决方案。

oracle11g oracle-sqldeveloper plsqldeveloper
1个回答
0
投票

我不完全确定我理解你的意思,据我了解:

您当前方法的问题是函数中的游标 LISTA 未正确定义。游标需要定义为返回多行和多列的查询,但在您当前的定义中,您包含了一个 INTO 子句,游标不需要它。

要解决这个问题,您可以按如下方式定义光标:

CURSOR LISTA IS
SELECT COMPANY_NAME|| ' ' ||COUNTRY|| ' ' ||PRODUCT_NAME|| ' ' ||ORDER_DATE 
AS NOMBRE_DE_COMPAÑIA_PAIS_NOMBRE_PRODUCTO_FECHA_DE_ORDEN
FROM SUPPLIERS S
INNER JOIN PRODUCTS P ON S.SUPPLIER_ID=P.SUPPLIER_ID
INNER JOIN ORDER_DETAILS OD ON P.PRODUCT_ID=OD.PRODUCT_ID
INNER JOIN ORDERS O ON OD.ORDER_ID=O.ORDER_ID
WHERE ORDER_DATE=FN_ORDER_DATE;

然后,您可以使用循环将结果连接成一个字符串,并在循环结束时返回:

CREATE OR REPLACE FUNCTION FN_PRODUCTOS_REGISTRADOS_EN_FECHAS(
    FN_ORDER_DATE IN ORDERS.ORDER_DATE%TYPE)
    RETURN VARCHAR
    IS
    NOMBRE VARCHAR (500);
    RESULT VARCHAR(4000);
    CURSOR LISTA IS
    SELECT COMPANY_NAME|| ' ' ||COUNTRY|| ' ' ||PRODUCT_NAME|| ' ' ||ORDER_DATE 
    AS NOMBRE_DE_COMPAÑIA_PAIS_NOMBRE_PRODUCTO_FECHA_DE_ORDEN
    FROM SUPPLIERS S
    INNER JOIN PRODUCTS P ON S.SUPPLIER_ID=P.SUPPLIER_ID
    INNER JOIN ORDER_DETAILS OD ON P.PRODUCT_ID=OD.PRODUCT_ID
    INNER JOIN ORDERS O ON OD.ORDER_ID=O.ORDER_ID
    WHERE ORDER_DATE=FN_ORDER_DATE;
BEGIN
    RESULT := '';
    FOR NOMBRE IN LISTA LOOP
        RESULT := RESULT || NOMBRE.NOMBRE_DE_COMPAÑIA_PAIS_NOMBRE_PRODUCTO_FECHA_DE_ORDEN || CHR(10);
    END LOOP;
    RETURN RESULT;
END;

上面的代码会将每一行的结果连接成一个由换行符分隔的字符串 (CHR(10)) 并返回它。

© www.soinside.com 2019 - 2024. All rights reserved.