PostgreSQL 9.3:缺少 table 的 FROM 子句条目

PostgreSQL 9.3: missing FROM-clause entry for table

我有一个包含两列的 table。

示例:

create table t1
( 
  cola varchar,
  colb varchar
);

现在我想从函数中插入行。

在函数中:我想使用两个 varchar 类型的参数将值插入到上面的 table 中。我正在传递要插入 table 的字符串。

我将两个字符串作为参数传递给函数:

参数:

cola varchar = 'a,b,c,d';
colb varchar = 'e,f,g,h';

以上参数必须像这样插入到table中:

cola       colb
----------------
a           e
b           f
c           g
d           h

我的尝试:

create or replace function fun_t1(cola varchar,colb varchar)
returns void as
$body$
Declare
    v_Count integer;
    v_i integer = 0;
    v_f1 text;
    v_cola varchar;
    v_colb varchar;
    v_query varchar;

Begin

    drop table if exists temp_table;

    create temp table temp_table
    (
        cola varchar,
        colb varchar
    );

    v_Count :=  length(cola) - length(replace(cola, ',', ''));

    raise info '%',v_Count;

    WHILE(v_i<=v_Count) LOOP

        INSERT INTO temp_table
        SELECT  LEFT(cola,CHARINDEX(',',cola||',',0)-1) 
        ,LEFT(colb,CHARINDEX(',',colb||',',0)-1);

        cola := overlay(cola placing '' from 1 for CHARINDEX(',',cola,0));

        colb := overlay(colb placing '' from 1 for CHARINDEX(',',colb,0));

        v_i := v_i + 1;

    END LOOP;

    for v_f1 IN select * from temp_table loop

        v_cola := v_f1.cola;  /* Error occurred here */
        v_colb := v_f1.colb;  

        v_query := 'INSERT INTO t1 values('''||v_cola||''','''||v_colb||''')';

        execute v_query;

    end loop;

end;

$body$

language plpgsql;   

注意:在函数中我使用了temp_table是根据要求 我在这里没有显示的功能中也用于其他用途。

调用函数:

SELECT fun_t1('a,b,c','d,e,f');     

出现错误:

missing FROM-clause entry for table "v_f1"

使用 split_part() 尝试这种方式:-

create or replace function ins_t1(vala varchar,valb varchar,row_cnt int) returns void as 
$$
BEGIN 
FOR i IN 1..row_cnt LOOP -- row_cnt is the number rows you need to insert (ex. 4 or 5 or whatever it is)
insert into t1 (cola,colb) 
values (
        (select split_part(vala,',',i))
       ,(select split_part(valb,',',i))
       );
END LOOP;
END;
$$
language plpgsql

函数调用:select ins_t1('a,b,c,d','e,f,g,h',4)


正如 mike-sherrill-cat-recall 在他的回答中使用 regexp_split_to_table

所说
create or replace function fn_t1(vala varchar,valb varchar) returns void
as
$$
insert into t1 (cola, colb)
select col1, col2 from (select 
    trim(regexp_split_to_table(vala, ','))  col1,   
    trim(regexp_split_to_table(valb, ','))  col2)t;
$$
language sql 

函数调用:select fn_t1('a,b,c,d','e,f,g,h')

如果没有令人信服的理由为此使用函数,您可以使用正则表达式拆分文本。在这里,我将您的论点表达为常见的 table 表达式,但这只是为了方便。

with data (col1, col2) as (
  select 'a, b, c, d'::text, 'e, f, g, h'::text
)
select 
    trim(regexp_split_to_table(col1, ',')) as col_a,   
    trim(regexp_split_to_table(col2, ',')) as col_b
from data;
col_a  col_b
--
a      e
b      f
c      g
d      h

如果 是使用函数的一个令人信服的理由,只需将函数定义包裹在 SELECT 语句周围即可。

create function strings_to_table(varchar, varchar) 
returns table (col_a varchar, col_b varchar)
as 
    'select trim(regexp_split_to_table(, '','')),
            trim(regexp_split_to_table(, '',''));'
language sql
stable
returns null on null input;

select * from strings_to_table('a,b,c,d', 'e,f, g, h');
col_a  col_b
--
a      e
b      f
c      g
d      h

我个人的偏好是通常构建这样的函数到return table而不是插入到 table 秒。要插入,我通常会这样写 SQL 语句。

insert into foo (col_a, col_b)
select col_a, col_b from strings_to_table('a,b,c,d', 'e,f,g,h');

最简单的方法是为此使用 pl python。

create or replace function fill_t1(cola varchar, colb varchar) returns void as $$
for r in zip(cola.split(','), colb.split(',')):
  plpy.execute(plpy.prepare('insert into t1(cola, colb) values (, )', ['varchar', 'varchar']), [r[0], r[1]])
$$ language plpythonu;

结果:

# create table t1 (cola varchar, colb varchar);
CREATE TABLE
# select fill_t1('1,2,3', '4,5,6');
 fill_t1 
---------

(1 row)

# select * from t1;
 cola | colb 
------+------
 1    | 4
 2    | 5
 3    | 6
(3 rows)

您可以在此处阅读有关 Python zip 函数的信息:https://docs.python.org/2/library/functions.html#zip