在编写schema.sql
时,我在sqlite3的数据类型中输入了拼写错误:
create table xxx(
id integer primary key autoincrement not null,
num integet
)
正如您所看到的,integet
应该是integer
,但它仍然有效,这意味着我可以将数据插入其中。为什么?如何在不中断数据库的情况下将其更正为integer
?
答案 0 :(得分:1)
正如the Python sqlite3
module和the database itself的文档都解释的那样,sqlite3是无类型的。您可以将字符串值插入INTEGER
列,或将整数值插入VARCHAR
列。
然而,sqlite有一个名为“列亲和力”的功能,如果列类型是INTEGER等,它会尝试以数字方式处理参数。然后Python模块尝试将每个sqlite类型映射到Python类型,所以如果sqlite为它提供了一个INTEGER列,Python会将它映射为整数类型。
正如各自的文件所述:
如果声明的类型包含字符串“INT”,则为其分配INTEGER affinity。
INTEGER int或long,具体取决于大小
比较不区分大小写。任何与任何规则都不匹配的内容都将被视为NUMERIC
,Python会将其视为str
/ bytes
/ buffer
(具体取决于您的版本)。
因此,对于sqlite本身,integet
匹配INTEGER
的规则,因此,您可以存储整数值并将其作为整数检索。 (当然你还可以存储'abc'
,然后你会把它作为一个字符串取回来。)而且Python会把它看作INTEGER
列,因此读取值为int
如果可能的话。
至于你问题的最后一部分,sqlite3没有提供任何方法来在创建列后更改列的类型。实际上,ALTER TABLE
命令只允许添加新列或约束,或重命名表。
如果您需要修改实时数据库,您需要做的是创建一个包含正确列的新表,复制所有内容,删除旧表,并重命名新表,如下所示:
CREATE TABLE yyy(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, num INTEGER)
INSERT INTO yyy SELECT * FROM xxx
DROP TABLE xxx
ALTER TABLE yyy RENAME TO xxx
您在旧表中插入的任何字符串值都将被复制 - 以及随后每次获取它们时,因为列类型为INTEGER
,如果可能,Python将尝试转换为int
,而不是将它们保留为bytes
或str
。
答案 1 :(得分:0)
SQLite宽容到了愚蠢的地步。您可以创建“wibble”类型的列。此CREATE TABLE语句适用于SQLite。
create table wibble (wibble wibble);
你也可以插入它。
insert into wibble values ('wibble');