I am migrating database from SQL Server to Postgresql and I am currently stuck at converting this query. I have referred to the documentation but I don't seem to find any solution.
Here is the query (undeclared @variables are .NET variables):
declare @table_name as varchar(64)
set @table_name = (select tbl_name from tbl1 where id = @id)
if @table_name = 'xyz'
begin
exec('select col1, col2, col3, col4 from '+@table_name+' where condition1='+@vbl1+' and condition2='+@vbl2+' and condition3=''abc'' and condition4='''+@vbl4+'''
union all
select col1, col2, col3, col4 from '+@table_name+' where condition1='+@vbl1+' and isnull(col3,''0'')=''0'' and condition3=''abc'' and condition4='''+@vbl4+'''
')
end
else
begin
exec('select col1, col2, col3, col4 from '+@table_name+' where condition1='+@vbl1+' and condition2='+@vbl2+' and condition3=''abc''
union all
select col1, col2, col3, col4 from '+@table_name+' where condition1='+@vbl1+' and isnull(col3,''0'')=''0'' and condition3=''abc''
')
end
I tried to convert this and here is what I could do:
create function ufn_function1(V_tbl_name anyelement, V_id integer, vbl1 integer, vbl2 integer, vbl4 integer) returns setof anyelement as $$
declare
V_table_name varchar:=(select V_tbl_name from tbl1 where id=V_id);
begin
if V_table_name= 'xyz'
then
return query execute format('
select col1, col2, col3, col4 from '||V_table_name||' where condition1='||vbl1||' and condition2='||vbl2||' and condition3=''abc'' and condition4='''||vbl4||'''
union all
select col1, col2, col3, col4 from '||V_table_name||' where condition1='||vbl1||' and isnull(col3,''0'')=''0'' and condition3=''abc'' and condition4='''||vbl4||'''
');
else
return query execute format('
select col1, col2, col3, col4 from '||V_table_name||' where condition1='||vbl1||' and condition2='||vbl2||' and condition3=''abc''
union all
select col1, col2, col3, col4 from '||V_table_name||' where condition1='||vbl1||' and isnull(col3,''0'')=''0'' and condition3=''abc''
');
end if;
end;
$$ language 'plpgsql';
Obviously this is not the correct conversion and has multiple syntax errors as I am completely alien to Postgresql.
Any help in converting this query is highly appreciated.
You really need to rethink your approach.
Generally, plain SQL does not allow interpolation / parameterization for identifiers (table or columns names etc.). You need to concatenate the query string, and then execute it. In PL/pgSQL, you can do this kind of "dynamic SQL" with
EXECUTE. The functionformat()is instrumental in concatenating the string safely.But the return type of a function cannot be completely dynamic. There are limited workarounds. Like returning anonymous records (which I don't find very useful). Or a polymorphic functions. See:
But that requires you to pass the return type with the call, which is not possible with your workflow, where you only pass an ID to fetch a table name. Plus, your original code seems inefficient and open to SQL injecton. However, your return type looks constant after all. If so, this could work:
There are subtle details to this. Too much for a single question.
Start by learning PL/pgSQL.
Related: