如何从postgresql中的plpgsql函数返回的SELECT查询中提取字符串(或文本)?

时间:2012-11-06 09:16:31

标签: postgresql plpgsql psql

我可能在这里扭曲postgres,但从根本上说,我想做的是使用字符串变量并将其传递给sql命令(在本例中为COPY),仅使用psql。

所以这就是我想出来的。命令分为2个文件,因为我希望能够在其他情况下使用mydb_functions:

文件一:mydb_functions - 1.0.sql(在共享/扩展中,并且mydb_functions.control也按照手册中的描述进行设置。给定一个文件名,返回一个完整的文件路径。这只是为了在add_data中创建COPY语句.sql下面,neater。

CREATE OR REPLACE FUNCTION fpn(filename text) RETURNS TEXT as '
  DECLARE 
    mypath text := ''/path/to/my/directory/'';
  BEGIN
    RETURN mypath || filename;
  END
' LANGUAGE plpgsql;

文件二:add_data.sql。这仅用于在命令行使用psql将数据复制到现有的postgres表中。注意:由于CREATE EXTENSION命令,因此需要运行具有超级用户权限的psql。

CREATE EXTENSION IF NOT EXISTS mydb_functions;
-- haven't figured out how to create a function without arguments yet.
CREATE OR REPLACE FUNCTION test (dummyvar text) RETURNS text as '     
  DECLARE 
    filepath RECORD;
  BEGIN 
    SELECT * INTO filepath from fpn(''mydatafile.data'');
    COPY tablename (columnname) FROM filepath;
  END
' LANGUAGE plpgsql;

我坚持的部分是如何从文件路径记录中提取文本以在COPY命令中使用。任何有关实现这一目标的简单方法的提示也是受欢迎的。我认为创建一个表来存储变量要比这容易得多。但我想完成最后一步。

1 个答案:

答案 0 :(得分:0)

如果您的问题正在使用动态目标路径COPY运行,请使用EXECUTE运行format SQL查询。

CREATE OR REPLACE FUNCTION test () RETURNS text as $$ 
  DECLARE 
    filepath RECORD;
  BEGIN 
    SELECT * INTO filepath from fpn('mydatafile.data');
    EXECUTE format('COPY tablename (columnname) FROM %L', filepath);
  END
$$ LANGUAGE plpgsql;

看,这失败了:

DO
$$
DECLARE
    somevar text;
BEGIN
    somevar := '/tmp/somepath.csv';
    COPY tablename(columnname) FROM somevar;
END;
$$;

但这有效:

DO
$$
DECLARE
    somevar text;
BEGIN
    somevar := '/tmp/somepath.csv';
    EXECUTE format('COPY tablename(columnname) FROM %L', somevar);
END;
$$;

请参阅:

format()的{​​{1}}说明符会自动引用文字。 %L对标识符也是如此。


如果按照我原先的想法,您正在讨论从外部将数据导入%I,您可能会发现psql变量和变量插值很有用:

psql

请注意冒号未加引号,然后引用变量名称。奇怪的语法,我知道。这仅适用于$ psql -v filepath=/path/to/my/directory/mydatafile.data regress regress=> SELECT :'filepath'; ?column? --------------------------------------- /path/to/my/directory/mydatafile.data (1 row) ;它不适用于(例如)PgAdmin-III。

或者,你可以使用here-document(特定于unix的shell,在Windows psql中不起作用)来进行引用文本插值:

cmd.exe

这两个都展示了如何将shell级别的变量插入$ FILEPATH=/path/to/my/directory/mydatafile.data $ psql regress <<__END__ SELECT '$FILEPATH'; __END__ ?column? --------------------------------------- /path/to/my/directory/mydatafile.data (1 row) 。从那里开始,就是在你的功能中使用它。就像这样,用psql

-v filename=myfilename.csv

或仅使用CREATE OR REPLACE FUNCTION test() RETURNS text as $$ DECLARE filepath RECORD; BEGIN SELECT * INTO filepath from fpn(:'filename'); COPY tablename (columnname) FROM filepath; END $$ LANGUAGE plpgsql;

-v filepath=/full/path/to/myfilename.csv