【问题标题】:How flexible/restricive are SQLite column types?SQLite 列类型的灵活性/限制性如何?
【发布时间】:2017-08-08 08:09:38
【问题描述】:

最近,关于 SQLite 中列类型的灵活性存在一些争论。因此问题是,SQLite 列类型有多灵活?

一个论点是类型仅限于主要的五种,即 TEXT、NUMERIC、INTEGER、REAL 和 BLOB,以及官方文档中的命名列类型,即:-

INT, TINYINT, SMALLINT, MEDIUMINT, BIGINT, UNSIGNED BIG INT, INT2, INT8, CHARACTER(20), VARCHAR(255), VARYING CHARACTER(255), NCHAR(55), NATIVE CHARACTER(70), NVARCHAR(100), CLOB, no datatype specified (BLOB), DOUBLE, DOUBLE PRECISION, FLOAT, DECIMAL(10,5), BOOLEAN, DATE & DATETIME.

3.1.1. Affinity Name Examples

另一个论点是该列表是一个示例列表,并且列类型更加灵活,5 条规则(如下)几乎被普遍应用。

3.1。柱亲和性的测定

列的亲和性由声明的类型决定 列,按以下规则显示的顺序:

1) 如果声明的类型包含字符串“INT”,则为其分配 INTEGER 亲和性。

2) 如果列的声明类型包含任何字符串“CHAR”、“CLOB”或“TEXT”,则该列具有 TEXT 关联。注意 类型 VARCHAR 包含字符串“CHAR”,因此被分配 TEXT 亲和力。

3) 如果为列声明的类型包含字符串“BLOB”,或者如果未指定类型,则该列具有亲和性 BLOB。

4) 如果为列声明的类型包含任何字符串“REAL”、“FLOA”或“DOUB”,则该列具有 REAL 亲和性。

5) 否则,亲和度为 NUMERIC。

请注意,确定列亲和性的规则的顺序是 重要的。声明类型为“CHARINT”的列将同时匹配 规则 1 和 2,但第一个规则优先,因此该列 亲和力将是整数。

3.1. Determination Of Column Affinity

那么 SQLite 列类型的进出/对错是什么?

【问题讨论】:

    标签: android-sqlite


    【解决方案1】:

    SQLite 列类型是灵活的(动态的),主要是为了迎合其他数据库管理系统使用的刚性列类型的采用/适应。

    注意!这个 Asnwer 不推荐使用奇怪而美妙的列类型。

    1) 实际上,您几乎可以为列类型使用任何名称,但是存在一些限制。

    2) 列类型是列定义中的第二个值,例如CREATE TABLE table (columnname columntype .....,....),尽管它可能会被有意或无意地省略 注意见 5a)

    3) 第一个限制是mycolumnINTEGER PRIMARY KEYmycolumnINTEGER PRIMARY KEY AUTOINCREMENT 是一种特殊的列类型。该列是 rowid 的别名,它是唯一的数字标识符(AUTOINCREMENT 强制规定 rowid 必须大于上次使用的表的 rowid 例如,如果一行使用 id (9223372036854775807),那么任何后续添加行的尝试都将导致 SQLITE FULL 错误。)。 SQLite Autoincrement

    4) 其他限制是列类型不能混淆 SQLite 解析器。例如,PRIMARY、TABLE、INDEX 列类型将导致 SQLite 异常(语法错误(代码 1)),例如当使用 INDEX 列类型时:-

    android.database.sqlite.SQLiteException: near "INDEX": syntax error (code 1):
    

    发生。

    5) 列类型不是强制性的,例如 CREATE TABLE mytable (...,PRIMARY_COL,.... 在这种情况下 PRAGMA TABLE_INFO(tablename) 将不显示任何类型,例如(第 3 行)。

    08-08 07:56:23.391 13097-13097/? D/TBL_INFO: Col=cid Value=8
    08-08 07:56:23.391 13097-13097/? D/ TBLINFO: Col=name Value=PRIMARY_COL
    08-08 07:56:23.391 13097-13097/? D/ TBLINFO: Col=type Value=
    08-08 07:56:23.391 13097-13097/? D/ TBLINFO: Col=notnull Value=1
    08-08 07:56:23.391 13097-13097/? D/ TBLINFO: Col=dflt_value Value=null
    08-08 07:56:23.391 13097-13097/? D/ TBLINFO: Col=pk Value=0
    

    5a) 在某些情况下,SQLite 解析器会跳到有效的关键字,例如CREATE TABLE mytable (mycolumn NOT NULL,... 导致 NOT NULL 被用来表示 NOT NULL 列,而 type 被视为 no type (上面的 table_info 实际上来自这样的用法) .

    6) 类型不限于单个单词,例如VARYING CHARACTER(255)THE BIG BAD WOLF 可以指定为从 table_info 提取中可以看出的类型:-

    08-08 08:23:26.423 4799-4799/? D/   TBLINFO: Col=type Value=THE BIG BAD WOLF
    

    在 SQLite 中使用非标准列类型的原因!

    简而言之,没有原因,正如开头所述,列类型的灵活性似乎主要是为了迎合从其他数据库管理系统轻松适应 SQL。

    列类型本身几乎没有影响,因为数据将根据 SQLite 确定的要使用的存储类进行存储。除了rowid(参见上面的3))任何列都可以保存任何类型的值。

    除了存储为 Blob 的数据,必须使用 cursor.getBlob 检索,并且 cursor.getBlob 不能用于未存储为 BLOB 的数据(getBlob 不会因为存储为 TEXT 的数据而失败),您可以使用任何cursor.get???? 方法非常多地检索数据(不一定有用)。

    这里有一些例子:-

    对于添加了数据 long myINT = 556677888; 的列(通过 ContentValues,例如 cv1.put(columnanme,myINT));

    然后:-

    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: Column=INTEGER_COL<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS INT >>556677888<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS LONG >>556677888<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS STRING >>556677888<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS DOUBLE >>5.56677888E8<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS FLOAT >>5.566779E8<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS SHORT >>15104<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:      Unable to handle with getBlob.
    

    getShort 不返回存储值,getBlob 无法获取存储值。

    对于Double myREAL = 213456789.4528791134567890109643534276;:-

    08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes: Column=REAL_COL<<
    08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS INT >>213456789<<
    08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS LONG >>213456789<<
    08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS STRING >>2.13457e+08<<
    08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS DOUBLE >>2.134567894528791E8<<
    08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS FLOAT >>2.1345678E8<<
    08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS SHORT >>6037<<
    08-08 09:19:03.658 13575-13575/mjt.soqanda D/ColTypes:      Unable to handle with getBlob.
    

    对于String myTEXT = "The Lazy Quick Brown Fox Jumped Over the Fence or something like that.";

    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes: Column=TEXT_COL<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS INT >>0<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS LONG >>0<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS STRING >>The Lazy Quick Brown Fox Jumped Over the Fence or something like that.<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS DOUBLE >>0.0<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS FLOAT >>0.0<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS SHORT >>0<<
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS BLOB >>[B@2f9e811e<<
    

    这是一个非常荒谬的例子,列类型为my_char_is_not_a_char_but_an_int,根据PRAGMA TABLE_INFO:-

    08-08 09:19:03.657 13575-13575/mjt.soqanda D/TBL_INFO: Col=cid Value=7
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/   TBLINFO: Col=name Value=my_char_is_not_a_char_but_an_int_COL
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/   TBLINFO: Col=type Value=my_char_is_not_a_char_but_an_int
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/   TBLINFO: Col=notnull Value=0
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/   TBLINFO: Col=dflt_value Value=null
    08-08 09:19:03.657 13575-13575/mjt.soqanda D/   TBLINFO: Col=pk Value=0
    

    结果(按上面的“双”存储)是:-

    08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes: Column=my_char_is_not_a_char_but_an_int_COL<<
    08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS INT >>213456789<<
    08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS LONG >>213456789<<
    08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS STRING >>2.13457e+08<<
    08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS DOUBLE >>2.134567894528791E8<<
    08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS FLOAT >>2.1345678E8<<
    08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes:  VALUE AS SHORT >>6037<<
    08-08 09:19:03.659 13575-13575/mjt.soqanda D/ColTypes:      Unable to handle with getBlob.
    

    以上内容基于以下几点:- Datatypes In SQLite Version 3 SQLite Autoincrement PRAGMA Statements

    代码在运行 API22 的 GenyMotion 模拟设备上测试/运行,最低版本为 14,目标为 26。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-03
      • 1970-01-01
      • 1970-01-01
      • 2022-08-17
      • 2012-02-14
      相关资源
      最近更新 更多