使用Java JDBC查询满足SQLite约束

时间:2017-03-02 17:18:56

标签: java sqlite jdbc

我有一个SQLite数据库,其中有一个表" Transactions"包含一个ID字段,它是一个主键并自动增加。

CREATE TABLE transactions (
  id        int AUTO_INCREMENT not null,
  time      DATETIME not null,
  buyer         varchar(320) not null,
  seller        varchar(320) not null,
  price         float not null,
  size      int not null,
  currency  char(3) not null,
  symbol        varchar(10) not null,
  primary key (id)
);

我创建了一个Java类来处理SQL查询。

            try {
                PreparedStatement pStmt = db.getConnection().prepareStatement(
                        "INSERT INTO transactions( id, time, buyer, seller, price, size, currency, symbol ) " +
                                "VALUES ( ?, ?, ?, ?, ?, ?, ?, ? )"
                );

                java.util.Date uDate = sdf.parse( curLine[0] );

                try {

                    pStmt.setLong( 2, uDate.getTime() );
                    pStmt.setString( 3, curLine[1] );
                    pStmt.setString( 4, curLine[2] );
                    pStmt.setFloat( 5, Float.parseFloat( curLine[3] ) );
                    pStmt.setInt( 6, Integer.parseInt( curLine[4] ) );
                    pStmt.setString( 7, curLine[5] );
                    pStmt.setString( 8, curLine[6] );

                    pStmt.executeUpdate();

                } catch( SQLException e ) {
                    e.printStackTrace();
                }

            } catch ( SQLException e ) {
                e.printStackTrace();
            }

curLine是从CSV文件解析的值数组。

在运行时,我有以下错误

  

org.sqlite.SQLiteException:[SQLITE_CONSTRAINT_NOTNULL] NOT NULL约束失败(NOT NULL约束失败:transactions.id)

我不知道如何处理它。

我尝试了其他几种配置:

  • 不要表示" id" sql查询中的字段。
  • 将0值赋予" id"。

但是这些配置中的每一个都会引发错误。

2 个答案:

答案 0 :(得分:4)

从insert语句中删除id,让sql有机会使用自己的进程自动增加:

"INSERT INTO transactions( time, buyer, seller, price, size, currency, symbol ) " +
                            "VALUES ( ?, ?, ?, ?, ?, ?, ? )"

编辑1

请使用符合SQLite的语法创建表:

sqlite> CREATE TABLE t2 ( id INTEGER PRIMARY KEY AUTOINCREMENT, size INTEGER NOT NULL);
sqlite> INSERT INTO t2 ( size) VALUES (123);
sqlite> INSERT INTO t2 ( size) VALUES (456);
sqlite> SELECT * FROM t2;
1|123
2|456

答案 1 :(得分:1)

@ bc004346答案是对的。我在这里添加一些细节。

这证明了你遇到的问题:

sqlite> create table a (id int AUTO_INCREMENT not null, v varchar(5));
sqlite> insert into a (v) values ('a');
Error: NOT NULL constraint failed: a.id
sqlite> drop table a;
sqlite> create table a (id integer PRIMARY KEY AUTOINCREMENT, v varchar(5));
sqlite> insert into a (v) values ('a');
sqlite> select * from a;
1|a

您遇到的问题是由sqlite中types work的方式引起的。类型与值本身无关,而与列无关。因为create table中的column这个typename的含义很少,甚至可以完全省略。

这是sqlite中的有效表定义:

create table a(x, y);

您可以将任何标记序列基本指定为类型名称:

sqlite> create table e (id int xxxx xxx not null, v varchar(5));
sqlite> create table f (id int xxxx xxx yyyy not null, v varchar(5));
sqlite> create table g (id inteeeee xxxx xxx yyyy not null, v varchar(5));
sqlite> create table h (id what ever you want not null, v varchar(5));

考虑到这一点,您可以看到为表transactions指定的定义无法按预期方式工作,即列ID不是自动增量列,并被视为具有not null约束的常规列。如果没有在insert语句中为其指定值,则会出现约束违规。

要解决此问题,您需要使用正确的语法来创建AUTOINCREMENT字段或手动生成id列值并在插入期间设置它。