PL / pgSQL işlevinde virgülle ayrılmış dizeyi bölme

Sep 26 2020

Girdi olarak bir ID alan bir fonksiyon yazmaya ve verilen ID'deki bazı alanları güncellemeye çalışıyorum. Şimdiye kadar şöyle görünüyor:

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;

Şimdi, bir seferde yalnızca bir kimliği kabul etmesi gerekiyor, ancak virgül ayırıcısı varsa, bu tek dizeyi bir kimlik dizisine bölerek birden çok kimliği (hatta belki yüzlerce) kabul edip edemeyeceğimi merak ediyorum. bunları bir IN()operatöre iletin. Bir dizeyi bir IN()operatöre besleyebilmek için bir diziye nasıl bölebilirim ?

Yanıtlar

4 a_horse_with_no_name Sep 26 2020 at 20:05

Blue Star, virgülle ayrılmış bir dizeyi bir diziye dönüştürmek için yerleşik bir işlev olduğundan daha önce bahsetti.

Ama başlamak için virgülle ayrılmış bir dizenin geçmemesini öneririm. Değişken sayıda kimlik iletmek istiyorsanız bir variadicparametre kullanın .

Ayrıca önce bir SELECT çalıştırmanız gerekmez, sisteme UPDATE ifadesinden sonra kaç satırın güncellendiğini sorabilirsiniz.

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 $$;

Bunu şu şekilde kullanabilirsiniz:

select update_status('active', 1);
select update_status('active', 5, 8, 42);

Herhangi bir nedenle, bunu tek bir bağımsız değişken olarak iletmeniz gerekiyorsa, bunun yerine gerçek bir dizi kullanın:

CREATE FUNCTION update_status(p_status text, p_id integer[]) 

Öyleyse şu şekilde geçirin

select update_status('active', array[5,8,42]);

veya

select update_status('active', '{5,8,42}');
1 BlueStar Sep 26 2020 at 19:19

Bkz Bunun için bir işlev var docs .

SELECT string_to_array('str1,str2,str3,str4', ',');

    string_to_array
-----------------------
 {str1,str2,str3,str4}

Bir dizi olduğunda, durumunuzun şöyle görünmesini isteyeceğinizi unutmayın -

WHERE user_id = ANY(string_to_array(p_id, ',');