问题
I have a rather complicated function in postgresql (Version 9.4.4) that I need a bit of help with.
I have a loop (with lots of work below) declared like this inside of my function:
CREATE OR REPLACE function getRSI(
psymbol varchar,
pstarttime timestamp with time zone,
pendtime timestamp with time zone,
pduration double precision,
ptable varchar
)
RETURNS SETOF rsi AS
$BODY$
declare
row_data record;
-- some variables
begin
FOR row_data IN SELECT datetime, value FROM "4" WHERE symbol = 'AAPL'
AND datetime BETWEEN '2015-11-23 09:30:00 -0500' AND
'2015-11-23 15:59:59-0500' LOOP
-- enter code here
END LOOP;
end
$BODY$ LANGUAGE plpgsql
This works perfectly, I can get the result of my function and have it crunch all the numbers for me.
I would like to get the loop to work like this:
FOR row_data in select datetime, value from quote_ident(ptable)
where symbol = quote_literal(psymbol) and datetime
between quote_literal(pstarttime) AND quote_literal(pendtime) LOOP
where ptable
, psymbol
, pstarttime
and pendtime
are variables passed from the function call.
But I would be happy having to hardcode a table and getting the other three things to be based on a variable:
FOR row_data in select datetime, value from "4" where symbol =
quote_literal(psymbol) and datetime between quote_literal(pstarttime)
AND quote_literal(pendtime) LOOP
Yes, I know that I have a table named after a number, nothing I can do about it in my current setup.
When I try to call the function with either of the above setups, I just get a blank. Any help would be appreciated. I can't find any documentation about using a variable in a for loop so it might not be possible.
回答1:
You need dynamic SQL with EXECUTE
- but only to parameterize the table name (or other identifiers) - not necessary to parameterize values.
And do not concatenate parameter values into the query. That's more expensive and error prone than necessary. Use the USING clause of EXECUTE instead.
FOR row_data IN
EXECUTE '
SELECT datetime, value FROM ' || quote_ident(ptable) || '
WHERE symbol = $1
AND datetime between $2 AND $3'
USING psymbol, pstarttime, pendtime
LOOP
-- do stuff
END LOOP;
Or use format():
EXECUTE format('
SELECT datetime, value FROM %I
WHERE symbol = $1
AND datetime between $2 AND $3', ptable)
USING psymbol, pstarttime, pendtime
Related:
- The manual on record types
- Table name as a PostgreSQL function parameter
- plpgsql - using dynamic table name in declare statement
回答2:
change your for loop like this
FOR row_data in execute 'select datetime, value from "4" where symbol =' ||
quote_literal(psymbol) || 'and datetime between' || quote_literal(pstarttime)
|| 'AND ' || quote_literal(pendtime) LOOP
来源:https://stackoverflow.com/questions/34526233/how-do-i-use-variables-in-a-postgresql-function-for-loop-query