sql:使用动态列和值更新动态表

时间:2017-08-21 13:08:30

标签: sql postgresql

目标:我想创建一个可以更新表的函数,条件(在哪里)是动态的。如下:

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;

- cource,它无法通过!   - 问题:   - 如何设置列的值?   - 因为表是动态的,所以列的类型是未知的!

2 个答案:

答案 0 :(得分:0)

我更改了功能:

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;

经过一些测试: 我传递的参数如下: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}]'

我得到的sql字符串为: 更新测试集名称='ssqhan',薪水='5200.00',其中1 = 1且id ='1'

然而,这不是我的意思:id int name text,salay number! sql应该是这样的:update test set name ='ssqhan',salary = 5200.00,其中1 = 1,id = 1,这就是我想要的。

答案 1 :(得分:0)

我得到了另一个代码:

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;

当我传递参数时: '测试' '[{ “feild_name”: “姓名”, “feild_value”: “ssqhan”},{ “feild_name”: “工资”, “feild_value”:5200.00}]' '[{ “feild_name”: “ID”, “feild_value”:2}]'

返回sql之类: 更新测试集名称='ssqhan',薪水= 5200.00,其中1 = 1且id = 2

是的,这就是我想要的,当数据类型是文本或数字时,这可能有用, 但是如果数据类型是合成的吗?