245

我有一个名为:的数据库架构nyummy和一个名为cimory

create table nyummy.cimory (
  id numeric(10,0) not null,
  name character varying(60) not null,
  city character varying(50) not null,
  CONSTRAINT cimory_pkey PRIMARY KEY (id)
);

我想将cimory表的数据导出为插入 SQL 脚本文件。但是,我只想导出城市等于“东京”的记录/数据(假设城市数据都是小写的)。

怎么做?

解决方案是在免费软件 GUI 工具还是命令行中都没有关系(尽管 GUI 工具解决方案更好)。我曾尝试过 pgAdmin III,但找不到执行此操作的选项。

4

11 回答 11

359

使用要导出的集合创建一个表,然后使用命令行实用程序 pg_dump 导出到文件:

create table export_table as 
select id, name, city
from nyummy.cimory
where city = 'tokyo'
$ pg_dump --table=export_table --data-only --column-inserts my_database > data.sql

--column-inserts将作为带有列名的插入命令转储。

--data-only不要转储模式。

如下所述,在需要新导出时创建视图而不是表将避免创建表。

于 2012-10-10T09:31:59.707 回答
205

要仅导出数据,请使用COPY

COPY (SELECT * FROM nyummy.cimory WHERE city = 'tokio') TO '/path/to/file.csv';

您可以导出整个表、仅导出选定的列或查询的结果,如图所示。无需显式创建表。

你得到一个文件,每行一个表格行作为纯文本(不是INSERT命令)。INSERT比命令更小更快。

要将相同的内容导入到另一个匹配结构的 Postgres 表中(列顺序相同,数据类型兼容!):

COPY other_tbl FROM '/path/to/file.csv';

COPY写入和读取服务器本地的文件,不像客户端程序,如pg_dumppsql读取和写入客户端本地的文件。如果两者都在同一台机器上运行,那并不重要,但对于远程连接来说确实如此。

还有psql\copy的命令

执行前端(客户端)复制。这是一个运行 SQLCOPY命令的操作,但不是服务器读取或写入指定的文件,而是 psql 读取或写入文件并在服务器和本地文件系统之间路由数据。这意味着 文件可访问性和权限是本地用户的,而不是服务器的,并且不需要 SQL 超级用户权限

与上面的语法相同。只需替换COPY\copy.

于 2012-10-10T17:16:45.403 回答
46

这是一种使用 pgAdmin手动将表导出到脚本的简单快捷方式,无需额外安装

  1. 右键单击目标表并选择“备份”。
  2. 选择一个文件路径来存储备份。作为格式选择“普通”。
  3. 打开底部的“转储选项#2”选项卡并选中“使用列插入”。
  4. 单击备份按钮。
  5. 如果您使用文本阅读器(例如 notepad++)打开生成的文件,您将获得一个脚本来创建整个表格。从那里您可以简单地复制生成的 INSERT-Statements。

此方法也适用于制作 export_table 的技术,如@Clodoaldo Neto 的回答所示。

在目标表上单击右键并选择

选择目标路径并将格式更改为

打开选项卡

您可以从那里复制 INSERT 语句。

于 2016-08-15T20:13:04.833 回答
11

对于我的用例,我能够简单地通过管道连接到 grep。

pg_dump -U user_name --data-only --column-inserts -t nyummy.cimory | grep "tokyo" > tokyo.sql
于 2015-08-25T15:38:41.173 回答
9

SQL Workbench就有这样一个特性。

运行查询后,右键单击查询结果并选择“将数据复制为 SQL > SQL 插入”

于 2013-11-27T12:58:12.363 回答
6

我试图根据@PhilHibbs 代码以不同的方式编写一个执行此操作的程序。请查看并测试。

 CREATE OR REPLACE FUNCTION dump(IN p_schema text, IN p_table text, IN p_where text)
   RETURNS setof text AS
 $BODY$
 DECLARE
     dumpquery_0 text;
     dumpquery_1 text;
     selquery text;
     selvalue text;
     valrec record;
     colrec record;
 BEGIN

     -- ------ --
     -- GLOBAL --
     --   build base INSERT
     --   build SELECT array[ ... ]
     dumpquery_0 := 'INSERT INTO ' ||  quote_ident(p_schema) || '.' || quote_ident(p_table) || '(';
     selquery    := 'SELECT array[';

     <<label0>>
     FOR colrec IN SELECT table_schema, table_name, column_name, data_type
                   FROM information_schema.columns
                   WHERE table_name = p_table and table_schema = p_schema
                   ORDER BY ordinal_position
     LOOP
         dumpquery_0 := dumpquery_0 || quote_ident(colrec.column_name) || ',';
         selquery    := selquery    || 'CAST(' || quote_ident(colrec.column_name) || ' AS TEXT),';
     END LOOP label0;

     dumpquery_0 := substring(dumpquery_0 ,1,length(dumpquery_0)-1) || ')';
     dumpquery_0 := dumpquery_0 || ' VALUES (';
     selquery    := substring(selquery    ,1,length(selquery)-1)    || '] AS MYARRAY';
     selquery    := selquery    || ' FROM ' ||quote_ident(p_schema)||'.'||quote_ident(p_table);
     selquery    := selquery    || ' WHERE '||p_where;
     -- GLOBAL --
     -- ------ --

     -- ----------- --
     -- SELECT LOOP --
     --   execute SELECT built and loop on each row
     <<label1>>
     FOR valrec IN  EXECUTE  selquery
     LOOP
         dumpquery_1 := '';
         IF not found THEN
             EXIT ;
         END IF;

         -- ----------- --
         -- LOOP ARRAY (EACH FIELDS) --
         <<label2>>
         FOREACH selvalue in ARRAY valrec.MYARRAY
         LOOP
             IF selvalue IS NULL
             THEN selvalue := 'NULL';
             ELSE selvalue := quote_literal(selvalue);
             END IF;
             dumpquery_1 := dumpquery_1 || selvalue || ',';
         END LOOP label2;
         dumpquery_1 := substring(dumpquery_1 ,1,length(dumpquery_1)-1) || ');';
         -- LOOP ARRAY (EACH FIELD) --
         -- ----------- --

         -- debug: RETURN NEXT dumpquery_0 || dumpquery_1 || ' --' || selquery;
         -- debug: RETURN NEXT selquery;
         RETURN NEXT dumpquery_0 || dumpquery_1;

     END LOOP label1 ;
     -- SELECT LOOP --
     -- ----------- --

 RETURN ;
 END
 $BODY$
   LANGUAGE plpgsql VOLATILE;

进而 :

-- for a range
SELECT dump('public', 'my_table','my_id between 123456 and 123459'); 
-- for the entire table
SELECT dump('public', 'my_table','true');

在我的 postgres 9.1 上测试,使用混合字段数据类型(文本、双精度、整数、没有时区的时间戳等)的表。

这就是需要 TEXT 类型的 CAST 的原因。我的测试正确运行了大约 9M 行,看起来它在运行 18 分钟之前就失败了。

ps:我在 WEB 上找到了 mysql 的等价物。

于 2018-05-24T13:15:07.980 回答
3

您可以查看带有特定记录的表,然后转储 sql 文件

CREATE VIEW foo AS
SELECT id,name,city FROM nyummy.cimory WHERE city = 'tokyo'
于 2012-10-10T08:54:59.293 回答
1

我刚刚敲了一个快速程序来做到这一点。它只适用于单行,所以我创建了一个临时视图,只选择我想要的行,然后用我想要插入的实际表替换 pg_temp.temp_view。

CREATE OR REPLACE FUNCTION dv_util.gen_insert_statement(IN p_schema text, IN p_table text)
  RETURNS text AS
$BODY$
DECLARE
    selquery text; 
    valquery text; 
    selvalue text; 
    colvalue text; 
    colrec record;
BEGIN

    selquery := 'INSERT INTO ' ||  quote_ident(p_schema) || '.' || quote_ident(p_table);

    selquery := selquery || '(';

    valquery := ' VALUES (';
    FOR colrec IN SELECT table_schema, table_name, column_name, data_type
                  FROM information_schema.columns 
                  WHERE table_name = p_table and table_schema = p_schema 
                  ORDER BY ordinal_position 
    LOOP
      selquery := selquery || quote_ident(colrec.column_name) || ',';

      selvalue := 
        'SELECT CASE WHEN ' || quote_ident(colrec.column_name) || ' IS NULL' || 
                   ' THEN ''NULL''' || 
                   ' ELSE '''' || quote_literal('|| quote_ident(colrec.column_name) || ')::text || ''''' || 
                   ' END' || 
        ' FROM '||quote_ident(p_schema)||'.'||quote_ident(p_table);
      EXECUTE selvalue INTO colvalue;
      valquery := valquery || colvalue || ',';
    END LOOP;
    -- Replace the last , with a )
    selquery := substring(selquery,1,length(selquery)-1) || ')';
    valquery := substring(valquery,1,length(valquery)-1) || ')';

    selquery := selquery || valquery;

RETURN selquery;
END
$BODY$
  LANGUAGE plpgsql VOLATILE;

如此调用:

SELECT distinct dv_util.gen_insert_statement('pg_temp_' || sess_id::text,'my_data') 
from pg_stat_activity 
where procpid = pg_backend_pid()

我还没有针对注入攻击对此进行测试,如果 quote_literal 调用不足以解决此问题,请告诉我。

此外,它仅适用于可以简单地转换为 ::text 并再次转换回来的列。

这也是针对 Greenplum 的,但我想不出它不能在 Postgres、CMIIW 上运行的原因。

于 2017-02-17T10:23:29.557 回答
0

我需要一种无需创建临时表(在生产中)即可生成插入语句的方法。我确实在上面的 pg_dump 中看到了一些有用的论据,但最终还是想出了一种方法来

生成插入语句并转储到文件中

下面的语句起到了作用,我认为这对最终在这里寻求类似答案的人很有用。

$ /usr/local/bin/pg_dump -h the_db_host_address -d the_db_name --table=schema_name.table_name --data-only --column-inserts -U postgres -p the_port_number -v -f /Users/the_user/folder_name/insrt_stmts_file_name.sql

接下来是询问密码的提示,在上述情况下,我提供了postgres密码,但任何其他具有读取功能的用户都应该可以正常工作。

insrt_stmts_file_name.sql我在 DBeaver 客户端中运行了名为:的文件中的插入语句 。

但是也可以使用以下脚本从命令提示符运行相同的操作:

/usr/local/bin/psql -h the_db_host_address -d the_db_name -v -U postgres -f /Users/the_user/folder_name/insrt_stmts_file_name.sql

pg_dump / psql 标志的参考: -h = host -d = db name -v = verbose(它会随着它的进行输出) -U = db user name -f = file / path

于 2021-05-04T02:58:02.003 回答
0

右键单击数据库,然后单击备份

在此处输入图像描述

然后仅使用来自转储选项部分的数据和查询的插入命令。

在此处输入图像描述

在此处输入图像描述

然后格式“普通”选择它。

在此处输入图像描述

于 2022-02-16T11:57:18.693 回答
-3

您是否尝试过在 pgadmin 中使用 " EXECUTE QUERY WRITE RESULT TO FILE " 选项 执行查询

它只导出数据,否则尝试

pg_dump -t view_name DB_name > db.sql

-t 选项用于 ==> 仅转储匹配表的表(或视图或序列),请参阅

于 2012-10-10T09:22:06.180 回答