Skip to main content
 首页 » 编程设计

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

2025年05月04日18insus

我正在尝试编写一个 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) 

这里有一些语法错误。代码停止工作。我不知道我做错了什么。 错误是 追溯(最近一次通话): 文件“”,第 4 行,位于 OperationalError: near "(": 语法错误

我不知道我做错了什么

请您参考如下方法:

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

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 

脚本.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 字符串插入到语句中。这意味着您必须自己负责转换为正确的格式、引用、转义等,而不是让数据库引擎决定如何处理每个值。当您尝试保存 bool 值或忘记引用字符串时,除了成为令人沮丧的错误的来源之外,这还会使您对 SQL injection 敞开心扉。除非你非常小心,否则攻击。

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