2010-11-16 23 views
18

¿Hay algún comando SQLite o herramienta de terceros que permita que los volcados de base de datos incluyan nombres de columna en las instrucciones INSERT INTO?Exportación SQLite con nombres de columna

En lugar de

INSERT INTO "MyTable" VALUES ('A', 'B'); 

me gustaría ver

INSERT INTO "MyTable" (Column1, Column2) VALUES ('A', 'B'); 

El comando .dump en SQLite sólo ofrece la primera versión.

Respuesta

2

Eché un vistazo rápido al código fuente. No vi ninguna forma obvia de hacer eso. Pero preparé un script awk rápido y sucio para insertar los nombres de las columnas.

A partir de este basurero:

PRAGMA foreign_keys=OFF; 
BEGIN TRANSACTION; 
CREATE TABLE test (test_id int primary key, test_name varchar(35)); 
INSERT INTO "test" VALUES(1,'Wibble'); 
INSERT INTO "test" VALUES(2,'Wobble'); 
INSERT INTO "test" VALUES(3,'Pernicious'); 
COMMIT; 

que corrió este script awk

/CREATE TABLE/ { 
    # Extract the part between parens. This part contains the 
    # column definitions. 
    first_col = match($0, /\(.*\)/); 
    if (first_col) { 
    num_columns = split(substr($0, RSTART + 1, RLENGTH), a, ","); 
    for (i = 1; i <= num_columns; i++) { 
     sub(/^ /, "", a[i]); 
     split(a[i], names, " "); 
     column_names[i] = names[1]; 
    } 
    } 
} 
/INSERT INTO \"[A-Za-z].*\"/ { 
    insert_part = match($0, /INSERT INTO \"[A-Za-z].*\"/); 
    printf("%s ", substr($0, RSTART, RLENGTH)); 

    printf("("); 
    for (j = 1; j <= num_columns; j++) { 
    if (j == 1) { 
     printf("%s", column_names[j]); 
    } 
    else { 
     printf(", %s", column_names[j]); 
    } 
    } 
    printf(") "); 

    values_part = substr($0, RLENGTH+1, length($0) - RSTART); 
    printf("%s\n", values_part); 

} 

que me dio esta salida.

INSERT INTO "test" (test_id, test_name) VALUES(1,'Wibble'); 
INSERT INTO "test" (test_id, test_name) VALUES(2,'Wobble'); 
INSERT INTO "test" (test_id, test_name) VALUES(3,'Pernicious'); 
5

Déjame tomar otra grieta en esto.

Vuelque los nombres de columna y las instrucciones INSERT a un archivo.

sqlite> .output test.data 
sqlite> pragma table_info(test); 
sqlite> .dump test 
sqlite> .quit 

$ cat test.data 
0|test_id|int|0||1 
1|test_name|varchar(35)|0||0 
PRAGMA foreign_keys=OFF; 
BEGIN TRANSACTION; 
CREATE TABLE test (test_id int primary key, test_name varchar(35)); 
INSERT INTO "test" VALUES(1,'Wibble'); 
INSERT INTO "test" VALUES(2,'Wobble'); 
INSERT INTO "test" VALUES(3,'Pernicious'); 
COMMIT; 

Ahora ejecute este script awk

/\|/ { 
    split($0, col_name, "|"); 
    column_names[++n] = col_name[2]; 
} 
/INSERT INTO \"[A-Za-z].*\"/ { 
    insert_part = match($0, /INSERT INTO \"[A-Za-z].*\"/); 
    printf("%s ", substr($0, RSTART, RLENGTH)); 

    printf("("); 
    for (i = 1; i <= n; i++) { 
    if (i == 1) { 
     printf("%s", column_names[i]); 
    } 
    else { 
     printf(", %s", column_names[i]); 
    } 
    } 
    printf(") "); 

    values_part = substr($0, RLENGTH+1, length($0) - RSTART); 
    printf("%s\n", values_part); 


} 

Y obtenemos

$ awk -f dump_with_col_names.awk test.data 
INSERT INTO "test" (test_id, test_name) VALUES(1,'Wibble'); 
INSERT INTO "test" (test_id, test_name) VALUES(2,'Wobble'); 
INSERT INTO "test" (test_id, test_name) VALUES(3,'Pernicious'); 
+0

Desafortunadamente esto sólo se puede utilizar para una mesa al mismo tiempo, y si no hay un carácter de barra vertical (|) en cualquier parte de sus datos. – qris

3

he creado este script de shell:

#!/bin/sh 

SQLITE=sqlite3 

if [ -z "$1" ] ; then 
     echo usage: $0 sqlite3.db 
     exit 
fi 

DB="$1" 

TABLES=`"$SQLITE" "$DB" .tables` 
echo "-- $TABLES" 
echo 'BEGIN TRANSACTION;' 

for TABLE in $TABLES ; do 
     echo 
     echo "-- $TABLE:"; 
     COLS=`"$SQLITE" "$DB" "pragma table_info($TABLE)" | 
     cut -d'|' -f2 ` 
     COLS_CS=`echo $COLS | sed 's/ /,/g'` 
     echo -e ".mode insert\nselect $COLS_CS from $TABLE;\n" | 
     "$SQLITE" "$DB" | 
     sed "s/^INSERT INTO table/INSERT INTO $TABLE ($COLS_CS)/" 
done 
echo 'COMMIT;'; 

dos problemas:

  1. tablas y columnas deben tener nombres 'normales' (es decir alfa-num-subrayado),
  2. datos no pueden contener la cadena '\ nInsertar EN mesa.
-2

script en Python sencillo hacer el truco

import sqlite3 
infile="your_file.sqlite3" 
table="your_table" 

conn = sqlite3.connect(infile) 
conn.row_factory = sqlite3.Row 

c = conn.cursor() 
res = c.execute("SELECT * FROM " + table) 
curr_row = -1 

for row in res: 
    curr_row += 1 
    if curr_row == 0: 
     col_names = sorted(row.keys()) 
     s = "INSERT INTO " + table + " (" 
     for col_name in col_names: 
     s+=col_name + "," 
     prefix = s[:-1] + ") VALUES (" 

    s = "" 
    for col_name in col_names: 
    col_val = row[col_name] 
    if isinstance(col_val,int) or isinstance(col_val,float): 
     s+= str(row[col_name]) +"," 
    else: 
     s+= "'" + str(row[col_name]) +"'," 
    print prefix,s[:-1],");" 
+2

Esto no escapa correctamente nombres, cadenas o blobs. –

2

He aquí una versión de Perl que funciona con cualquier número de tablas:

#!/usr/bin/perl 

use strict; 
use warnings; 

my @column_names; 
my $col_reset = 1; 

while(<>) 
{ 
    if (/^\d+\|/) { 
    if ($col_reset) 
    { 
     @column_names =(); 
     $col_reset = 0; 
    } 
    my @col_info = split(/\|/); 
    push @column_names, $col_info[1]; 
    } 

    if(/INSERT INTO/) { 
    m/(INSERT INTO \"?[A-Za-z_]+\"?) (.*)/ or die $_; 
    my $insert_part = $1; 
    my $values_part = $2; 
    print $insert_part." (".join(",", @column_names).") ".$values_part."\n"; 
    $col_reset = 1; 
    } 
} 

Y así es como me genera el volcado de cada mesa en la base de datos:

grep 'CREATE TABLE' /tmp/school.sql.final \ 
| awk '{ print $3 }' \ 
| while read table; do 
    echo -e "pragma table_info($table);\n.dump $table" 
done | sqlite3 school.db \ 
> /tmp/school.sql.final-with-table-info 
0

Otro AWK sc ript que funciona directamente desde la salida de "sqlite3 data.db.volcado" para cualquier número de tablas

Se utiliza el hecho de que las instrucciones CREATE ahora se imprimen con cada columna en su propia línea

BEGIN { 
     state = "default" # Used to know if we are in the middle of a table declaration 
     print_definitions = 1 # Wether to print CREATE statements or not 
} 

state == "default" && match($0, /^CREATE TABLE ([A-Za-z0-9_]+)/, a) { 
     tablename = a[1] 
     state = "definition" 
     if (print_definitions) 
       print 
     next 
} 

state == "definition" && /^);$/ { 
     state = "default" 
     if (print_definitions) 
       print 
     next 
} 

state == "definition" && ! (/PRIMARY/ || /UNIQUE/ || /CHECK/ || /FOREIGN/) { 
     if (length(columnlist [tablename])) 
       columnlist[tablename] = columnlist[tablename] ", " 
     columnlist[tablename] = columnlist[tablename] $1 
     if (print_definitions) 
       print 
     next 
} 

state == "default" && match($0, /^(INSERT INTO ")([A-Za-z0-9_]+)"(.*)$/, a) { 
     print a[1] a[2] "\" (" columnlist[a[2]] ")" a[3] 
} 
+0

No estoy seguro de que esto responda la pregunta. – Kmeixner

0

Louis L. solución no estaba trabajando para mí, así que hice este gawk solución probada con vertederos de la versión 3.8.7.1 sqlite3

la tabla CREATE son como por ejemplo

CREATE TABLE "strom" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "otec" integer NOT NULL, 
    "nazev" text NOT NULL, 
    "ikona" text NULL, 
    "barva" text NULL 
); 

sino que también puede tener un aspecto como éste

CREATE TABLE "changes" (
    "version" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "last_change" text NOT NULL DEFAULT (datetime('now','localtime')), 
    `ref` text NOT NULL, 
    "ref_id" text NULL, 
    "action" text NOT NULL 
, "data" text NOT NULL DEFAULT ''); 

#!/usr/bin/gawk -f 

# input is sqlite3 dump, tested with sqlite3 version 3.8.7.1 
# output are INSERT statements including column names 
# i.e. not e.g. 
# INSERT INTO "changes" VALUES(1,'2016-07-19 17:46:12','cenik','10','UPDATE',''); 
# like in standard dump 
# but 
# INSERT INTO "changes" ("version", "last_change", "ref", "ref_id", "action", "data") VALUES(1,'2016-07-19 17:46:12','cenik','10','UPDATE',''); 
# BEGIN TRANSACTION and COMMIT are included in output 

BEGIN { 
     state = "default" # default/definition/insert let us know wether we are in CREATE or INSERT statement 
     print_definitions = 0 # wether to print CREATE statements or not 
} 

state == "default" && match($0, /^CREATE TABLE \"([A-Za-z0-9_]+)\" *\($/, a) { 
     tablename = a[1] 
    state = "definition" 
     if (print_definitions) 
       print 
     next 
} 

state == "definition" && /^ *); *$/ { 
     state = "default" 
     if (print_definitions) 
       print 
     next 
} 

state == "definition" && ! (/^[\ ]{1,2}PRIMARY/ || /UNIQUE/ || /CHECK/ || /^[\ ]{1,2}FOREIGN KEY.*REFERENCES/) { 
     if (length(columnlist [tablename])) 
       columnlist[tablename] = columnlist[tablename] ", " 
     if (match($0, /(\".*\")/, b)) 
     columnlist[tablename] = columnlist[tablename] b[1] 
    if (match($0, /`(.*)`/, c)) 
     columnlist[tablename] = columnlist[tablename] "\""c[1]"\"" 
     if (print_definitions) 
       print 
} 

state == "definition" && /^.*); *$/ { 
     state = "default" 
     next 
} 

state == "default" && match($0, /^(INSERT INTO ")([A-Za-z0-9_]+)"(.*)/, a) { 
     print a[1] a[2] "\" (" columnlist[a[2]] ")" a[3] 
    state = "insert" 
    if (/^.*); *$/) 
     state = "default" 
} 

state == "insert" && ! /^INSERT INTO/{ 
    print 
} 

state == "insert" && /^.*); *$/ { 
     state = "default" 
    next 
} 

state == "default" && (/^ *BEGIN TRANSACTION;/ || /^ *COMMIT;/) { 
    print 
} 
0

Esto no responde a la pregunta. Estoy escribiendo esto aquí porque es la forma en que estoy abordando un problema similar. Una forma es volcar la estructura y los datos por separado. Para insertos como el que describes fuera del archivo de datos:

sqlite> .headers on 
sqlite> .mode insert MyTable 
sqlite> .output MyTable_data.sql 
sqlite> select * from MyTable; 
sqlite> .quit 
0

Hay un módulo de extensión SQLite para la importación/exportación información de base de datos desde/hacia el texto original de SQL y exportación a texto CSV. http://www.ch-werner.de/sqliteodbc/html/impexp_8c.html

Por ejemplo, en Ubuntu sus pasos son:

  1. instalar el módulo del repositorio ubuntu

    sudo apt install libsqlite3-mod-impexp 
    
  2. módulo de carga en la línea de comandos sqlite pronta ejecución

    .load libsqlite3_mod_impexp 
    
  3. Exportar base de datos t O dump.sql presentar

    select export_sql('dump.sql','1'); 
    
  4. ejemplo Resultado de mi base de datos es

    INSERT OR REPLACE INTO "camera" ("name","reviews") VALUES('BenQ GH700', NULL); 
    INSERT OR REPLACE INTO "camera" ("name","reviews") VALUES('Canon EOS 40D', NULL); 
    
Cuestiones relacionadas