SQLite 主键自动增量不起作用
SQLite PRIMARY key AutoIncrement doesn't work
我正在尝试 table 具有自动递增的主键。包含 SQL 创建 table 的查询。
问题是自动增量不起作用。意思是当我插入一行 NULL 作为 conversation_id
的值时,它只是插入 null
。我在多个 table 上遇到这个问题。
-- Table: conversations
CREATE TABLE conversations (
conversation_id INTEGER (64) PRIMARY KEY
UNIQUE,
target_id BIGINT (64),
sender_id BIGINT (64),
status STRING (16) NOT NULL
DEFAULT unseen,
is_group INTEGER (1) NOT NULL
DEFAULT (0),
last_update INTEGER (32) DEFAULT (0),
target_name STRING (64),
target_photo STRING (256),
unread_count INTEGER (10) DEFAULT (0),
last_message STRING (256)
);
下面是我用来插入table的方法:
public Conversation addConversation(Conversation conversation) {
SQLiteDatabase db = getWritableDatabase();
ContentValues row = new ContentValues();
row.put("target_id", conversation.getTargetID());
row.put("sender_id", conversation.getSenderID());
row.put("target_name", conversation.getTargetName());
row.put("target_photo", conversation.getTargetPhoto());
row.put("status", conversation.getStatus());
row.put("unread_count", conversation.getUnreadCount());
row.put("last_message", conversation.getLastMessage());
conversation.setConversationID(db.insert(TBL_CONVERSATIONS, null, row));
Log.d(TAG, "conversation added: "+conversation.getConversationID());
db.close();
return conversation;
}
奇怪的是,当我从 insert
方法中检索插入 ID 时,它 returns 是正确的值,但实际的数据库字段为空。
如果我没理解错的话A column declared INTEGER PRIMARY KEY will autoincrement.
[Cite]
我只是在查询中添加了自动增量,它工作正常。
像这样
id integer primary key autoincrement
来自文档:
A table created using CREATE TABLE AS has no PRIMARY KEY and no
constraints of any kind. The default value of each column is NULL.
您不必在具有 PRIMARY KEY
约束的 COLUMN 上添加 UNIQUE
约束。
解释:
A UNIQUE constraint is similar to a PRIMARY KEY constraint, except
that a single table may have any number of UNIQUE constraints.
改为添加 NOT NULL
。
这就是为什么:
According to the SQL standard, PRIMARY KEY should always imply NOT
NULL. Unfortunately, due to a bug in some early versions, this is not
the case in SQLite. Unless the column is an INTEGER PRIMARY KEY or the
table is a WITHOUT ROWID table or the column is declared NOT NULL,
SQLite allows NULL values in a PRIMARY KEY column. SQLite could be
fixed to conform to the standard, but doing so might break legacy
applications. Hence, it has been decided to merely document the fact
that SQLite allowing NULLs in most PRIMARY KEY columns.
我建议使用此列定义:
CREATE TABLE conversations (
conversation_id INTEGER PRIMARY KEY NOT NULL AUTOINCREMENT,
...
}
您看到的 return 值很可能是该行的 ROWID
。 ROWID
是每个 table 中可用的隐藏列,除非明确删除。根据官方文档,当您定义 INTEGER PRIMARY KEY
时,它应该自动成为 ROWID
的别名。这也是为什么以这种方式定义列时不需要 AUTOINCREMENT
的原因。
With one exception noted below, if a rowid table has a primary key
that consists of a single column and the declared type of that column
is "INTEGER" in any mixture of upper and lower case, then the column
becomes an alias for the rowid. Such a column is usually referred to
as an "integer primary key". A PRIMARY KEY column only becomes an
integer primary key if the declared type name is exactly "INTEGER".
Other integer type names like "INT" or "BIGINT" or "SHORT INTEGER" or
"UNSIGNED INTEGER" causes the primary key column to behave as an
ordinary table column with integer affinity and a unique index, not as
an alias for the rowid.
您的专栏不是 INTEGER
,或者不是 PRIMARY KEY
。仔细查看您的创建语句,我可以看到一两个可能的罪魁祸首。
唯一键与主键
主键默认是唯一的。根据语法定义(您可以在与上述引用相同的文档页面上找到),您应该选择 PRIMARY KEY
或 UNIQUE
,而不是两者。
COLUMN 长度限制
ROWID
默认已经是 64 位了。您已指定长度 64,但未以位为单位指定长度。您可能在这里指定了一个 64 字节的整数,我确定这不是故意的。然而,这实际上应该不是问题,因为 SQLite ignores length-constraints。所以指定它们是没有意义的。
TLDR
替换此代码:
conversation_id INTEGER (64) PRIMARY KEY UNIQUE
有了这个:
conversation_id INTEGER PRIMARY KEY AUTOINCREMENT
我正在尝试 table 具有自动递增的主键。包含 SQL 创建 table 的查询。
问题是自动增量不起作用。意思是当我插入一行 NULL 作为 conversation_id
的值时,它只是插入 null
。我在多个 table 上遇到这个问题。
-- Table: conversations
CREATE TABLE conversations (
conversation_id INTEGER (64) PRIMARY KEY
UNIQUE,
target_id BIGINT (64),
sender_id BIGINT (64),
status STRING (16) NOT NULL
DEFAULT unseen,
is_group INTEGER (1) NOT NULL
DEFAULT (0),
last_update INTEGER (32) DEFAULT (0),
target_name STRING (64),
target_photo STRING (256),
unread_count INTEGER (10) DEFAULT (0),
last_message STRING (256)
);
下面是我用来插入table的方法:
public Conversation addConversation(Conversation conversation) {
SQLiteDatabase db = getWritableDatabase();
ContentValues row = new ContentValues();
row.put("target_id", conversation.getTargetID());
row.put("sender_id", conversation.getSenderID());
row.put("target_name", conversation.getTargetName());
row.put("target_photo", conversation.getTargetPhoto());
row.put("status", conversation.getStatus());
row.put("unread_count", conversation.getUnreadCount());
row.put("last_message", conversation.getLastMessage());
conversation.setConversationID(db.insert(TBL_CONVERSATIONS, null, row));
Log.d(TAG, "conversation added: "+conversation.getConversationID());
db.close();
return conversation;
}
奇怪的是,当我从 insert
方法中检索插入 ID 时,它 returns 是正确的值,但实际的数据库字段为空。
如果我没理解错的话A column declared INTEGER PRIMARY KEY will autoincrement.
[Cite]
我只是在查询中添加了自动增量,它工作正常。
像这样
id integer primary key autoincrement
来自文档:
A table created using CREATE TABLE AS has no PRIMARY KEY and no constraints of any kind. The default value of each column is NULL.
您不必在具有 PRIMARY KEY
约束的 COLUMN 上添加 UNIQUE
约束。
解释:
A UNIQUE constraint is similar to a PRIMARY KEY constraint, except that a single table may have any number of UNIQUE constraints.
改为添加 NOT NULL
。
这就是为什么:
According to the SQL standard, PRIMARY KEY should always imply NOT NULL. Unfortunately, due to a bug in some early versions, this is not the case in SQLite. Unless the column is an INTEGER PRIMARY KEY or the table is a WITHOUT ROWID table or the column is declared NOT NULL, SQLite allows NULL values in a PRIMARY KEY column. SQLite could be fixed to conform to the standard, but doing so might break legacy applications. Hence, it has been decided to merely document the fact that SQLite allowing NULLs in most PRIMARY KEY columns.
我建议使用此列定义:
CREATE TABLE conversations (
conversation_id INTEGER PRIMARY KEY NOT NULL AUTOINCREMENT,
...
}
您看到的 return 值很可能是该行的 ROWID
。 ROWID
是每个 table 中可用的隐藏列,除非明确删除。根据官方文档,当您定义 INTEGER PRIMARY KEY
时,它应该自动成为 ROWID
的别名。这也是为什么以这种方式定义列时不需要 AUTOINCREMENT
的原因。
With one exception noted below, if a rowid table has a primary key that consists of a single column and the declared type of that column is "INTEGER" in any mixture of upper and lower case, then the column becomes an alias for the rowid. Such a column is usually referred to as an "integer primary key". A PRIMARY KEY column only becomes an integer primary key if the declared type name is exactly "INTEGER". Other integer type names like "INT" or "BIGINT" or "SHORT INTEGER" or "UNSIGNED INTEGER" causes the primary key column to behave as an ordinary table column with integer affinity and a unique index, not as an alias for the rowid.
您的专栏不是 INTEGER
,或者不是 PRIMARY KEY
。仔细查看您的创建语句,我可以看到一两个可能的罪魁祸首。
唯一键与主键
主键默认是唯一的。根据语法定义(您可以在与上述引用相同的文档页面上找到),您应该选择 PRIMARY KEY
或 UNIQUE
,而不是两者。
COLUMN 长度限制
ROWID
默认已经是 64 位了。您已指定长度 64,但未以位为单位指定长度。您可能在这里指定了一个 64 字节的整数,我确定这不是故意的。然而,这实际上应该不是问题,因为 SQLite ignores length-constraints。所以指定它们是没有意义的。
TLDR
替换此代码:
conversation_id INTEGER (64) PRIMARY KEY UNIQUE
有了这个:
conversation_id INTEGER PRIMARY KEY AUTOINCREMENT