sqlite3.OperationalError: 没有这个列:

19

这是一个非常基础的问题,我知道这段代码存在安全问题,应该使用参数化条目等其他问题 - 这是一个正在进行的工作。 我试图构建一个用户注册模块,已经设置了一个表格,第一列作为一个带有主键约束的ID,但是当我运行代码时,我遇到了以下错误,不确定为什么 -(如果与p_ID列有关):

Traceback (most recent call last):
  File "user.py", line 72, in <module>
    userSignUp()
  File "user.py", line 68, in userSignUp
    c.execute("INSERT INTO People VALUES(userName, password, confirmPassword,   firstName,lastName, companyName, email, phoneNumber,addressLine1, addressLine2, addressLine3, zipCode, province, country, regDate)")
sqlite3.OperationalError: no such column: userName

代码是:

import sqlite3
import datetime


path = "/Users/workhorse/thinkful/"
db = "apartment.db"

def checkAndCreateDB():
    #not checking for some reason
    #fullPath = os.path.join(path, db)
    #if os.path.exists(fullPath):
    #   print "Database Exists"
    #else:
    connection = sqlite3.connect(db)
    print "Creating database"
    createUserRegTable()

def createUserRegTable():
    with sqlite3.connect(db) as connection:
        c = connection.cursor()
        c.execute("""CREATE TABLE People
        (p_ID INTEGER PRIMARY KEY AUTOINCREMENT,
        userName TEXT NOT NULL UNIQUE,
        password TEXT NOT NULL,
        confirmPassword TEXT NOT NULL,
        firstName TEXT NOT NULL,
        lastName TEXT NOT NULL,
        companyName TEXT NOT NULL,
        email TEXT NOT NULL UNIQUE,
        phoneNumber TEXT NOT NULL,
        addressLine1 TEXT NOT NULL,
        addressLine2 TEXT,
        addressLine3 TEXT,
        zipCode TEXT NOT NULL,
        province TEXT NOT NULL,
        country TEXT NOT NULL,
        regDate DATE NOT NULL)
        """)
        print "table made"


def userSignIn():
    pass

def userSignUp():
    userName = raw_input("Enter a user name: ")
    password = raw_input("Enter a password: ")
    confirmPassword = raw_input("Confirm Your Password: ")
    firstName = raw_input("Enter your first name: ")
    lastName = raw_input("Enter your last name: ")
    companyName = raw_input("Enter your company name: ")
    email = raw_input("Enter your email: ")
    phoneNumber = raw_input("Enter your phone number: ")
    addressLine1 = raw_input("Enter your address: ")
    addressLine2 = raw_input("Enter second line of your address (Not Required): ")
    addressLine3 = raw_input("Enter third line of your address (Not Required): ")
    zipCode = raw_input("Enter your zip code: ")
    province = raw_input("Enter your state or province: ")
    country = raw_input("Enter your country: ")
    regDate = datetime.date.today()
    print regDate

    #userInfo = (userName, password, confirmPassword, firstName,lastName, companyName, email, phoneNumber,addressLine1,
    #addressLine2, addressLine3, zipCode, province, country, regDate)

    with sqlite3.connect(db) as connection:
        c = connection.cursor()
        c.execute("INSERT INTO People VALUES(userName, password, confirmPassword, firstName,lastName, companyName, email, phoneNumber,addressLine1, addressLine2, addressLine3, zipCode, province, country, regDate)")

checkAndCreateDB()

userSignUp()

非常感谢

4个回答

37

如果您想要将Python值插入SQL数据库中,仅在SQL语句中命名Python变量是不够的。SQL数据库认为您要插入来自表格或其他查询的值。

相反,请使用SQL参数,并传入实际的值:

params = (userName, password, confirmPassword, firstName, lastName,
          companyName, email, phoneNumber, addressLine1, addressLine2, 
          addressLine3, zipCode, province, country, regDate)

c.execute("INSERT INTO People VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", params)

NULL值用于p_ID主键列;另一种选择是命名您想要为其插入值的所有列,或将 None 作为附加参数的值传入。


如上所述,另一种方法是使用INSERT INTO People (userName, password, confirmPassword, <要插入值的所有列名>) VALUES (?, ?, <与您拥有值相同的问号数量>)。但这会变得有点冗长。使用NULL让SQLite代替插入默认值更容易。 - Martijn Pieters
@MartijnPieters 在那里为您制作变量的<与您拥有的值一样多的问号>,例如可能是从len(params)? - taiko
2
@taiko 当然,那只是字符串格式化;使用','.join(['?'] * len(params)将结果插入到您的查询字符串中。 - Martijn Pieters
1
@MartijnPieters :) 哦,当然,看不到树木的森林。非常感谢你。 - taiko
在最后,ID(主键)列会发生什么? 它会自动增加还是接收NULL值? - Simao
1
@Simao 使用 NULL 表示 SQLite 将自动递增。请参阅 SQLite 自动递增文档如果在插入时未指定 ROWID,或者指定的 ROWID 值为 NULL,则会自动创建一个适当的 ROWID。 - Martijn Pieters

5

实际上这是一个小错误,你需要像这样编辑:

c.execute("INSERT INTO People VALUES('userName', 'password', 'confirmPassword', 'firstName','lastName', 'companyName', 'email', phoneNumber,'addressLine1', 'addressLine2', 'addressLine3', zipCode, 'province', 'country', 'regDate')")

我希望你理解了


我更喜欢使用这种方法,而不是使用“?”来避免列移动的情况。然而,当我使用具有自增属性的列时,出现了问题,错误提示表格的列数多于我提供的值。 - colk84
1
为了解决这个问题,我使用了c.execute("INSERT INTO table('col1', 'col2', 'col4') VALUES(?,?,?)", (var1, var2, var3)) - colk84

1

Martijn的回答很好,但仅适用于您知道某个值将为NULL的情况。但是,如果任何变量都可能为NULL,则我使用了稍微不同的实现。

将任何变量设置为None。如果浏览数据库,该值将为空,并且在Python控制台中显示为None,因为它们是等价的。

请参阅文档中的第11.13.5.1节(https://docs.python.org/2/library/sqlite3.html):

Python类型None = SQLite类型NULL


0
我实际上找到了一种非常简单的方法来解决这个问题! 不使用“?”作为占位符或参数关键字... 只需在引号前面传入“f”,将您的字符串变成“格式化”字符串。但请注意,这不是一个好的做法,只是一个快捷方式,如果您不打算发布此应用程序。 这允许您在放置“{}”时传递变量。
cur = connection.cursor()
        cur.execute(f"INSERT INTO bills VALUES ({bills})")
        connection.commit()
        connection.close()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接