EXECUTE 的查询字符串参数为空
Query string argument of EXECUTE is null
编辑
我的问题似乎是当这个 select 语句 returns 为空时(我正在尝试处理这种情况 - 当它 returns 为空时,我想要我的新值为 -999)。如果发现 null 时出错,我该怎么办?
原版
我已经阅读了所有其他的 SO post 我能找到关于这个错误的信息,但是 none 似乎解决了我的问题的根源。
错误非常简单 - 我的 EXECUTE 语句中的参数之一为空。伟大的。但是,我在调用 EXECUTE 语句之前打印出了构成我的 EXECUTE 语句的每个值,我可以清楚地看到 none 个值是 null。
代码:
CREATE FUNCTION inform_icrm_prob_flow_query(tablename text, location_id int,
product_date_str text, lead_time_start int,
lead_time_end int, first_member_id int,
last_member_id int, dest_file text)
RETURNS void AS $$
DECLARE
count int;
product_date TIMESTAMPTZ;
interval_lead_time_start text;
interval_lead_time_end text;
curr_value double precision;
query text;
BEGIN
product_date := product_date_str::TIMESTAMPTZ;
count := first_member_id;
curr_value := 0;
interval_lead_time_start := ''''|| product_date ||'''::timestamptz +
interval '''||lead_time_start||' hours''';
interval_lead_time_end := ''''|| product_date ||'''::timestamptz +
interval '''||lead_time_end||' hours'' -
interval ''6 hours''';
--create our temporary table and populate it's date column
EXECUTE 'CREATE TEMPORARY TABLE temp_table_icrm_prob_flow AS
SELECT * FROM generate_series('||interval_lead_time_start || ',' ||
interval_lead_time_end || ', ''6 hours'')
AS date_valid';
LOOP
EXIT WHEN count > last_member_id;
IF NOT EXISTS(
SELECT 'date_valid'
FROM information_schema.columns
WHERE table_name='temp_table_icrm_prob_flow'
and column_name='value'||count||'')
THEN
EXECUTE 'ALTER TABLE temp_table_icrm_prob_flow ADD COLUMN value' || count
|| ' double precision DEFAULT -999';
END IF;
raise notice 'tablename: %', tablename;
raise notice 'location_id: %', location_id;
raise notice 'product_date: %', product_date;
raise notice 'count: %', count;
query := 'SELECT value FROM '|| tablename ||'
INNER JOIN temp_table_icrm_prob_flow
ON (temp_table_icrm_prob_flow.date_valid = '|| tablename ||'.date_valid)
WHERE '|| tablename ||'.id_location = '|| location_id ||'
AND '|| tablename ||'.date_product = '''|| product_date ||'''
AND '|| tablename ||'.id_member = '|| count ||'';
EXECUTE query INTO curr_value;
EXECUTE 'UPDATE temp_table_icrm_prob_flow
SET value'|| count ||' = COALESCE('|| curr_value ||', -999)';
count := count + 1;
END LOOP;
EXECUTE 'ALTER TABLE temp_table_icrm_prob_flow DROP COLUMN date_valid';
EXECUTE 'COPY temp_table_icrm_prob_flow TO '''||dest_file||''' DELIMITER '','' CSV';
EXECUTE 'DROP TABLE temp_table_icrm_prob_flow';
END;
$$ LANGUAGE plpgsql;
输出:
NOTICE: tablename: inform_tseries_data_basin_proc_fcst_prob_flow
NOTICE: location_id: 38
NOTICE: product_date: 2015-02-05 12:00:00+00
NOTICE: count: 1
ERROR: query string argument of EXECUTE is null
CONTEXT: PL/pgSQL function inform_icrm_prob_flow_query(text,integer,text,integer,integer,integer,integer,text) line 38 at EXECUTE
如果我传入的变量 none 为空,并且唯一引用的其他内容是我知道存在的临时 table,可能是什么导致了此错误?
注意:将我的查询更改为:
query := 'SELECT value FROM '|| tablename ||' WHERE '|| tablename ||'.id_location = '|| location_id ||' AND '|| tablename ||'.date_product = '''|| product_date ||''' AND '|| tablename ||'.id_member = '|| count ||' AND temp_table_icrm_prob_flow.date_va lid = '|| tablename ||'.date_valid';
我收到以下错误:
NOTICE: tablename: inform_tseries_data_basin_proc_fcst_prob_flow
NOTICE: location_id: 38
NOTICE: product_date: 2015-02-05 12:00:00+00
NOTICE: count: 1
ERROR: missing FROM-clause entry for table "temp_table_icrm_prob_flow"
LINE 1: ..._data_basin_proc_fcst_prob_flow.id_member = 1 AND temp_table...
^
QUERY: SELECT value FROM inform_tseries_data_basin_proc_fcst_prob_flow WHERE inform_tseries_data_basin_proc_fcst_prob_flow.id_location = 38 AND inform_tseries_data_basin_proc_fcst_prob_flow.date_product = '2015-02-05 12:00:00+00' AND inform_tseries_data_basin_proc_fcst_prob_flow.id_member = 1 AND temp_table_icrm_prob_flow.date_valid = inform_tseries_data_basin_proc_fcst_prob_flow.date_valid
CONTEXT: PL/pgSQL function inform_icrm_prob_flow_query(text,integer,text,integer,integer,integer,integer,text) line 35 at EXECUTE
对不起,小题外话。您的代码很难读(并且 SQL 注入漏洞)。您可以使用一些技巧:
使用 EXECUTE
语句的子句 USING
作为常用参数。
DO $$
DECLARE
tablename text := 'mytab';
from_date date := CURRENT_DATE;
BEGIN
EXECUTE 'INSERT INTO ' || quote_ident(tablename) || ' VALUES()'
USING from_date;
END
$$;
此代码将是安全的(由于使用 quote_ident
函数),速度稍快(由于使用 from_date 变量的二进制值 - 删除了多个字符串<->日期转换和可读性更高(因为字符串表达式更短)。
使用函数format
。构建查询字符串将更短且更易读(table 别名也有帮助):
query := format('
SELECT value
FROM %I _dtn
INNER JOIN temp_table_icrm_prob_flow t ON t.date_valid = _dtn.date_valid
WHERE _dtn.id_location =
AND _dtn.date_product =
AND _dtd.id_member = '
, tablename);
EXECUTE query INTO curr_value USING location_id, product_date, count;
使用像重要 SQL 关键字和标识符这样命名的变量是错误的想法 - 名称 count、values 是错误的。
错误消息很清楚 - 您正在使用标识符 temp_table_icrm_prob_flow.date_valid
,但查询中未提及 table temp_table_icrm_prob_flow。查询缺少 JOIN 部分。
编辑
我的问题似乎是当这个 select 语句 returns 为空时(我正在尝试处理这种情况 - 当它 returns 为空时,我想要我的新值为 -999)。如果发现 null 时出错,我该怎么办?
原版
我已经阅读了所有其他的 SO post 我能找到关于这个错误的信息,但是 none 似乎解决了我的问题的根源。
错误非常简单 - 我的 EXECUTE 语句中的参数之一为空。伟大的。但是,我在调用 EXECUTE 语句之前打印出了构成我的 EXECUTE 语句的每个值,我可以清楚地看到 none 个值是 null。
代码:
CREATE FUNCTION inform_icrm_prob_flow_query(tablename text, location_id int,
product_date_str text, lead_time_start int,
lead_time_end int, first_member_id int,
last_member_id int, dest_file text)
RETURNS void AS $$
DECLARE
count int;
product_date TIMESTAMPTZ;
interval_lead_time_start text;
interval_lead_time_end text;
curr_value double precision;
query text;
BEGIN
product_date := product_date_str::TIMESTAMPTZ;
count := first_member_id;
curr_value := 0;
interval_lead_time_start := ''''|| product_date ||'''::timestamptz +
interval '''||lead_time_start||' hours''';
interval_lead_time_end := ''''|| product_date ||'''::timestamptz +
interval '''||lead_time_end||' hours'' -
interval ''6 hours''';
--create our temporary table and populate it's date column
EXECUTE 'CREATE TEMPORARY TABLE temp_table_icrm_prob_flow AS
SELECT * FROM generate_series('||interval_lead_time_start || ',' ||
interval_lead_time_end || ', ''6 hours'')
AS date_valid';
LOOP
EXIT WHEN count > last_member_id;
IF NOT EXISTS(
SELECT 'date_valid'
FROM information_schema.columns
WHERE table_name='temp_table_icrm_prob_flow'
and column_name='value'||count||'')
THEN
EXECUTE 'ALTER TABLE temp_table_icrm_prob_flow ADD COLUMN value' || count
|| ' double precision DEFAULT -999';
END IF;
raise notice 'tablename: %', tablename;
raise notice 'location_id: %', location_id;
raise notice 'product_date: %', product_date;
raise notice 'count: %', count;
query := 'SELECT value FROM '|| tablename ||'
INNER JOIN temp_table_icrm_prob_flow
ON (temp_table_icrm_prob_flow.date_valid = '|| tablename ||'.date_valid)
WHERE '|| tablename ||'.id_location = '|| location_id ||'
AND '|| tablename ||'.date_product = '''|| product_date ||'''
AND '|| tablename ||'.id_member = '|| count ||'';
EXECUTE query INTO curr_value;
EXECUTE 'UPDATE temp_table_icrm_prob_flow
SET value'|| count ||' = COALESCE('|| curr_value ||', -999)';
count := count + 1;
END LOOP;
EXECUTE 'ALTER TABLE temp_table_icrm_prob_flow DROP COLUMN date_valid';
EXECUTE 'COPY temp_table_icrm_prob_flow TO '''||dest_file||''' DELIMITER '','' CSV';
EXECUTE 'DROP TABLE temp_table_icrm_prob_flow';
END;
$$ LANGUAGE plpgsql;
输出:
NOTICE: tablename: inform_tseries_data_basin_proc_fcst_prob_flow
NOTICE: location_id: 38
NOTICE: product_date: 2015-02-05 12:00:00+00
NOTICE: count: 1
ERROR: query string argument of EXECUTE is null
CONTEXT: PL/pgSQL function inform_icrm_prob_flow_query(text,integer,text,integer,integer,integer,integer,text) line 38 at EXECUTE
如果我传入的变量 none 为空,并且唯一引用的其他内容是我知道存在的临时 table,可能是什么导致了此错误?
注意:将我的查询更改为:
query := 'SELECT value FROM '|| tablename ||' WHERE '|| tablename ||'.id_location = '|| location_id ||' AND '|| tablename ||'.date_product = '''|| product_date ||''' AND '|| tablename ||'.id_member = '|| count ||' AND temp_table_icrm_prob_flow.date_va lid = '|| tablename ||'.date_valid';
我收到以下错误:
NOTICE: tablename: inform_tseries_data_basin_proc_fcst_prob_flow
NOTICE: location_id: 38
NOTICE: product_date: 2015-02-05 12:00:00+00
NOTICE: count: 1
ERROR: missing FROM-clause entry for table "temp_table_icrm_prob_flow"
LINE 1: ..._data_basin_proc_fcst_prob_flow.id_member = 1 AND temp_table...
^
QUERY: SELECT value FROM inform_tseries_data_basin_proc_fcst_prob_flow WHERE inform_tseries_data_basin_proc_fcst_prob_flow.id_location = 38 AND inform_tseries_data_basin_proc_fcst_prob_flow.date_product = '2015-02-05 12:00:00+00' AND inform_tseries_data_basin_proc_fcst_prob_flow.id_member = 1 AND temp_table_icrm_prob_flow.date_valid = inform_tseries_data_basin_proc_fcst_prob_flow.date_valid
CONTEXT: PL/pgSQL function inform_icrm_prob_flow_query(text,integer,text,integer,integer,integer,integer,text) line 35 at EXECUTE
对不起,小题外话。您的代码很难读(并且 SQL 注入漏洞)。您可以使用一些技巧:
使用
EXECUTE
语句的子句USING
作为常用参数。DO $$ DECLARE tablename text := 'mytab'; from_date date := CURRENT_DATE; BEGIN EXECUTE 'INSERT INTO ' || quote_ident(tablename) || ' VALUES()' USING from_date; END $$;
此代码将是安全的(由于使用
quote_ident
函数),速度稍快(由于使用 from_date 变量的二进制值 - 删除了多个字符串<->日期转换和可读性更高(因为字符串表达式更短)。使用函数
format
。构建查询字符串将更短且更易读(table 别名也有帮助):query := format(' SELECT value FROM %I _dtn INNER JOIN temp_table_icrm_prob_flow t ON t.date_valid = _dtn.date_valid WHERE _dtn.id_location = AND _dtn.date_product = AND _dtd.id_member = ' , tablename); EXECUTE query INTO curr_value USING location_id, product_date, count;
使用像重要 SQL 关键字和标识符这样命名的变量是错误的想法 - 名称 count、values 是错误的。
错误消息很清楚 - 您正在使用标识符 temp_table_icrm_prob_flow.date_valid
,但查询中未提及 table temp_table_icrm_prob_flow。查询缺少 JOIN 部分。