简体   繁体   中英

sql: update dynamic table with dynamic columns and values

target: i wanna create a function which can update table,and the condition(in where) is dynamic .as following:

create or replace function f_update(
    tablename          text,      --the table name updated
    update_fields      text,      --fields and values as json 
                                  --[{"fieldName":"id","fieldValue":1},
                                  --{"fieldName":"name","fieldValue":"admin"},
                                  --{"fieldName":"salary,"fieldValue":6000.00}]
    condition_fields   text,      --condition: json like above
    out return_value   text       --return value
) as $$
declare
    ex_sql             text;
    recs               record;
begin
    ex_sql:='update '||quote_ident(tablename)||' set ';
    --set values to the column
    for recs in select * from json_to_recordset(update_fields::json) as x( field_name text,field_value text) loop
        if json_typeof(recs.field_value) ='numeric' then 
            ex_sql:=ex_sql|| recs.field_name || '=' ||  recs.field_value ||',';
        else 
            ex_sql:=ex_sql|| recs.field_name || '='''|| recs.field_value || ''',';
        end if;
    end loop;
    ex_sql:= substring(ex_sql from 0 for length(ex_sql)-1);

    --setting conditions 
    ex_sql:=ex_sql||' where 1=1';
    for recs in select * from json_to_recordset(condition_fields::json) as x( field_name text,field_value text) loop
        if json_typeof(recs.field_value) ='numeric' then 
            ex_sql:=ex_sql|| ' and ' || recs.field_name || '=' ||  recs.field_value ||',';
        else 
            ex_sql:=ex_sql|| ' and ' || recs.field_name || '='''|| recs.field_value || ''',';
        end if;
    end loop;
    ex_sql:= substring(ex_sql from 0 for length(ex_sql)-1);
    return_value:=ex_sql;
end;
$$ language plpgsql;

--of cource ,it cannot pass! --the question: --how to set value to the columns? --because the table is dynamic,so the type of the column is unknown!

i changed the function:

create or replace function f_update(
    tablename          text,          
    update_feilds      text,          
    condition_feilds   text,       
    out return_value   text        
) as $$
declare
    ex_sql             text;
    recs               record;
begin
    ex_sql:='update '||quote_ident(tablename)||' set ';
    for recs in select * from json_to_recordset(update_feilds::json) as x( feild_name text,feild_value text) loop
        if json_typeof(to_json(recs.feild_value)) ='number' then 
            ex_sql:=ex_sql|| recs.feild_name || '=' ||  recs.feild_value ||',';
        else 
            ex_sql:=ex_sql|| recs.feild_name || '='''|| recs.feild_value || ''',';
        end if;
    end loop;
    ex_sql:= substring(ex_sql from 0 for length(ex_sql));


    ex_sql:=ex_sql||' where 1=1';
    for recs in select * from json_to_recordset(condition_feilds::json) as x( feild_name text,feild_value text) loop
        if json_typeof(to_json(recs.feild_value)) ='number' then 
            ex_sql:=ex_sql|| ' and ' || recs.feild_name || '=' ||  recs.feild_value ||',';
        else 
            ex_sql:=ex_sql|| ' and ' || recs.feild_name || '='''|| recs.feild_value || ''',';
        end if;
    end loop;
    ex_sql:= substring(ex_sql from 0 for length(ex_sql));
    return_value:=ex_sql;
end;
$$ language plpgsql;

after some testing: i pass the parameters like : tableName:'test' update_feilds '[{"field_name":"name","field_value":"ssqhan"},{"field_name":"salary","field_value":5200.00}]' condition_feilds '[{"field_name":"id,"field_value":1}]'

and i got the sql string as: update test set name='ssqhan',salary='5200.00' where 1=1 and id='1'

however,this is not what i mean: id int name text, salay number! sql should be like: update test set name='ssqhan',salary=5200.00 where 1=1 and id=1, that's what i want.

i got another code like that:

create or replace function f_update_all(
    tablename          text,      
    update_feilds      text,       
    condition_feilds   text,       
    out return_value   text        
) as $$
declare
    ex_sql             text;
    recs               record;
    _key               text ;
    _value             text;
begin
    ex_sql:='update '||quote_ident(tablename)||' set ';
    --setting values for updated table
    for recs in select * from json_array_elements(update_feilds::json)   loop
        _key   := recs.value ->> 'feild_name';
        _value := recs.value ->> 'feild_value' ;


        if json_typeof(recs.value -> 'feild_value') ='number' then 
            ex_sql:=ex_sql|| _key || '=' ||  _value ||',';
        else 
            ex_sql:=ex_sql|| _key || '='''||  (recs.value ->> 'feild_value')  || ''',';
        end if;


    end loop;
    ex_sql:= substring(ex_sql from 0 for length(ex_sql));

    --setting condition in where 
     ex_sql:=ex_sql||' where 1=1';
    for recs in select * from  json_array_elements(condition_feilds::json)  loop
        _key   := recs.value ->> 'feild_name';
        _value := recs.value ->> 'feild_value' ;

         if json_typeof(recs.value -> 'feild_value') ='number' then 
            ex_sql:=ex_sql|| ' and ' || _key || '=' ||  _value ||',';
        else 
            ex_sql:=ex_sql|| ' and ' || _key || '='''||  (recs.value ->> 'feild_value') || ''',';
        end if;
    end loop;
    ex_sql:= substring(ex_sql from 0 for length(ex_sql));
    return_value:=ex_sql;
end;
$$ language plpgsql;

when i pass the parameters as : 'test' ,'[{"feild_name":"name","feild_value":"ssqhan"},{"feild_name":"salary","feild_value":5200.00}]' ,'[{"feild_name":"id","feild_value":2}]'

the return sql like: update test set name='ssqhan',salary=5200.00 where 1=1 and id=2

Yeah,this what i want ,this may work when the datatype is text or number, but if the data type is composited?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM