Divisão de string separada por vírgula na função PL / pgSQL
Estou tentando escrever uma função que recebe um ID como entrada e atualiza alguns campos nesse ID fornecido. Até agora, é assim:
CREATE FUNCTION update_status(p_id character varying,
p_status character varying DEFAULT NULL::character varying) RETURNS character varying
LANGUAGE plpgsql
AS
$$ DECLARE v_row_count bigint DEFAULT 0; v_result varchar(255); BEGIN IF p_id IS NOT NULL THEN SELECT count(user_id) INTO v_row_count FROM test WHERE user_id = p_id; END IF; IF v_row_count <= 0 THEN v_result = 'User not found'; RETURN v_result; ELSE IF p_id NOT LIKE '%,%' THEN UPDATE test SET status = p_status, updated_by = 'admin' WHERE user_id IN (p_id); ELSE --Here comes split and pass multiple IDs into an IN() operator END IF; END IF; END $$;
ALTER FUNCTION update_status(varchar, varchar) OWNER TO postgres;
Agora, ele deve aceitar apenas um ID de cada vez, mas eu me pergunto se posso fazer com que ele também aceite vários IDs - talvez até centenas - uma vez, dividindo essa única string em uma matriz de IDs se ela tiver um delimitador de vírgula, então passe para um IN()operador. Como posso dividir uma string em uma matriz para que possa alimentá-la para um IN()operador?
Respostas
Blue Star já mencionou que existe uma função embutida para converter uma string separada por vírgulas em um array.
Mas eu sugiro que não passe uma string separada por vírgulas para começar. Se você deseja passar um número variável de IDs, use um variadicparâmetro.
Você também não precisa primeiro executar um SELECT, você pode perguntar ao sistema quantas linhas foram atualizadas após a instrução UPDATE.
CREATE FUNCTION update_status(p_status text, p_id variadic integer[])
RETURNS character varying
LANGUAGE plpgsql
AS
$$ DECLARE v_row_count bigint DEFAULT 0; BEGIN UPDATE test SET status = p_status, updated_by = 'admin' WHERE user_id = any (p_id); get diagnostics v_row_count = row_count; if v_row_count = 0 then return 'User not found'; end if; return concat(v_row_count, ' users updated'); END $$;
Você pode usá-lo assim:
select update_status('active', 1);
select update_status('active', 5, 8, 42);
Se, por algum motivo, você "tiver" que passar isso como um único argumento, use uma matriz real em vez disso:
CREATE FUNCTION update_status(p_status text, p_id integer[])
Então passe assim:
select update_status('active', array[5,8,42]);
ou
select update_status('active', '{5,8,42}');
Existe uma função para isso, consulte os documentos .
SELECT string_to_array('str1,str2,str3,str4', ',');
string_to_array
-----------------------
{str1,str2,str3,str4}
Observe que, uma vez que é uma matriz, você deseja que sua condição se pareça com isto -
WHERE user_id = ANY(string_to_array(p_id, ',');