J'ai un schéma de base de données nommé: nyummy
et une table nommée 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)
);
Je souhaite exporter les données de la table cimory
en tant que fichier de script SQL d'insertion. Cependant, je souhaite uniquement exporter les enregistrements/données où la ville est égale à 'tokyo' (en supposant que les données de la ville sont toutes en minuscules).
Comment faire?
Peu importe que la solution soit dans des outils d'interface graphique gratuits ou en ligne de commande (bien que la solution d'outils d'interface graphique soit meilleure). J'ai essayé pgAdmin III, mais je ne trouve pas d'option pour le faire.
Créez une table avec l'ensemble que vous souhaitez exporter, puis utilisez l'utilitaire de ligne de commande pg_dump pour exporter dans un fichier:
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
affichera des commandes d’insertion avec des noms de colonnes.
--data-only
ne pas vider le schéma.
Comme indiqué ci-dessous, la création d'une vue dans une table évite la création d'une table chaque fois qu'une nouvelle exportation est nécessaire.
Pour une exportation data-only, utilisez COPY
.
Vous obtenez un fichier avec une ligne de tableau par ligne sous forme de texte brut (pas de commandes INSERT
), il est plus petit et plus rapide:
COPY (SELECT * FROM nyummy.cimory WHERE city = 'tokio') TO '/path/to/file.csv';
Import identique dans une autre table de la même structure n'importe où avec:
COPY other_tbl FROM '/path/to/file.csv';
COPY
écrit et lit les fichiers local du serveur, contrairement aux programmes clients tels que pg_dump
ou psql
qui lisent et écrivent des fichiers local du client. Si les deux fonctionnent sur le même ordinateur, peu importe, mais c'est le cas pour les connexions à distance.
Il y a aussi la commande \copy
de psql that:
Effectue une copie frontale (client). C'est une opération qui exécute un Commande SQL
COPY
, mais au lieu que le serveur lise ou écrit le fichier Le fichier spécifié, psql lit ou écrit le fichier et achemine les données entre le serveur et le système de fichiers local. Cela signifie que le fichier l'accessibilité et les privilèges sont ceux de l'utilisateur local, pas le serveur, et aucun privilège de superutilisateur SQL n'est requis.
Ceci est un simple et rapide moyen de exporter une table dans un script avec pgAdmin manuellement sans installations supplémentaires:
Cette méthode fonctionne également avec la technique de création d'une table export_ comme indiqué dans la réponse de @Clodoaldo Neto.
SQL Workbench a une telle fonctionnalité.
Après avoir exécuté une requête, faites un clic droit sur les résultats de la requête et choisissez "Copier les données en tant que SQL> Insertion SQL".
Pour mon cas d'utilisation, je pouvais simplement me connecter à grep.
pg_dump -U user_name --data-only --column-inserts -t nyummy.cimory | grep "tokyo" > tokyo.sql
Vous pouvez afficher la table avec des enregistrements spécifiques, puis vider le fichier SQL
CREATE VIEW foo AS
SELECT id,name,city FROM nyummy.cimory WHERE city = 'tokyo'
J'ai essayé d'écrire une procédure faisant cela, basée sur les codes @PhilHibbs, d'une manière différente… .. Veuillez regarder et tester.
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;
Et alors :
-- for a range
SELECT dump('public', 'my_table','my_id between 123456 and 123459');
-- for the entire table
SELECT dump('public', 'my_table','true');
testé sur mon postgres 9.1, avec une table avec un type de données de champ mixte (texte, double, int, horodatage sans fuseau horaire, etc.).
C’est pourquoi le type CAST in TEXT est nécessaire . Mon test s’exécute correctement pendant environ 9 millions de lignes et semble échouer juste avant 18 minutes d’exécution.
ps: J'ai trouvé un équivalent pour MySQL sur le WEB.
Je viens de mettre au point une procédure rapide pour le faire. Cela ne fonctionne que pour une seule ligne, je crée donc une vue temporaire qui sélectionne simplement la ligne que je veux, puis remplace la page pg_temp.temp_view par la table dans laquelle je veux insérer.
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;
Invoqué ainsi:
SELECT distinct dv_util.gen_insert_statement('pg_temp_' || sess_id::text,'my_data')
from pg_stat_activity
where procpid = pg_backend_pid()
Je n'ai pas testé cela contre les attaques par injection, merci de me prévenir si l'appel quote_literal n'est pas suffisant pour cela.
En outre, cela ne fonctionne que pour les colonnes qui peuvent être simplement converties en :: text et inversement.
C'est aussi pour Greenplum, mais je ne vois pas pourquoi cela ne fonctionnerait pas avec Postgres, CMIIW.