我有这个功能
/*
@Function: valiDates [Avoid inserting data from invalid dates]
@Purpose: Providing a _TABLE and a date _COLUMN to be validated.
Given a _DATE (from script name) validate that a certain % of data (_TOLERANCE) belongs to the _INTERVAL of days specified.
*/
CREATE OR REPLACE FUNCTION valiDates(_date date, _table regclass, _column text, _interval integer, _tolerance real) RETURNS BOOLEAN AS
$$
DECLARE result boolean;
BEGIN
EXECUTE 'SELECT
(SELECT count(*) FROM ' || _table::regclass || '
WHERE ' || _column || ' BETWEEN '''|| _date || '''::date and ''' || _date || '''::date + INTERVAL ''' || _interval || 'days'')'
|| '/
(SELECT COUNT(*) FROM ' || _table::regclass || ')::real
> ' || _tolerance
INTO result;
RETURN result;
END
;
$$ LANGUAGE plpgsql;
它实际上适用于我的PostgreSQL环境版本9.1.13,但是当我尝试在Dev Server(PostgreSQL 8.2)上调用此函数时,会出现以下错误:
array value must start with "{" or dimension information
它应该在官方documentation page中描述的8.2上工作。
这就是我调用函数的方式:
select valiDates('2015-03-01','_table','_date',1,0.8);
我真的不知道如何修复它,我已经尝试用'_table'::regclass
调用该函数但它也不起作用。
答案 0 :(得分:0)
您的错误消息很可能来自 作为参数名称。 _date
_date
是date[]
的别名 - 日期数组的类型名称。类似于_interval
。
非常古老的版本的Postgres可能会误解第一个单词_date
作为数据类型而不是参数名称。使用合理的参数名称来解决此问题。使用基本类型名称作为任何类型的标识符永远是一个好主意。
您的功能已经过审核,应在Postgres 8.2中工作(未经测试):
CREATE OR REPLACE FUNCTION validates(_day date, _table regclass, _column text
, _days integer, _tolerance real)
RETURNS BOOLEAN AS
$func$
DECLARE result boolean;
BEGIN
EXECUTE 'SELECT
(SELECT count(*) FROM ' || _table || '
WHERE ' || quote_ident(_column) || ' BETWEEN '''
|| _day || '''::date and '''
|| _day || '''::date + ' || _days
|| ') >
(SELECT COUNT(*) FROM ' || _table || ') * ' || _tolerance
INTO result;
RETURN result;
END
$func$ LANGUAGE plpgsql;
按照讨论的方式修复参数名称。
这是胡说八道:_table::regclass
- _table
已经是[{1}}类型
另一方面,这是自杀:regclass
。 SQL注入广泛开放。请改用_column
。
您只需添加quote_ident(_column)
即可添加天数。更简单。
date + integer
可以重写为3 / 2 > 1.5
。更短,更清洁,更清晰,避免舍入错误,无需演员。
在Postgres 9.1+中,这可能是:
3 > 2 * 1.5
甚至在Postgres 9.4+中使用新的聚合CREATE OR REPLACE FUNCTION validates(_day date, _tbl regclass, _col text
, _days int, _tolerance real
, OUT result boolean) AS
$func$
BEGIN
EXECUTE format(
'SELECT count((%I BETWEEN $1 AND $2) OR NULL) > count(*) * $3 FROM %s'
, _col, _tbl
)
USING _day, _day + _days, _tolerance
INTO result;
END
$func$ LANGUAGE plpgsql;
子句更清洁:
FILTER
说明:
答案 1 :(得分:0)
感谢Erwin的建议,我把大部分内容都拿走了。最后我意识到由于_table参数(regclass类型)我只需要更改它或字符串(文本),它期待一个数组。