将URL写入数据库时的错误 (sqlite3.OperationalError: 没有此列)

0 投票
1 回答
2123 浏览
提问于 2025-04-18 15:15

我正在尝试把一些网址写入sqlite数据库。我已经成功地在没有网址的情况下完成了这个操作。如果我把 'Volumes/data/rc3/2/sdss/SDSS_r_0_0.fits' 替换成一个数字,它也能正常工作。

c.execute("INSERT INTO rc3 (ID,ra,dec,radius,PGC_number,new_ra, new_dec, new_radius,ufits,gfits,rfits,ifits,zfits,best,low,in_SDSS_footprint,clean,error)VALUES({},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{})".format(n,pgc,ra,dec,radius,new_ra,new_dec,new_radius,2, 3, 4, 5, 6, 7,8,in_SDSS_footprint,clean,error))

看起来它把网址误认为是一个列,所以出现了这个错误:

c.execute("CREATE TABLE rc3 (ID INT , PGC_number INT,ra REAL, dec REAL,radius REAL,new_ra REAL,new_dec REAL,new_radius REAL, ufits TEXT, gfits TEXT, rfits TEXT ,ifits TEXT, zfits TEXT, best TEXT, low TEXT,in_SDSS_footprint BIT ,clean BIT, error INT,PRIMARY KEY(ID))")
....
c.execute("INSERT INTO rc3 (ID,ra,dec,radius,PGC_number,new_ra, new_dec, new_radius,ufits,gfits,rfits,ifits,zfits,best,low,in_SDSS_footprint,clean,error)VALUES({},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{})".format(0, 0.0075, 47.2744444444, 0.01999027436515, 2, 0, 0, 0, 'Volumes/data/rc3/2/sdss/SDSS_u_0_0.fits', 'Volumes/data/rc3/2/sdss/SDSS_g_0_0.fits', 'Volumes/data/rc3/2/sdss/SDSS_r_0_0.fits', 'Volumes/data/rc3/2/sdss/SDSS_i_0_0.fits', 'Volumes/data/rc3/2/sdss/SDSS_z_0_0.fits', 'Volumes/data/rc3/2/sdss/SDSS_0_0_BEST.tiff ', 'Volumes/data/rc3/2/sdss/SDSS_0_0_LOW.tiff ', 0, 1, 0))
sqlite3.OperationalError: no such column: Volumes 

但我不太确定该怎么做。提前谢谢你。

1 个回答

3

不要试着通过字符串格式化命令来创建SQL语句,也就是说,不要把值直接嵌入到SQL语句里。应该使用SQL参数。

比如,不要这样做:

c.execute("INSERT INTO breakfast (id, spam, eggs) VALUES({}, {}, {})".format(
    id, spam, eggs))

… 而是这样做:

c.execute("INSERT INTO breakfast (id, spam, eggs) VALUES(?, ?, ?)",
          id, spam, eggs)

这个在sqlite3的文档开头就有说明。简单来说,采用这种方式的原因有几个(按重要性大致排序):

  • 可以避免SQL注入,尤其是当数据可能来自恶意用户或不太懂的程序时。
  • 这样你就不用担心如何处理字符串的引号、转义,或者格式化数字等问题。
  • 能让错误更明显,特别是当值的类型不对时,更容易找到问题。
  • 让SQL引擎能把你的一千个插入操作看作是同一个语句,只是值不同,而不是一千个完全不同的语句,这样更有可能进行缓存或优化。
  • 可以使用executemany,这比用循环写起来更清晰,也可能给SQL引擎更多优化的机会。

在你的情况下,你遇到的问题就是第二种情况。你试图把字符串Volumes/data/rc3/2/sdss/SDSS_r_0_0.fits当作一个值来使用。这样做其实是个表达式,像是在让sqlite把Volumes列除以data列,再除以rc3等等。如果你想把这个字符串当作字符串存储,就需要把它放在引号里。

不过,再次强调,不要试图通过加引号来解决这个问题;直接使用参数就可以了。

撰写回答