【发布时间】:2012-02-27 23:21:21
【问题描述】:
客户希望将任何内容存储在单独的表中。 (长话短说,这是必要的)。 为此,我构建了一个 Postgres 函数以在其自己的命名空间中动态创建新表。
这些表可以有 2、4 或 100 列,这正是用户想要的。 没问题,这行得通。这些动态表中使用的数据类型是本机的,例如文本、布尔值、整数等。
现在问题来了,我必须在这些表中插入数据。关键是,用户不能直接访问表,他们将通过一个函数来做到这一点。
对于几个数据类型这不是问题,但对于文本数据类型它是有问题的。
到目前为止的功能如下:
-- Function: add(integer, text[])
-- DROP FUNCTION add(integer, text[]);
CREATE OR REPLACE FUNCTION add(id integer, fields text[])
RETURNS integer AS
$BODY$
DECLARE
l_line_ending text := ')';
l_fieldtype integer;
l_ito_table_name text;
l_ito_fieldnames text;
l_field ito_fields%rowtype;
l_first_loop boolean := true;
l_values_to_insert text := 'VALUES (';
l_loop_counter integer := 0;
l_query text;
BEGIN
select into l_ito_table_name ito_table_name from ito where id = target_ito_id;
l_ito_fieldnames := 'insert into ' || l_ito_table_name || '(';
FOR l_field IN SELECT * FROM ito_fields
WHERE ito_fields.ito_id = target_ito_id
order by ito_fields.id asc
LOOP
l_loop_counter := l_loop_counter +1;
l_fieldtype := l_field.fieldtype;
if not l_first_loop THEN
l_values_to_insert := (l_values_to_insert || ', ');
end if;
if l_field.fieldtype = 1 THEN
l_values_to_insert := (l_values_to_insert || '''' || (fields[l_loop_counter]) || '''' );
elsif l_field.fieldtype = 2 THEN
l_values_to_insert := quote_literal(l_values_to_insert || private.cast_to_integer(fields[l_loop_counter]));
elsif l_field.fieldtype = 3 THEN
l_values_to_insert := quote_literal(l_values_to_insert || private.cast_to_boolean(fields[l_loop_counter]));
elsif l_field.fieldtype = 4 THEN
l_values_to_insert := quote_literal(l_values_to_insert || private.cast_to_float(fields[l_loop_counter]));
else
return 103;
end if;
if l_first_loop then
l_ito_fieldnames := l_ito_fieldnames || l_field.column_name;
l_first_loop := false;
else
l_ito_fieldnames := l_ito_fieldnames || ', ' || l_field.column_name;
end if;
END LOOP;
l_ito_fieldnames := l_ito_fieldnames || l_line_ending;
l_values_to_insert := ((l_values_to_insert) || (l_line_ending));
l_query := (l_ito_fieldnames || l_values_to_insert);
EXECUTE l_query;
return 0;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION add(integer, text[])
OWNER TO postgres;
表 ito_fields 存储所有字段元数据,因此数据类型、版本、描述都存储在这里。 ito表存储所有动态表数据。
这个函数的重点是引号。插入函数是动态创建的,因此我必须在插入函数的文本字段周围添加一些引号。 一旦我这样做,Postgres 就会给出错误。即使使用 quote_literal 函数,它仍然是一个问题,因为字符串连接(我知道,安全风险,但现在没问题)。
我试过用quote_literal,quote_ident,甚至用替换替换引号('),直到执行函数(replace(query,l_quote_rep,'''')..我真的不知道现在如何解决这个问题...
提前致谢。
【问题讨论】:
标签: arrays postgresql dynamic insert plpgsql