在 Postgres 中使用 table 值参数调用函数

Calling function with table valued parameters in Postgres

我从早上开始就遇到了一个问题,花了很多时间,但未能调用给定的函数。

函数定义:

CREATE OR REPLACE FUNCTION public.proc_mc2cdnpf_insertupdatev3(
    tblnotesv3 typupdate_notesv3,
    tbldoclinks typupdate_guidparameter,
    iuserid integer,
    shtmltext character varying,
    OUT snoteid character varying,
    OUT inoteid integer,
    OUT inoteactivityid integer)
    RETURNS record
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE 
AS $BODY$    
#variable_conflict use_variable
    declare         sNote VARCHAR;
    declare sLoggedInUser VARCHAR(20);
    declare     dtCurrDateTime timestamp;
    declare     iCurrDate int;
    declare     iCurrTime INT;
    declare iNewNoteID INT;
BEGIN

/*
    proc_MC2CDNPF_InsertUpdateV3
    2018-04-23      Dennis Sebenick

    2018-04-23      
        - Initial creation of new proc for storing additional HTML text value.  
        - This proc is going to help bridge the old note system to a new note storage method

    2018-04-25
    - Added iNoteID / iNoteActivityID for output

    2018-06-01
    - Update to typUpdate_NotesV3 - removed additional CDN rows for long text

    2091-05-08
        Rupali Shah
        web 1753-added RTRIM(isnull(NOTE_HDQTRS,''))  while creating sNoteID

*/
/******************************
** File:  proc_MC2CDNPF_InsertUpdateV3
** Desc:  Insert/Update account notes
** Auth:  Rupali Shah
** Date:  2019-05-08
**************************
** Change History
**************************
** Date                                Dev                        JIRA                                       Description 
**2019-05-08                Rupali Shah                 Web 1753                        -added RTRIM(isnull(NOTE_HDQTRS,'')) while creating sNoteID
*******************************/
    SELECT dtCurrDateTime = fnGetDate();
    SELECT iCurrDate = fnMC2DateToMC2(dtCurrDateTime);
    SELECT iCurrTime = fnMC2DateTimeToMC2(dtCurrDateTime);

    /*==========================================
        Retrieve Update fields from parameter
    ============================================*/
    select  
          NoteID,
          NOTE_NOTES,
          NOTE_LOGGEDINUSER,
          coalesce(NOTE_ID, 0)
        INTO SNoteID,sNote,sLoggedInUser,iNewNoteID
    from 
        tblNotesV3
    LIMIT 1;

    /************************************************
        2018-04-18      DKS
        Added in to update new note table
    *************************************************/
    IF (iNewNoteID > 0)
    THEN
    BEGIN
        IF (LENGTH(sNote) > 0)
        THEN
        BEGIN
            UPDATE 
                NoteDetails
            SET
                sNote = sNote,
                sNoteHTML = sHTMLText,
                iNoteEditedBy = iUserID,
                dtNoteEdited = dtCurrDateTime
            WHERE
                iNoteID = iNewNoteID;

            IF (ROWCOUNT = 0)
            THEN
            BEGIN
                INSERT INTO 
                    NoteDetails
                    (
                        iNoteType,
                        sNote,
                        sNoteHTML,
                        iNoteEnteredBy,
                        dtNoteEntered
                    )
                    VALUES
                    (   9,         -- iNoteType - int
                        sNote,       -- sNote - VARCHAR(max)
                        sHTMLText,       -- sNoteHTML - VARCHAR(max)
                        iUserID,         -- iNoteEnteredBy - int
                        dtCurrDateTime
                ) RETURNING iNewNoteID;

            END;
            END IF;
        END;
        END IF;
    END;
    ELSE
    BEGIN
        -- Inserting a New Activity
        -- 2018-04-18       DKS
        -- - Insert to new note table.
        IF (LENGTH(sNote) > 0)
        THEN
        BEGIN
            INSERT INTO 
                NoteDetails
                (
                    iNoteType,
                    sNote,
                    sNoteHTML,
                    iNoteEnteredBy,
                    dtNoteEntered
                )
                VALUES
                (   9,         -- iNoteType - int
                    sNote,       -- sNote - VARCHAR(max)
                    sHTMLText,       -- sNoteHTML - VARCHAR(max)
                    iUserID,         -- iNoteEnteredBy - int
                    dtCurrDateTime
            ) RETURNING iNewNoteID;
        END;
        END IF;
    END;
    END IF;

    /************************************************
        End new note table insert / update
    *************************************************/

    IF EXISTS(SELECT * FROM MC2CDNPF WHERE MC2CDNPF.iNoteID = iNoteID)
    THEN
    BEGIN
        UPDATE 
            MC2CDNPF
        SET
            CDNNOTES = '',
            CDNFDATE = fnMC2DateToMC2(TblNotesUpdate.NOTE_DDATE),
            CDNREASN = TblNotesUpdate.NOTE_REASN,
            CDNPRIOR = TblNotesUpdate.NOTE_PRIOR,
            CDNTAGGED = TblNotesUpdate.NOTE_TAGGED,
            iNoteID =  iNewNoteID
        FROM
            MC2CDNPF
        JOIN
            tblNotesV3 TblNotesUpdate
        ON
            MC2CDNPF.iNoteID = TblNotesUpdate.NOTE_ID
        WHERE
            MC2CDNPF.CDNDSEQN = 1;

    END;
    ELSE
    BEGIN
        SELECT 

                TRIM(coalesce(NOTE_CMPANY,'')) || 
                TRIM(coalesce(NOTE_BUSNSS,'')) || 
                TRIM(coalesce(NOTE_CUSNBR,'')) ||
                TRIM(coalesce(NOTE_ENTITY,'')) ||
                TRIM(coalesce(NOTE_HDQTRS,'')) ||
                CAST( iCurrDate AS VARCHAR(8)) || 
                CAST( iCurrTime AS VARCHAR(10))
                INTO sNoteID
        FROM
            tblNotesV3
        LIMIT 1;

        INSERT INTO
            MC2CDNPF
            (
                CDNDSEQN, 
                CDNNOTES, 
                CDNCMPANY, 
                CDNCUSNBR, 
                CDNBUSNSS, 
                CDNENTITY, 
                CDNHDQTRS, 
                CDNRPTCON,
                CDNFULNME, 
                CDNAGNIDN, 
                CDNDDATE, 
                CDNDTIME, 
                CDNREASN,
                CDNTUSER, 
                CDNADATE, 
                CDNTAGGED, 
                CDNFDATE, 
                CDNPRIOR,  
                CDNDTASRC, 
                CDNODATE, 
                CDNOTIME,
                iNoteID
            )
        SELECT
            1, 
            '',                             -- 6/1/2018 DKS - no longer storing note in MC2CDNPF
            coalesce(NOTE_CMPANY,''), 
            coalesce(NOTE_CUSNBR,''), 
            coalesce(NOTE_BUSNSS,''), 
            coalesce(NOTE_ENTITY,''), 
            coalesce(NOTE_HDQTRS,''), 
            coalesce(NOTE_RPTCON,''),
            NOTE_FULNME, 
            coalesce(NOTE_AGNIDN,''), 
            iCurrDate, 
            iCurrTime, 
            NOTE_REASN, 
            NOTE_TUSER, 
            iCurrDate, 
            coalesce(NOTE_TAGGED,''), 
            iCurrDate, 
            NOTE_PRIOR, 
            coalesce(NOTE_DTASRC,''),
            iCurrDate, 
            iCurrTime,
            iNewNoteID
        FROM
            tblNotesV3 TblSource;

    END;
    END IF;

    -- There are attachments to link
    IF EXISTS(SELECT * FROM tblDocLinks)
    THEN
    BEGIN
        CALL public.proc_Documents_AddLinkMultiple_LinkID (tblDocLinks, 9, 0, sNoteID, iUserID);
    END;
    END IF;
     iNoteID := iNewNoteID;
     iNoteActivityID := 0;  

END;
$BODY$;

我正在尝试通过以下两种方式调用我的函数:

方法一:

SELECT public.proc_MC2CDNPF_InsertUpdateV3
(
    (SELECT w::typupdate_notesv3 FROM (TABLE tblnotesv31) w ) ,
    (SELECT w1::typupdate_guidparameter FROM (TABLE tbldoclinks1) w1 ) ,
    1,
    'test text'
)  

但失败并出现以下错误:

ERROR: query has no destination for result data HINT: If you want to discard the results of a SELECT, use PERFORM instead. CONTEXT: PL/pgSQL function proc_mc2cdnpf_insertupdatev3(typupdate_notesv3,typupdate_guidparameter,integer,character varying) line 41 at SQL statement SQL state: 42601

方法二:

SELECT * 
from proc_MC2CDNPF_InsertUpdateV3
(
    (SELECT w::typupdate_notesv3 FROM (TABLE tblnotesv31) w ) ,
    (SELECT w1::typupdate_guidparameter FROM (TABLE tbldoclinks1) w1 ) ,
    1,
    'test text'
)  

再次失败说:

ERROR: query has no destination for result data HINT: If you want to discard the results of a SELECT, use PERFORM instead. CONTEXT: PL/pgSQL function proc_mc2cdnpf_insertupdatev3(typupdate_notesv3,typupdate_guidparameter,integer,character varying) line 41 at SQL statement SQL state: 42601

有人可以帮我看看我的函数调用到底出了什么问题吗?

从第 41 行开始(正如错误消息告诉您的那样),您得到:

SELECT dtCurrDateTime = fnGetDate();
SELECT iCurrDate = fnMC2DateToMC2(dtCurrDateTime);
SELECT iCurrTime = fnMC2DateTimeToMC2(dtCurrDateTime);

我假设您想在那里设置变量。但是你做错了。 (看起来你试图使用 SQL 服务器语法。这是将函数从 SQL 服务器移植到 Postgres 的尝试吗?还有 BEGIN ... END 块用于 IFs和 ELSEs,它们在 Postgres 中是不必要的(但无害),但在 SQL 服务器中需要。)

或者使用 INTO:

SELECT fnGetDate() INTO dtCurrDateTime;
SELECT fnMC2DateToMC2(dtCurrDateTime) INTO iCurrDate;
SELECT fnMC2DateTimeToMC2(dtCurrDateTime) INTO iCurrTime;

或者,由于您实际上并不是在查询 table,简单的赋值也应该有效:

dtCurrDateTime = fnGetDate();
iCurrDate = fnMC2DateToMC2(dtCurrDateTime);
iCurrTime = fnMC2DateTimeToMC2(dtCurrDateTime);

可能还有其他行有同样的错误,你应该检查整个代码。