10

我想为一些 csv 文件生成 sql insert 语句。

我可以使用单行 awk 脚本来做到这一点,例如:

awk -F "\t" '{printf("INSERT INTO T_COMMON_ENUM_VALUE (id,name,category_id) values (%s, '\''%s'\'', %s, %s);\n", $1, $2, $3, $4)}'

但这仍然需要一些努力。csvkit 中的 csvsql 似乎会自动生成插入语句。我检查了文档并使用了以下命令,但它不会生成插入语句。

$ cat data02.csv
db_enumvalue_id db_enumvalue_name       db_enumcategory_id
800     şirin   9

$ csvsql data02.csv
CREATE TABLE data02 (
        db_enumvalue_id INTEGER NOT NULL,
        db_enumvalue_name VARCHAR(18) NOT NULL,
        db_enumcategory_id INTEGER NOT NULL
);

它生成创建表语句。但是文档说:

Generate SQL statements for a CSV file or execute those statements directly on a database.

我应该怎么做才能使用 csvkit 获取插入 sql 语句?

4

3 回答 3

5

这是一种完全由数据驱动的方式。有点傻,但它有效。

#!/usr/bin/env bash

##
## ensure script stops on errors
set -eu
set -o pipefail

##
## load your data into a SQLite DB
csvsql test.csv --db=sqlite:///test.db --insert

##
## let SQLite generate the inserts
echo ".dump test" | sqlite3 test.db

运行它,你会得到类似的东西:

BEGIN TRANSACTION;
CREATE TABLE test (
    id INTEGER NOT NULL,
    month VARCHAR(5) NOT NULL,
    market FLOAT NOT NULL,
    acme FLOAT NOT NULL
);
INSERT INTO "test" VALUES(1,'1/86',-0.061134,0.03016);
INSERT INTO "test" VALUES(2,'2/86',0.00822,-0.165457);
INSERT INTO "test" VALUES(3,'3/86',-0.007381,0.080137);
...
INSERT INTO "test" VALUES(60,'12/90',-0.026401,-0.190834);
COMMIT;

将其捕获到文件中,您就可以了。如果您还想自动化插入阶段,也可以包装在 Python 子进程调用中,或通过管道传输到数据库命令行客户端。

如果您要插入到现有表中,这种方法适用于像 MySQL 这样进行隐式类型转换的 DBMS,因为 CSV 无法为过去字符串和数字的字段定义数据类型。对于像 Postgres 这样更严格的 DBMS,您需要编辑脚本文件中的数据类型。

于 2017-09-27T22:57:16.790 回答
1

看文档,我猜是这样的:

如果目标表 T_COMMON_ENUM_VALUE 已经存在:

$ csvsql --tables T_COMMON_ENUM_VALUE --insert --no-create data02.csv

如果目标表 T_COMMON_ENUM_VALUE 不存在:

$ csvsql --tables T_COMMON_ENUM_VALUE --insert data02.csv

这应该只输出脚本,如果你想将语句执行到你的数据库,你需要添加--db CONNECTION_STRING,例如:

$ csvsql --db mssql://user:pass@host:port/database --tables T_COMMON_ENUM_VALUE --insert data02.csv

我希望这有帮助

于 2016-07-07T07:52:50.737 回答
0

使用 csvsql 生成插入或删除 SQL 脚本可能没有直接的解决方案;至少当我迫切需要它时,我自己找不到。然而,--query通过允许我们自己准备这样的陈述,我们可以选择这个选项。当然,它需要一点点努力,但它的回报非常好。

这是一个例子。我有一个 csv 文件(称为 test2.csv)。这就是我能够为 csv 文件中的所有行生成插入语句的方式。

csvsql  --query "SELECT 'insert into test2  values (''' ||    
trim(ifnull(my_table.survived, 'null123')) ||''' ,''' ||     
trim(ifnull(my_table.RECORD_TYPE, 'null123')) ||''' ,''' ||     
trim(ifnull(my_table.BASE_HIN, 'null123')) ||''' ,''' ||     
trim(ifnull(my_table.SUFFIX, 'null123')) ||''',''' ||     
trim(ifnull(my_table.name, 'null123')) ||''' ,''' ||     
trim(ifnull(my_table.ADDRESS_1, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.ADDRESS_2, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.CITY, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.STATE, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.PRIMARY_ZIP, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.COUNTRY, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.TELEPHONE, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.CLASS_OF_TRADE, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.DEA, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.DATE_HIN_ASSIGNED, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.DATE_LAST_EDITED, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.STATUS, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.VERIFIED, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.LAST_ACTION_CODE, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.REASON_CODE, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.REFERBACK_CODE, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.SUBSET, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.UPIN, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.SPECIALTY, 'null123')) ||'''  ,''' ||     
trim(ifnull(my_table.FAX, 'null123')) ||''' )'FROM test2 as my_table WHERE survived='0'" test2.csv > insert.sql

确保这是一行,因为 csvsql 不喜欢虚线。

此外,一旦insert.sql准备好,您需要删除标题行,删除双引号(从所有行中)并查找并替换= 'null123'is null.

于 2017-05-17T21:50:43.733 回答