Thanks goes to a_horse_with_no_name. Solution is:
update answers set answer_value = lo_get(cast(value as bigint))
Note - the lo_get
function appears to be present in Postgres 9.4 or higher. For earlier versions, I don't see a way of doing this directly. I'm currently running 9.0, but this just accelerated my upgrade plans.
There is no way that saves you from specifying all JSON attributes in the select list, whether implicitly through the "dummy type" or explicitly, e.g. using something like this:
select json_column ->> 'text1' as text1,
json_column ->> 'text2' as text2,
...
from the_table;
What you can do, is to make this simpler by automatically creating a view with all attributes based on the distinct attributes in the JSON documents.
The following code will re-create a view with all distinct keys from the JSON column:
do
$$
declare
l_keys text;
begin
drop view if exists v_json_view cascade;
select string_agg(distinct format('json_column ->> %L as %I',jkey, jkey), ', ')
into l_keys
from the_table, json_object_keys(json_column) as t(jkey);
execute 'create view v_json_view as select '||l_keys||' from the_table';
end;
$$
;
You will need to run the above every time the list of keys in all json documents changes. Theoretically this could be done in a trigger but that's probably not a good idea if you run many updates on that table.
If the total number of JSON keys is somewhat "stable", you could schedule a cron job to re-create that view in regular intervals.
You are also limited by the maximum number of columns in a table or view. If you have more (distinct) keys than approx. 1600 (maybe less) the above will fail.
Best Answer
There is no way to do this, since a type name is always an identifier, and only constants (literals) can be parameters.
The only resort is to use dynamic SQL like