【问题标题】:Record cannot be inserted in table with Integer Primary Key field无法在具有整数主键字段的表中插入记录
【发布时间】:2012-08-04 13:16:18
【问题描述】:

我在 SQLite 数据库中有一个表,其 ID 字段为 integer primary key(因此为 autoincremented )。我有以下查询要在表中插入记录。

INSERT INTO users(fname, lname, email, password) VALUES('Foo','Bar','foo@bar.com','12345');

虽然省略了第一个字段u_id。这个查询在终端上运行良好,我可以插入记录,但是从 Java 中这样做会抛出 SQLException 和消息 users.u_id may not be NULL。我正在使用PreparedStatement 进行以下查询:

INSERT INTO users(fname, lname, email, password) VALUES(?,?,?,?)

我在这里做错了什么?

注意: 我正在使用带有 JDBC 驱动程序 SQLiteJDBC 的 SQLite 3(该站点已关闭,但我之前确实下载了 jar 文件)。跟司机有关系吗?

更新:

这是抛出异常的堆栈跟踪:

java.sql.SQLException: users.u_id may not be NULL
at org.sqlite.DB.execute(DB.java:275)
at org.sqlite.DB.executeUpdate(DB.java:281)
at org.sqlite.PrepStmt.executeUpdate(PrepStmt.java:77)
at com.paperfood.DatabaseManager.insertUser(DatabaseManager.java:64)
at com.paperfood.controller.RegisterUser.doPost(RegisterUser.java:62)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)

以下是我的记录插入 Java 代码:

PreparedStatement pst = con.prepareStatement("INSERT INTO users(fname, lname, email, password) VALUES(?,?,?,?)");
pst.setString(1, user.getFirstName());
pst.setString(2, user.getLastName());
pst.setString(3, user.getEmail());
pst.setString(4, user.getPassword());
pst.executeUpdate();

其中,user 是实体类的对象,其字段映射到表字段。另外,请注意,我的控制器(RegisterUser servlet)使用DatabaseManager 类插入记录,DatabaseManager 类具有方法insertUser(),它接受User 类的实体类对象的参数。

以下是创建表users的SQL:

CREATE TABLE users(
    u_id integer PRIMARY KEY,
    fname varchar(30),
    lname varchar(30),
    email varchar(30),
    password varchar(32)
);

【问题讨论】:

  • 发布带有错误代码的完整堆栈跟踪
  • 请在您创建查询并尝试插入的地方发布一些相关的 java 代码
  • 如果您使用 pst.execute(); 而不是 pst.executeUpdate(); 是否有效?此外,您设置的userStrings 究竟是什么?也许它们包含 sql 关键字。
  • 也不适用于execute()user 中的字符串是常用名称,不包含任何 SQL 关键字。
  • 尝试在 create 语句中将NOT NULL 添加到您的主键。

标签: java jdbc sqlite sqlexception


【解决方案1】:

你可以试试这个。

PreparedStatement pst = con.prepareStatement("INSERT INTO users(u_id, fname, lname, email, password) VALUES(?,?,?,?,?)");

pst.setString(1, null);
pst.setString(2, user.getFirstName());
pst.setString(3, user.getLastName());
pst.setString(4, user.getEmail());
pst.setString(5, user.getPassword());

根据this,将其设置为 null 应该可以。

如果插入时没有指定 ROWID,或者指定的 ROWID 的值为 NULL,则会自动创建适当的 ROWID。

我不确定为什么您的代码不起作用,尽管根据上述语句的第一部分它是正确的。

编辑:

刚刚遇到this。请检查您是否在代码中指向正确的数据库。

【讨论】:

  • 试过了,得到同样的异常。 (顺便说一句,SQL 查询中有 6 个问号,而不是 5 个)。
  • 在我的 SQLiteDB 文件上运行命令 .databases,并且只有 main 数据库和 users 表,我怎样才能确保我在主数据库中指向这个表?
  • 酷,如果表错误,那么,它会说表不存在。另外,刚刚经历了这么长时间的讨论experts-exchange.com/Database/Miscellaneous/Q_27506454.html,同样的jdbcdriver,他终于通过自己插入主键来插入,现在更想知道这是怎么回事!
  • 由于它在命令行和其他网站上的相关讨论中工作,我得出的结论是潜水员很糟糕,你可以试试这个xerial.org/trac/Xerial/wiki/SQLiteJDBC :)
  • 我使用的是 3.7.2 版本,并且该版本没有任何问题。
【解决方案2】:

你当前的主键不是自增的,所以你需要自己指定主键的值。如果希望主键自增,需要明确指定。

请参阅:http://www.sqlite.org/autoinc.html 您的表定义需要:

CREATE TABLE users(
    u_id integer PRIMARY KEY AUTOINCREMENT,
    fname varchar(30),
    lname varchar(30),
    email varchar(30),
    password varchar(32)
);

【讨论】:

  • 我也是这么想的。我总是使用AUTOINCREMENT 关键字,但在阅读了您提供的链接后,我不确定,INTEGER PRIMARY KEY 是必要的。文中说,添加AUTOINCREMENT 将改变用于生成密钥的算法,但即使没有AUTOINCREMENT,每一行都会自动获得其唯一ID。
  • 我尝试了完全相同的表创建查询,但仍然无法解决问题。
  • @Kush 您是否尝试创建一个新的最小项目只是为了测试驱动程序和 sql 语句?
猜你喜欢
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 2019-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-17
相关资源
最近更新 更多