Buscando una forma de insertar una lista de registros basada en una matriz de UUID. Aquí está mi código de ejemplo:
CREATE OR REPLACE FUNCTION "AddGroupUsers" ( "@OrganizationID" UUID, "@GroupID" UUID, "@UserIDs" UUID[] ) RETURNS viud AS $func$ BEGIN FOR index IN "@UserIDs" LOOP INSERT INTO "UserGroups" ( "UserID", "GroupID", "OrganizationID" ) VALUES ( "@UserID"[index], "@GroupID", "@OrganizationID" ); END LOOP; END; $func$ LANGUAGE PLPGSQL;Obviamente no funciona, jajaja.
Quiero poder llamar:
SELECT "AddGroupUsers"( 'cb6e96db-73db-4b07-811f-c54b61d09fa4', '451a9ab7-02f6-4f63-bb87-80ad531ab490' array( '451a9ab7-02f6-4f63-bb87-80ad531ab490', '451a9ab7-02f6-4f63-bb87-80ad531ab491', '451a9ab7-02f6-4f63-bb87-80ad531ab492', '451a9ab7-02f6-4f63-bb87-80ad531ab493', '451a9ab7-02f6-4f63-bb87-80ad531ab494' )::uuid[] );Como nota al margen, tengo una restricción de clave única que garantiza que solo exista un registro para un ID de usuario y un ID de grupo. Si el segundo valor de la matriz rompe esa regla, ¿fallará toda la consulta y cómo puedo ignorarla para asegurarme de que se inserten el resto de los valores?
Use unnest y sql simple en lugar de plpgsql. Con esta tabla:
create table user_groups ( org_id uuid, grp_id uuid, use_id uuid, unique (grp_id, use_id) );Esta función insertará inexistente:
create or replace function AddGroupUsers( _org_id uuid, _grp_id uuid, _use_id uuid[] ) returns setof user_groups as $$ insert into user_groups (org_id, grp_id, use_id) select s.org_id, grp_id, use_id from ( select _org_id as org_id, _grp_id as grp_id, unnest(_use_id) as use_id ) s left join user_groups ug using (grp_id, use_id) where ug.grp_id is null returning * ; $$ language sql;Uso:
select * from AddGroupUsers( 'cb6e96db-73db-4b07-811f-c54b61d09fa4'::uuid, '451a9ab7-02f6-4f63-bb87-80ad531ab490'::uuid, array[ '451a9ab7-02f6-4f63-bb87-80ad531ab490', '451a9ab7-02f6-4f63-bb87-80ad531ab491', '451a9ab7-02f6-4f63-bb87-80ad531ab492', '451a9ab7-02f6-4f63-bb87-80ad531ab493', '451a9ab7-02f6-4f63-bb87-80ad531ab494' ]::uuid[] ); org_id | grp_id | use_id --------------------------------------+--------------------------------------+-------------------------------------- cb6e96db-73db-4b07-811f-c54b61d09fa4 | 451a9ab7-02f6-4f63-bb87-80ad531ab490 | 451a9ab7-02f6-4f63-bb87-80ad531ab490 cb6e96db-73db-4b07-811f-c54b61d09fa4 | 451a9ab7-02f6-4f63-bb87-80ad531ab490 | 451a9ab7-02f6-4f63-bb87-80ad531ab491 cb6e96db-73db-4b07-811f-c54b61d09fa4 | 451a9ab7-02f6-4f63-bb87-80ad531ab490 | 451a9ab7-02f6-4f63-bb87-80ad531ab492 cb6e96db-73db-4b07-811f-c54b61d09fa4 | 451a9ab7-02f6-4f63-bb87-80ad531ab490 | 451a9ab7-02f6-4f63-bb87-80ad531ab493 cb6e96db-73db-4b07-811f-c54b61d09fa4 | 451a9ab7-02f6-4f63-bb87-80ad531ab490 | 451a9ab7-02f6-4f63-bb87-80ad531ab494Según esta respuesta y la documentación oficial , podría declare una variable para almacenar cada ID de usuario, así:
CREATE OR REPLACE FUNCTION AddGroupUsers ( "@OrganizationID" UUID, "@GroupID" UUID, "@UserIDs" UUID[] ) RETURNS void AS $func$ DECLARE uID UUID; BEGIN FOREACH uID IN ARRAY "@UserIDs" LOOP INSERT INTO UserGroups ( UserID, GroupID, OrganizationID ) VALUES ( uID, "@GroupID", "@OrganizationID" ); END LOOP; END; $func$ LANGUAGE PLPGSQL;Y para llamarlo realmente:
SELECT AddGroupUsers( 'cb6e96db-73db-4b07-811f-c54b61d09fa4'::uuid, '451a9ab7-02f6-4f63-bb87-80ad531ab490'::uuid, array[ '451a9ab7-02f6-4f63-bb87-80ad531ab490', '451a9ab7-02f6-4f63-bb87-80ad531ab491', '451a9ab7-02f6-4f63-bb87-80ad531ab492', '451a9ab7-02f6-4f63-bb87-80ad531ab493', '451a9ab7-02f6-4f63-bb87-80ad531ab494' ]::uuid[] );(Tenga en cuenta los corchetes en lugar de paréntesis)