从 plpgsql 中的文本动态转换

bel*_*daz 6 postgresql dynamic-sql plpgsql

我的数据库中的许多表共享一个公共布局,特别是它们有一个serial以关系名称命名的主键。从 Web 应用程序中更新这些表通常涉及以下形式的查询:

UPDATE table SET attribute = x WHERE table_id = y
Run Code Online (Sandbox Code Playgroud)

这很常见,以至于我有一个执行此任务的存储过程:

CREATE OR REPLACE FUNCTION setvalue(
    relname text,
    row_id integer,
    colname text,
    newvalue text)
RETURNS void AS
$BODY$
BEGIN
  EXECUTE format('UPDATE %I SET %I = $1 WHERE %I = $2', relname, colname, relname || '_id', colname) USING row_id;
END;
$BODY$
LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不适用于非文本类型。例如,更新一date列给出ERROR: column ... is of type date but expression is of type text. 假设文本是预期类型的​​有效文字表示,是否有一种安全的方法让 DBMS 找出正确的类型并做正确的事情?

bel*_*daz 4

到目前为止,我自己的解决方案是将字符串文字粘贴到查询中:

EXECUTE format(
  'UPDATE %I SET %I = ' || quote_literal(newvalue) || ' WHERE %I = $1 ',
  relname, colname, relname || '_id') USING row_id;
Run Code Online (Sandbox Code Playgroud)

要不就

EXECUTE format(
  'UPDATE %I SET %I = %L WHERE %I = $1', 
  relname, colname, newvalue, relname || '_id') USING row_id;
Run Code Online (Sandbox Code Playgroud)

例如,这适用于格式适当的日期类型 ( '1990-05-04')。这可能会牺牲重用查询计划的能力。