SQLite导出列名

时间:2010-11-16 22:48:06

标签: sql sqlite

是否有任何SQLite命令或第三方工具允许数据库转储在INSERT INTO语句中包含列名?

而不是

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

我想看看

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

SQLite中的.dump命令仅提供第一个版本。

11 个答案:

答案 0 :(得分:6)

让我再看一次。

将列名和INSERT语句转储到文件中。

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;

现在运行这个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);


}

我们得到了

$ 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');

答案 1 :(得分:4)

这不回答这个问题。我在这里写这篇文章是因为我正在解决类似的问题。一种方法是分别转储结构和数据。对于您在数据文件之外描述的插入:

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

答案 2 :(得分:3)

我创建了这个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;';

两个问题:

  1. 表和列必须具有“正常”名称(即 α-NUM-下划线),
  2. 数据不能包含字符串'\ nINSERT INTO 表”。

答案 3 :(得分:2)

我快速浏览了一下源代码。我没有看到任何明显的方法来做到这一点。但是我掀起了一个快速而又脏的awk脚本来插入列名。

从此转储开始:

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;

我运行了这个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);

}

给了我这个输出。

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');

答案 4 :(得分:2)

这是一个适用于任意数量的表的Perl版本:

#!/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;
  }
}

这就是我如何生成数据库中每个表的转储:

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

答案 5 :(得分:2)

有一个用于导入/导出的SQLite扩展模块 数据库信息来自/到SQL源文本和 导出为CSV文本。 http://www.ch-werner.de/sqliteodbc/html/impexp_8c.html

例如在Ubuntu中,您的步骤是:

  1. 从ubuntu存储库安装模块

    sudo apt install libsqlite3-mod-impexp
    
  2. 在sqlite命令行提示符下运行

    加载模块
    .load libsqlite3_mod_impexp
    
  3. 将数据库导出到dump.sql文件

    select export_sql('dump.sql','1');
    
  4. 我的数据库的结果示例是

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

答案 6 :(得分:0)

Another AWK script which works directly from the output of "sqlite3 data.db .dump" for any number of tables

It uses the fact that CREATE statements are now printed with each column on its own line

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]
}

答案 7 :(得分:0)

路易斯L.解决方案对我不起作用,所以我用sqlite3版本3.8.7.1的转储测试了这个gawk解决方案

表CREATE语句就像是。

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

但也可能看起来像这个

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
}

答案 8 :(得分:0)

如果您不介意GUI。您可以使用DB Browser for SQLite。 选中选项在INSERT INTO中保留列名

export dialog

答案 9 :(得分:0)

结合外壳管道的纯SQL解决方案:

创建文件dump_sqlite.sql

.headers off
.mode list

select
    "select " || """" || "insert into " || tab || " (" ||
    "" || group_concat(col_name) || ") VALUES (" || """ || " ||
    group_concat(col_val, " || "","" || ") || 
    " || "")" || """" || " FROM " || tab || ";" as stmt
from (
select
    m.name as tab,
    ti.name as col_name,
    case
        when ti.type like "text" or ti.type like "varchar%" 
            then """"" || " || "coalesce(quote(`" || ti.name || "`), 'NULL')" || " || """""
        else "coalesce(`" || ti.name || "`, 'NULL')"
    end as col_val,
    ti.type as coltype
from sqlite_master as m,
-- https://stackoverflow.com/a/54962853
PRAGMA_TABLE_INFO(m.name) as ti
where m.type = 'table' and m.name not like 'sqlite_%'
) group by tab
;

然后执行shell命令:

sqlite3 your.db < ./dump_sqlite.sql | sqlite3 your.db

如果要将输出保存到文件(而不是将其打印到控制台), 将最终重定向添加到文件。

sqlite3 your.db < ./dump_sqlite.sql | sqlite3 your.db > dump.sql

答案 10 :(得分:-2)

直截了当的python脚本做的伎俩

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],");"