Ludovico Frate
Ludovico Frate

Reputation: 29

Postgresql Trigger Error: more than one row returned by a subquery used as an expression

I have a PostgreSQL database with this function enabled. The function should automatically populate the num_accessione field using values from other fields, as can be seen from the code.

    CREATE OR REPLACE FUNCTION dati_raccolta_pop_accessione()
    RETURNS TRIGGER AS 
    $datiraccoltapopaccessione$
    BEGIN
        IF (TG_OP='INSERT') THEN
            UPDATE dati_raccolta
            SET num_accessione = (
                SELECT
                    CASE
                        WHEN interesse_agricolo = 'si' THEN
                            CONCAT(
                                banca_germoplasma, '_A_', 
                                REGEXP_REPLACE(data_raccolta::text, '-', '', 'g'), '_', gid, '_',
                                UPPER(
                                    REGEXP_REPLACE(
                                        REGEXP_REPLACE(nome_raccoglitore, '\y(\w)\w*', '\1', 'g'), 
                                        '\s+', '', 'g'
                                    )
                                )
                            )
                        WHEN interesse_agricolo = 'no' THEN
                            CONCAT(
                                banca_germoplasma, '_N_', 
                                REGEXP_REPLACE(data_raccolta::text, '-', '', 'g'), '_', gid, '_',
                                UPPER(
                                    REGEXP_REPLACE(
                                        REGEXP_REPLACE(nome_raccoglitore, '\y(\w)\w*', '\1', 'g'), 
                                        '\s+', '', 'g'
                                    )
                                )
                            )
                    END
                FROM dati_raccolta
            );
        ELSIF (TG_OP='UPDATE') THEN
            UPDATE dati_raccolta AS t
            SET num_accessione = (
                SELECT
                    CASE
                        WHEN interesse_agricolo = 'si' THEN
                            CONCAT(
                                banca_germoplasma, '_A_', 
                                REGEXP_REPLACE(data_raccolta::text, '-', '', 'g'), '_', gid, '_',
                                UPPER(
                                    REGEXP_REPLACE(
                                        REGEXP_REPLACE(nome_raccoglitore, '\y(\w)\w*', '\1', 'g'), 
                                        '\s+', '', 'g'
                                    )
                                )
                            )
                        WHEN interesse_agricolo = 'no' THEN
                            CONCAT(
                                banca_germoplasma, '_N_', 
                                REGEXP_REPLACE(data_raccolta::text, '-', '', 'g'), '_', gid, '_',
                                UPPER(
                                    REGEXP_REPLACE(
                                        REGEXP_REPLACE(nome_raccoglitore, '\y(\w)\w*', '\1', 'g'), 
                                        '\s+', '', 'g'
                                    )
                                )
                            )
                    END
                FROM dati_raccolta
            );
        END IF;
        
        RETURN NEW;
    END;
    $datiraccoltapopaccessione$ 
    LANGUAGE plpgsql;
    
    
    
    CREATE TRIGGER dati_raccolta_pop_num_accessione_insert
    AFTER INSERT ON dati_raccolta
    FOR EACH STATEMENT
    EXECUTE PROCEDURE dati_raccolta_pop_accessione();
    
    CREATE TRIGGER dati_raccolta_pop_num_accessione_update
    AFTER UPDATE ON dati_raccolta
    FOR EACH ROW
    WHEN (OLD.geom IS DISTINCT FROM NEW.geom)
    EXECUTE PROCEDURE dati_raccolta_pop_accessione();

Unfortunately, I receive the following error:

ERROR: more than one row returned by a subquery used as an expression CONTEXT: SQL statement "UPDATE dati_raccolta SET num_accessione = ( SELECT CASE WHEN interesse_agricolo = 'si' THEN CONCAT( banca_germoplasma, 'A', REGEXP_REPLACE(data_raccolta::text, '-', '', 'g'), '', gid, '', UPPER( REGEXP_REPLACE( REGEXP_REPLACE(nome_raccoglitore, '\y(\w)\w*', '\1', 'g'), '\s+', '', 'g' ) ) ) WHEN interesse_agricolo = 'no' THEN CONCAT( banca_germoplasma, 'N', REGEXP_REPLACE(data_raccolta::text, '-', '', 'g'), '', gid, '', UPPER( REGEXP_REPLACE( REGEXP_REPLACE(nome_raccoglitore, '\y(\w)\w*', '\1', 'g'), '\s+', '', 'g' ) ) ) END FROM dati_raccolta )" PL/pgSQL function dati_raccolta_pop_accessione() line 4 at SQL statement

Upvotes: 0

Views: 34

Answers (1)

Ludovico Frate
Ludovico Frate

Reputation: 29

Here the solution for the insert steatment:

CREATE OR REPLACE FUNCTION dati_raccolta_pop_accessione()
RETURNS TRIGGER AS 
$datiraccoltapopaccessione$
DECLARE
    accessione_calcolata TEXT;
BEGIN
    IF (TG_OP='INSERT') THEN
        accessione_calcolata := (
                CASE
                    WHEN NEW.interesse_agricolo = 'si' THEN concat(NEW.banca_germoplasma, '_A_', REGEXP_REPLACE(NEW.data_raccolta::text, '-', '', 'g'), '_', NEW.gid, '_', 
                        UPPER (
                            REGEXP_REPLACE (
                                REGEXP_REPLACE (NEW.nome_raccoglitore, '\y(\w)\w*', '\1', 'g'),'\s+', '', 'g'
                                )
                            )
                        ) 
                    WHEN NEW.interesse_agricolo = 'no' THEN concat(NEW.banca_germoplasma, '_N_', REGEXP_REPLACE(NEW.data_raccolta::text, '-', '', 'g'), '_', NEW.gid, '_', 
                        UPPER (
                            REGEXP_REPLACE (
                                REGEXP_REPLACE (NEW.nome_raccoglitore, '\y(\w)\w*', '\1', 'g'),'\s+', '', 'g'
                                )
                            )
                        )
                END
        );
    END IF;
    
    NEW.num_accessione := accessione_calcolata;
    RETURN NEW;
END;
$datiraccoltapopaccessione$ 
LANGUAGE plpgsql;

CREATE TRIGGER dati_raccolta_pop_num_accessione_insert
BEFORE INSERT ON dati_raccolta
FOR EACH ROW
EXECUTE FUNCTION dati_raccolta_pop_accessione();

Upvotes: 0

Related Questions