Reputation: 703
I am working on a Postgres 8.3 database and was trying to use PL/pgSQL to create function that generates a table name based on dates input to the table:
I have to create a series of tables that are indexed by dates for example:
drop table one_day_11_13 cascade;
create table one_day_11_13 as
select * from master_table where
timestamp < '2012-11-14' and timestamp >= '2012-11-13';
drop table one_day_11_14 cascade;
create table one_day_11_14 as
select * from master_table where
timestamp < '2012-11-15' and timestamp >= '2012-11-14';
I was thinking the way to do this would be to create a PL/pgSQL function that took as arguments ('11_13', '2012-11-14', '2012-11-13')
for example to create the first table above. I am having trouble coding up the appropriate EXECUTE statements.
What is the best way to do this kind of thing is PL/pgSQL overkill?
Upvotes: 1
Views: 300
Reputation: 656714
First, consider upgrading to a more recent version. 8.3 is on its way out.
For 8.3 it could work like this:
CREATE OR REPLACE FUNCTION f_recreate_tbl(date, date)
RETURNS void AS
$func$
DECLARE
-- derive tablename from first date
_tbl text := 'one_day_' || to_char($1, 'MM_YY');
BEGIN
-- Use IF EXISTS to avoid an exception when table does not exist.
EXECUTE
'DROP TABLE IF EXISTS ' || _tbl || ' CASCADE';
EXECUTE
'CREATE TABLE ' || _tbl || ' AS
SELECT *
FROM master_table
WHERE timestamp >= ''' || $1::text || '''::date
AND timestamp < ''' || $2::text || '''::date';
END
$func$ LANGUAGE plpgsql;
Call:
SELECT f_recreate_tbl('2012-11-13'::date, '2012-11-14'::date);
Whenever you want to parameterize identifiers, you can't use pure SQL. Use EXECUTE
dynamic SQL in a PL/pgSQL function or DO
statement (version 9.0+).
This version is safe enough. With more flexible input you would have to sanitize identifiers and values with quote_ident()
and quote_literal()
to prevent possible SQL injection.
In modern versions (since 8.4) you would use the USING
clause to skip casting parameters to text.
Don't use timestamp
as column name. It's the name of a data type.
Use DROP TABLE
IF EXISTS
. Already available in 8.3.
I derive the table name from the date and skip the third parameter. Seemed like a simplification.
Upvotes: 4