通过从文本文件中读取数据自动加载SQL表

时间:2013-10-06 03:12:25

标签: python sqlite

我正在尝试编写一个python脚本,它将使用SQL加载我在pyhton中创建的表,并使用来自文本文件的数据自动填充它们。我坚持基本编码。我确实有一个大概,但是当我尝试运行这种方法时,我遇到了错误。我创建了2个表。我已经读过这个文件了。该文件是逗号分隔的文本文件,没有标题。

该文件的前3行如下所示。

+ ---- + ----- + -------------------- + -------- + - + --- + ----- +
| John | Smith | 111 N. Wabash Avenue | plumber  | 5 | 1.0 | 200   |
| John | Smith | 111 N. Wabash Avenue | bouncer  | 5 | 1.0 | 200   |
| Jane | Doe   | 243 S. Wabash Avenue | waitress | 1 | 5.0 | 10000 |
+ ---- + ----- + -------------------- + -------- + - + --- + ----- +

import sqlite3
conn= sqlite3.connect('csc455.db')
c = conn.cursor()

#Reading the data file
fd = open ('C:/Users/nasia/Documents/data_hw2.txt','r')
data = fd.readlines()

#Creating Tables
>>> L = """create table L
... (first text, last text, address text, job text, LNum integer,
... constraint L_pk
... primary key(first, last, address, job),
... constraint L_fk
... foreign key (LNum) references LN(LNum)
... );"""
>>> c.execute(L)

LN = """create table LN
... (
... LNum integer, Interest float, Amount, Integer,
... constraint LN_pk
 ... primary key (LNum)
... );"""
 c.execute(LN)

#Inserting into database
for elt in data:
...     currentRow = elt.split(", ")[:-1]
...     insert = """(insert into LN values (%s, %s, %s);, %(currentRow[4], currentRow[5], currentRow[6]))"""
...     c.execute(insert)

这里有一些语法错误。代码停止工作。我无法弄清楚我做错了什么。 错误是     Traceback(最近一次调用最后一次):       文件"",第4行,in     OperationalError:near"(&#34 ;:语法错误

我无法弄清楚我做错了什么

2 个答案:

答案 0 :(得分:3)

如果您可以使用标准sqlite3实用程序,则可以更轻松地执行此操作:

sqlite3 -init mydata.sql mydatabase.db ""

只需从你的python脚本中调用这一行,就完成了。

这将读取包含有效SQL语句的任何文本文件,如果不存在,将创建mydatabase.db。更重要的是,它支持跨越多行的语句,并且还使用--comment语法和C / C ++(如/*comment*/语法正确地忽略SQL注释。

通常,您的mydata.sql内容应如下所示:

BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS table1 (
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(32)
);
INSERT INTO table1 (name) VALUES
('John'),
('Jack'),
('Jill');
-- more statements ...
COMMIT;

答案 1 :(得分:3)

您还没有解释数据的格式,表格结构是什么,或者您想如何映射数据,这使得这很难回答。但我会自己做,并回答这个问题,并希望它会有所帮助:

infile.txt:

CommonName,Species,Location,Color
Black-headed spider monkey,Ateles fusciceps,Ecuador,black
Central American squirrel monkey,Saimiri oerstedii,Costa Rica,orange
Vervet,Chlorocebus pygerythrus,South Africa,white

script.py

import csv
import sqlite3

db = sqlite3.connect('outfile.db')
cursor = db.cursor()
cursor.execute('CREATE TABLE Monkeys (Common Name, Color, Species)')
cursor.execute('''CREATE TABLE MonkeyLocations (Species, Location,
                  FOREIGN KEY(Species) REFERENCES Monkeys(Species))''')
with open('infile.txt') as f:
    for row in csv.DictReader(f):
        cursor.execute('''INSERT INTO Monkeys 
                          VALUES (:CommonName, :Color, :Species)''', row)
        cursor.execute('''INSERT INTO MonkeyLocations 
                          VALUES (:Species, :Location)''', row)
db.commit()
db.close()

当然,如果您的真实数据采用的是CSV以外的其他格式,您将使用不同的代码来解析输入文件。

我还使事情比实际数据可能要处理的要复杂得多 - CSV列的名称与SQL列的名称不完全相同。

在其他方面,您的数据可能更复杂 - 例如,如果您的架构具有引用自动递增的行ID而不是文本字段的外键,则您需要在第一次插入后获取rowid。

但这应该足以让你有这个想法。


现在您已经显示了更多详细信息......您处于正确的轨道上(尽管调用readlines而不是直接迭代fd是浪费的,您应该关闭数据库和文件,理想情况下使用with语句,...),但是你在接近结尾处有一个简单的错误,阻止你进一步:

insert = """(insert into LN values (%s, %s, %s);, %(currentRow[4], currentRow[5], currentRow[6]))"""
c.execute(insert)

您已将格式%表达式直接放入字符串中,而不是在字符串上使用运算符。我想你要做的是:

insert = """insert into LN values (%s, %s, %s);""" % (currentRow[4], currentRow[5], currentRow[6])
c.execute(insert)

但是,你不应该这样做。相反,这样做:

insert = """insert into LN values (?, ?, ?);"""
c.execute(insert, (currentRow[4], currentRow[5], currentRow[6]))

有什么区别?

好吧,第一个只是将值作为Python字符串插入语句中。这意味着你必须自己处理转换为正确的格式,引用,转义等,而不是让数据库引擎决定如何处理每个值。当你试图保存一个布尔值或者忘记引用一个字符串时,除了成为令人沮丧的错误的来源之外,这还会让你受到SQL injection攻击,除非你非常小心。

除此之外还有其他问题。例如,大多数数据库都会尝试缓存重复的语句,并且告诉我insert into LN values (?, ?, ?)的3000个实例都是相同的语句是微不足道的,但要说明insert into LN values (5, 1.0, 200)insert into LN values (1, 5.0, 5000)是{{1}}同样的声明。