在sqlite3的数据类型错字但仍然有效,为什么?

时间:2013-05-28 09:17:35

标签: python sql sqlite

在编写schema.sql时,我在sqlite3的数据类型中输入了拼写错误:


create table xxx(
    id integer primary key autoincrement not null,
    num integet
)

正如您所看到的,integet应该是integer,但它仍然有效,这意味着我可以将数据插入其中。为什么?如何在不中断数据库的情况下将其更正为integer

2 个答案:

答案 0 :(得分:1)

正如the Python sqlite3 modulethe 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,而不是将它们保留为bytesstr

答案 1 :(得分:0)

SQLite宽容到了愚蠢的地步。您可以创建“wibble”类型的列。此CREATE TABLE语句适用于SQLite。

create table wibble (wibble wibble);

你也可以插入它。

insert into wibble values ('wibble');