2009-11-30 23 views
10

Un po 'di un titolo vago, spiegherò.Script SQL per creare script di inserimento

Sto scrivendo uno script SQL per creare un'istruzione di inserimento per ogni riga di una tabella nel mio database, puramente per essere in grado di applicare tali dati a un altro database.

Ecco quello che ho in questo momento:

SELECT 'INSERT INTO products (id,name,description) VALUES ('||ID||','''||name||''','''||description||''');' FROM products 

e funziona benissimo, l'output di questo:

INSERT INTO products (id,name,description) VALUES (1,'Lorem','Ipsum'); 
INSERT INTO products (id,name,description) VALUES (2,'Lorem','Ipsum'); 
INSERT INTO products (id,name,description) VALUES (3,'Lorem','Ipsum'); 
INSERT INTO products (id,name,description) VALUES (4,'Lorem','Ipsum'); 

Il problema è che se uno dei campi è vuoto che fila mancherà di produrre uno script di aggiornamento, nel file di output la riga è vuota. Ovviamente, poiché ci sono più di 20 campi, alcuni facoltativi significano che quasi nessuno dei miei script viene generato.

C'è un modo per risolvere questo problema?

risposta

5

nel caso di campi NULL si può fare qualcosa di simile

Select COALESCE(Name, '') from... 

la funzione COALESCE restituisce il primo valore non nullo nell'elenco.

Per i campi veramente vuoti (vuoto nvarchar per esempio) credo che il tuo script sopra funzionerà.

+0

Cheers Chris, ha funzionato alla grande. –

+0

Vorrei avvisarvi che questo non è sicuro da iniezioni SQL. Un singolo apostrofo in una colonna rovinerà l'SQL risultante o potrebbe essere sfruttato da un utente malintenzionato per eseguire query arbitrarie nel database. – intgr

+2

Anche questo non genererà le stesse righe esatte. La coalescenza come sopra finirà per inserire valori di stringa vuoti in cui dovrebbe essere inserito valori NULL. –

4

Utilizzare la funzione quote_nullable() nuova in PostgreSQL 8.4. Oltre a consentire valori NULL, mantiene i tipi di dati e ti protegge dalle tabelle Bobby (iniezioni SQL):

SELECT 'INSERT INTO products (id,name,description) VALUES (' || 
quote_nullable(ID) || ',' || quote_nullable(name) || ',' || 
quote_nullable(description) || ');' FROM products; 

Nelle versioni più vecchie, si ottiene lo stesso comportamento con coalesce() e quote_literal():

SELECT 'INSERT INTO products (id,name,description) VALUES (' || 
coalesce(quote_literal(ID), 'null') || ',' || 
coalesce(quote_literal(name), 'null') || ',' || 
coalesce(quote_literal(description), 'null') || ',' || 
');' FROM products; 
+0

Molte grazie per la risposta, ma ottengo un errore che la funzione quote_nullable non esiste. Nonostante questa soluzione, Chris Clarks ha funzionato. Ancora una volta, molte grazie. –

+0

D'oh, 'quote_nullable()' è nuovo in PostgreSQL 8.4 – intgr

13
pg_dump -a -U user1 -t products -f products.copy database1 

e poi:

psql -U user2 -d database2 -f products.copy 

e il gioco è fatto. È anche più sicuro e veloce.

1

Ho scritto uno script python basato su @intgr answer per costruire l'istruzione select. Prende lista di colonne separate da virgola da stdin (usare -).

Volevo usare sqlparse ma non riuscivo a capire come usare quella lib.

import fileinput 

names = ' '.join(fileinput.input()) 

ns = [x.strip() for x in names.split(',')] 
quoted = ['quote_nullable(' + x + ')' for x in ns] 
insert = "SELECT 'INSERT INTO <TABLE> (" + (', ').join(ns) + ") VALUES(' || " + (" || ',' || ").join(quoted) + " || ');' FROM <TABLE>" 
print insert 

GIST dello script è qui: https://gist.github.com/2568047