在线文档教程
Sqlite
其他 | Miscellaneous

SQLite Frequently Asked Questions

SQLite Frequently Asked Questions

Frequently Asked Questions

  • 我如何创建一个AUTOINCREMENT字段?

  • SQLite支持哪些数据类型?

  • SQLite允许我将一个字符串插入到integer类型的数据库列中!

  • 为什么SQLite不允许我在同一个表的两个不同行上使用'0'和'0.0'作为主键?

  • 多个应用程序或同一应用程序的多个实例可以同时访问单个数据库文件吗?

  • SQLite线程安全吗?

  • 如何列出SQLite数据库中包含的所有表/索引

  • SQLite数据库是否有任何已知的大小限制?

  • SQLite中VARCHAR的最大大小是多少?

  • SQLite是否支持BLOB类型?

  • 如何在SQLite的现有表中添加或删除列。

  • 我删除了很多数据,但数据库文件没有变小。这是一个错误?

  • 我可以在商业产品中使用SQLite而无需支付版税?

  • 如何使用包含嵌入式单引号(')字符的字符串文字?

  • 什么是SQLITE_SCHEMA错误,为什么我会得到一个?

  • 为什么ROUND(9.95,1)会返回9.9而不是10.0?不应该9.95?

  • 编译SQLite时会出现一些编译警告。这不是问题吗?它不代表糟糕的代码质量吗?

  • Unicode字符不区分大小写的匹配不起作用。

  • INSERT非常慢 - 我只能每秒执行几十个INSERT

  • 我不小心删除了我的SQLite数据库中的一些重要信息。我怎样才能恢复它?

  • 什么是SQLITE_CORRUPT错误?数据库“畸形”意味着什么?为什么我得到这个错误?

  • SQLite是否支持外键?

  • I get a compiler error if I use the SQLITE_OMIT_... compile-time options when building SQLite.

  • 我的WHERE子句表达式column1="column1"不起作用。它会导致返回表的每一行,而不仅仅是column1的值为“column1”的行。

  • SQLite的语法图(又名“铁路”图)如何生成?

  • SQL标准要求强制使用UNIQUE约束,即使约束中的一个或多个列为NULL,但SQLite不会执行此操作。这不是一个错误?

  • 什么是SQLite的出口管制分类号码(ECCN)?

  • 我的查询不会返回我期望的列名称。这是一个错误?

(1)如何创建AUTOINCREMENT字段?

简短回答:声明INTEGER PRIMARY KEY的列将自动增加。较长的答案:如果您声明表的列为INTEGER PRIMARY KEY,那么无论何时将NULL插入到该表的该列中,NULL都会自动转换为一个大于该列上最大值的整数表中的所有其他行,如果表为空,则为1。或者,如果最大的现有整数密钥9223372036854775807正在使用中,则随机选择未使用的密钥值。例如,假设您有这样的表:CREATE TABLE t1(INTEGER PRIMARY KEY,b INTEGER 用这张表,INSERT INTO t1 VALUES(NULL,123 在逻辑上相当于说:INSERT INTO t1 VALUES((SELECT max(a)FROM t1)+1,123 有一个名为sqlite3_last_insert_rowid()的函数,它将返回最近插入操作的整数键。请注意,整数键比插入前表中最大的键大1。新密钥对于当前表中的所有密钥都是唯一的,但它可能与之前从表中删除的密钥重叠。要创建在表的生命周期内唯一的键,请将AUTOINCREMENT关键字添加到INTEGER PRIMARY KEY声明中。那么所选择的关键将比该表中曾经存在的最大关键要多一个。如果该表中以前存在最大可能的键,那么INSERT将失败并显示SQLITE_FULL错误代码。请注意,整数键比插入前表中最大的键大1。新密钥对于当前表中的所有密钥都是唯一的,但它可能与之前从表中删除的密钥重叠。要创建在表的生命周期内唯一的键,请将AUTOINCREMENT关键字添加到INTEGER PRIMARY KEY声明中。那么所选择的关键将比该表中曾经存在的最大关键要多一个。如果该表中以前存在最大可能的键,那么INSERT将失败并显示SQLITE_FULL错误代码。请注意,整数键比插入前表中最大的键大1。新密钥对于当前表中的所有密钥都是唯一的,但它可能与之前从表中删除的密钥重叠。要创建在表的生命周期内唯一的键,请将AUTOINCREMENT关键字添加到INTEGER PRIMARY KEY声明中。那么所选择的关键将比该表中曾经存在的最大关键要多一个。如果该表中以前存在最大可能的键,那么INSERT将失败并显示SQLITE_FULL错误代码。将AUTOINCREMENT关键字添加到INTEGER PRIMARY KEY声明中。那么所选择的关键将比该表中曾经存在的最大关键要多一个。如果该表中以前存在最大可能的键,那么INSERT将失败并显示SQLITE_FULL错误代码。将AUTOINCREMENT关键字添加到INTEGER PRIMARY KEY声明中。那么所选择的关键将比该表中曾经存在的最大关键要多一个。如果该表中以前存在最大可能的键,那么INSERT将失败并显示SQLITE_FULL错误代码。

(2) What datatypes does SQLite support?

SQLite使用动态类型。内容可以存储为INTEGER,REAL,TEXT,BLOB或NULL。

(3)SQLite允许我将一个字符串插入到integer类型的数据库列中!

这是一个功能,而不是一个错误。SQLite使用动态类型。它不强制数据类型约束。任何类型的数据都可以(通常)插入到任何列中。您可以将任意长度的字符串放入整数列,布尔列中的浮点数或字符列中的日期。您在CREATE TABLE命令中分配给列的数据类型不限制可将哪些数据放入该列。每列可以容纳任意长度的字符串。(有一个例外:INTEGER PRIMARY KEY类型的列只能包含一个64位的有符号整数,如果您尝试将除INTEGER PRIMARY KEY列之外的其他任何内容放入INTEGER PRIMARY KEY列,则会导致错误。)但SQLite确实使用声明列的类型作为您偏好该格式的值的提示。所以,例如,如果列的类型为INTEGER,并且您尝试向该列中插入字符串,则SQLite将尝试将该字符串转换为整数。如果可以,它会插入整数。如果不是,则插入字符串。该功能称为类型亲和力。

(4)为什么SQLite不允许我在同一个表的两个不同行上使用'0'和'0.0'作为主键?

当您的主键是数字类型时,会出现此问题。将主键的数据类型更改为TEXT,它应该可以工作。每一行都必须有一个唯一的主键。对于具有数字类型的列,SQLite认为'0'和'0.0'是相同的值,因为它们在数值上彼此相等。(请参阅上一个问题。)因此,这些值不是唯一的。

(5)同一应用程序的多个应用程序或多个实例可以同时访问单个数据库文件吗?

多个进程可以同时打开同一个数据库。多个进程可以同时做一个SELECT。但是,只有一个过程可以随时对数据库进行更改。SQLite使用读写器锁来控制对数据库的访问。(在Win95 / 98 / ME下,缺少对读/写锁的支持,而是使用概率模拟。)但要小心:如果数据库文件保存在NFS文件系统上,则此锁定机制可能无法正常工作。这是因为在许多NFS实现中fcntl()文件锁定被破坏。如果多个进程可能试图同时访问文件,则应避免将NFS数据库文件放在NFS上。在Windows上,Microsoft的文档说如果你没有运行Share.exe守护进程,锁定可能无法在FAT文件系统下工作。对Windows有很多经验的人告诉我,网络文件的文件锁定非常麻烦并且不可靠。如果他们说的是真的,在两台或多台Windows机器之间共享SQLite数据库可能会导致意想不到的问题。我们知道没有其他人嵌入式SQL数据库引擎,它支持与SQLite一样多的并发性。SQLite允许多个进程一次打开数据库文件,并允许多个进程一次读取数据库。当任何进程想要写入时,它必须在更新期间锁定整个数据库文件。但通常只需要几毫秒。其他流程只需等待作者完成,然后继续他们的业务。其他嵌入式SQL数据库引擎通常只允许单个进程一次连接到数据库。但是,客户端/服务器数据库引擎(如PostgreSQL,MySQL或Oracle)通常支持更高级别的并发,并允许多个进程同时写入同一数据库。这在客户端/服务器数据库中是可行的,因为总是有一个可以协调访问的良好控制的服务器进程。如果您的应用程序需要大量的并发性,那么您应该考虑使用客户端/服务器数据库。但是经验表明,大多数应用程序所需要的并发性比设计者想象的要少得多。当SQLite试图访问被另一个进程锁定的文件时,默认行为是返回SQLITE_BUSY。您可以使用sqlite3_busy_handler()或sqlite3_busy_timeout() API函数从C代码调整此行为。当SQLite试图访问被另一个进程锁定的文件时,默认行为是返回SQLITE_BUSY。您可以使用sqlite3_busy_handler()或sqlite3_busy_timeout()API函数从C代码调整此行为。当SQLite试图访问被另一个进程锁定的文件时,默认行为是返回SQLITE_BUSY。您可以使用sqlite3_busy_handler()或sqlite3_busy_timeout()API函数从C代码调整此行为。

(6) Is SQLite threadsafe?

线程是邪恶的。避免它们。SQLite是线程安全的。我们做出这个让步,因为许多用户选择忽略前一段给出的建议。但为了保证线程安全,必须使用SQLITE_THREADSAFE预处理器宏将其设置为1来编译SQLite。分发中的Windows和Linux预编译二进制文件都是以这种方式编译的。如果您不确定您链接的SQLite库是否已编译为线程安全,则可以调用sqlite3_threadsafe()接口来查找。SQLite是线程安全的,因为它使用互斥体来序列化对公共数据结构的访问。但是,获取和释放这些互斥锁的工作将稍微减慢SQLite的速度。因此,如果您不需要SQLite进行线程安全,则应该禁用互斥锁以获得最佳性能。有关其他信息,请参阅线程模式文档。

(7)如何列出SQLite数据库中包含的所有表/索引

If you are running the sqlite3 command-line access program you can type ".tables" to get a list of all tables. Or you can type ".schema" to see the complete database schema including all tables and indices. Either of these commands can be followed by a LIKE pattern that will restrict the tables that are displayed. From within a C/C++ program (or a script using Tcl/Ruby/Perl/Python bindings) you can get access to table and index names by doing a SELECT on a special table named "SQLITE_MASTER". Every SQLite database has an SQLITE_MASTER table that defines the schema for the database. The SQLITE_MASTER table looks like this: CREATE TABLE sqlite_master ( type TEXT, name TEXT, tbl_name TEXT, rootpage INTEGER, sql TEXT For tables, the type field will always be 'table' and the name field will be the name of the table. So to get a list of all tables in the database, use the following SELECT command: SELECT name FROM sqlite_master WHERE type='table' ORDER BY name; For indices, type is equal to 'index', name is the name of the index and tbl_name is the name of the table to which the index belongs. For both tables and indices, the sql field is the text of the original CREATE TABLE or CREATE INDEX statement that created the table or index. For automatically created indices (used to implement the PRIMARY KEY or UNIQUE constraints) the sql field is NULL. The SQLITE_MASTER table is read-only. You cannot change this table using UPDATE, INSERT, or DELETE. The table is automatically updated by CREATE TABLE, CREATE INDEX, DROP TABLE, and DROP INDEX commands. Temporary tables do not appear in the SQLITE_MASTER table. Temporary tables and their indices and triggers occur in another special table named SQLITE_TEMP_MASTER. SQLITE_TEMP_MASTER works just like SQLITE_MASTER except that it is only visible to the application that created the temporary tables. To get a list of all tables, both permanent and temporary, one can use a command similar to the following: SELECT name FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type='table' ORDER BY name

(8)SQLite数据库是否有任何已知的大小限制?

有关SQLite限制的完整讨论,请参阅limits.html。

(9)SQLite中VARCHAR的最大大小是多少?

SQLite不强制执行VARCHAR的长度。你可以声明一个VARCHAR(10),SQLite会很乐意在那里存储一个5亿字符的字符串。它将保持所有5亿个字符的完整。您的内容不会被截断。无论N的值如何,SQLite都将“VARCHAR(N)” 的列类型理解为与“TEXT”相同。

(10)SQLite是否支持BLOB类型?

SQLite允许您将BLOB数据存储在任何列中,甚至是声明为保存其他类型的列。BLOB甚至可以用作PRIMARY KEY。

(11)如何在SQLite的现有表中添加或删除列。

SQLite具有有限的ALTER TABLE支持,您可以使用它将列添加到表的末尾或更改表的名称。如果您想在表格结构中进行更复杂的更改,则必须重新创建表格。您可以将现有数据保存到临时表中,删除旧表,创建新表,然后将数据从临时表中复制回来。例如,假设您有一个名为“t1”的表,其中列名称为“a”,“b”和“c”,并且您希望从此表中删除列“c”。以下步骤说明了如何做到这一点:BEGIN TRANSACTION; CREATE TEMPORARY TABLE t1_backup(a,b INSERT INTO t1_backup SELECT a,b FROM t1; DROP TABLE t1; CREATE TABLE t1(a,b INSERT INTO t1 SELECT a,b FROM t1_backup; DROP TABLE t1_backup; 承诺;

(12)我删除了很多数据,但数据库文件没有变小。这是一个错误?

不是。当您从SQLite数据库中删除信息时,未使用的磁盘空间将添加到内部“自由列表”中,并在下次插入数据时重新使用。磁盘空间不会丢失。但是它们都没有返回到操作系统。如果删除大量数据并想缩小数据库文件,请运行VACUUM命令。VACUUM将从头开始重建数据库。这将使数据库保留一个空白的自由列表和一个尺寸最小的文件。但是,请注意,VACUUM可能需要一些时间才能运行,并且在运行时可以使用最多两倍的原始文件的临时磁盘空间。使用VACUUM命令的替代方法是使用auto_vacuum编译指示启用的auto-vacuum模式。

(13)我可以在没有支付版税的情况下在商业产品中使用SQLite吗?

是。SQLite处于公有领域。对代码的任何部分均不提出所有权索赔。你可以用它做任何你想做的事。

(14)如何使用包含嵌入式单引号(')字符的字符串文字?

SQL标准指定通过在一行中放置两个单引号来逃脱字符串中的单引号。在这方面,SQL就像Pascal编程语言一样工作。例如:INSERT INTO xyz VALUES('5 O''clock'

(15)什么是SQLITE_SCHEMA错误,为什么我会得到一个错误?

准备好的SQL语句不再有效并且无法执行时,将返回SQLITE_SCHEMA错误。发生这种情况时,必须使用sqlite3_prepare()API从SQL重新编译该语句。只有在使用sqlite3_prepare()和sqlite3_step()接口运行SQL时才会发生SQLITE_SCHEMA错误。您将永远不会从sqlite3_exec()收到SQLITE_SCHEMA错误。如果使用sqlite3_prepare_v2()而不是sqlite3_prepare()准备语句,也不会收到错误。sqlite3_prepare_v2()接口创建一个准备好的语句,如果模式更改,它将自动重新编译自身。处理SQLITE_SCHEMA错误的最简单方法是始终使用sqlite3_prepare_v2()而不是sqlite3_prepare()。

(16)ROUND(9.95,1)为什么会返回9.9而不是10.0?不应该是9.95?

SQLite使用二进制算术,二进制,没有办法写9.95在有限的位数。最接近你的可以达到9.95的64位IEEE浮点数(这是SQLite使用的)是9.949999999999999289457264239899814128875732421875。所以当你输入“9.95”时,SQLite真的可以理解这个数字是上面显示的数值。这个价值下降了。处理浮点二进制数字时,这种问题始终存在。要记住的一般规则是,具有十进制有限表示法(又名“base-10”)的大多数分数不具有二进制的有限表示形式(又名“base-2”)。因此它们使用可用的最接近的二进制数来近似。这种近似通常非常接近,

(17)我编译SQLite时遇到了一些编译器警告。这不是问题吗?它不代表糟糕的代码质量吗?

SQLite中的质量保证是使用全覆盖测试完成的,而不是通过编译器警告或其他静态代码分析工具。换句话说,我们验证了SQLite实际上得到了正确的答案,而不仅仅是满足样式约束。大部分的SQLite代码都是纯粹用于测试的。SQLite测试套件运行数万个单独的测试用例,并且许多这些测试用例都经过参数化,以便在每次发布之前运行数亿次涉及数十亿SQL语句的测试并进行正确评估。开发人员使用代码覆盖工具来验证通过代码的所有路径都经过测试。无论何时在SQLite中发现错误,都会编写新的测试用例来展示该错误,以便将来无法再次检测到错误。在测试期间,SQLite库是用特殊的检测工具编译的,它允许测试脚本模拟各种各样的故障,以便验证SQLite是否可以正确恢复。内存分配被仔细地跟踪,并且不会发生内存泄漏,即使在内存分配失败之后。自定义VFS层用于模拟操作系统崩溃和电源故障,以确保事务在这些事件中是原子级的。一种故意注入I / O错误的机制表明SQLite对这种故障具有适应性。(作为一个实验,尝试在其他SQL数据库引擎上引发这些错误并查看会发生什么!)我们也使用SQLite运行 内存分配被仔细地跟踪,并且不会发生内存泄漏,即使在内存分配失败之后。自定义的VFS层用于模拟操作系统崩溃和电源故障,以确保事务在这些事件中是原子级的。一种故意注入I / O错误的机制表明SQLite对这种故障具有适应性。(作为一个实验,尝试在其他SQL数据库引擎上引发这些错误并查看会发生什么!)我们也使用SQLite运行 内存分配被仔细地跟踪,并且不会发生内存泄漏,即使在内存分配失败之后。自定义VFS层用于模拟操作系统崩溃和电源故障,以确保事务在这些事件中是原子级的。一种故意注入I / O错误的机制表明SQLite对这种故障具有适应性。(作为一个实验,尝试在其他SQL数据库引擎上引发这些错误并查看会发生什么!)我们也使用SQLite运行Valgrind在Linux上并验证它没有发现问题。有人说我们应该消除所有的警告,因为良性的警告掩盖了未来变化中可能出现的真实警告。这已经足够了。但在回答中,开发人员发现所有警告已经在用于SQLite开发的构建(GCC,MSVC和clang的各种版本)中得到修复。编译器警告通常只能从SQLite开发人员不使用的编译器或编译时选项中产生。

(18)Unicode字符不区分大小写的匹配不起作用。

SQLite的默认配置只支持不区分大小写的ASCII字符比较。原因在于,要进行完整的Unicode区分大小写比较和大小写转换,需要表和逻辑,这些大小几乎是SQLite库的两倍。SQLite开发人员认为,任何需要完整Unicode支持的应用程序可能已经具有必要的表格和函数,因此SQLite不应占用空间来重复此功能。默认情况下,SQLite不提供完整的Unicode支持,而是提供了与外部Unicode比较和转换例程链接的功能。应用程序可以使用sqlite3_create_collat​​ion())和内置的like(),upper()和lower()函数(使用sqlite3_create_function())来重载内置的NOCASE整理序列。SQLite源代码包含一个“ICU”扩展,可以完成这些重载。或者,开发人员可以根据自己的项目中已包含Unicode识别的比较例程编写自己的重载。

(19)INSERT很慢 - 我只能每秒执行几十个INSERT

实际上,SQLite在一台普通台式机上每秒钟可以轻松完成50,000或更多的INSERT语句。但它每秒只能做几十个事务。交易速度受到磁盘驱动器转速的限制。一个交易通常需要磁盘盘片的两次完整的旋转,这在7200RPM磁盘驱动器上每秒限制您约60个事务。交易速度受磁盘驱动器速度的限制,因为(默认情况下)SQLite实际上一直等到数据真正安全存储在磁盘表面上,然后交易完成。这样,如果您突然断电或者您的操作系统崩溃,您的数据仍然安全。有关详细信息,请阅读SQLite中的原子提交。默认情况下,每个INSERT语句都是它自己的事务。但是,如果用BEGIN包围多个INSERT语句... COMMIT,那么所有的插入被分组到单个事务中。提交事务所需的时间将在所有随附的插入语句之间进行摊销,因此每个插入语句的时间会大大减少。另一个选项是运行PRAGMA synchronous = OFF。这个命令将导致SQLite不等待数据到达磁盘表面,这将使写入操作看起来更快。但是,如果您在交易中断电,您的数据库文件可能会损坏。这会使写入操作看起来更快。但是,如果您在交易中断电,您的数据库文件可能会损坏。这会使写入操作看起来更快。但是,如果您在交易中断电,您的数据库文件可能会损坏。

(20)我不小心删除了我的SQLite数据库中的一些重要信息。我怎样才能恢复它?

如果您有数据库文件的备份副本,请从备份中恢复信息。如果你没有备份,恢复是非常困难的。您可能能够在原始数据库文件的二进制转储中找到部分字符串数据。在给定特殊工具的情况下恢复数字数据也是可能的,但据我们所知,目前还没有这样的工具。SQLite有时用SQLITE_SECURE_DELETE选项进行编译,该选项用零覆盖所有被删除的内容。如果是这种情况,那么恢复显然是不可能的。自从数据被删除以来,如果您运行了VACUUM,恢复也是不可能的。如果未使用SQLITE_SECURE_DELETE并且VACUUM尚未运行,则某些已删除的内容可能仍在数据库文件中,标记为可重用的区域。但是,再次,我们知道没有任何程序或工具可以帮助您恢复数据。

(21)什么是SQLITE_CORRUPT错误?数据库“畸形”意味着什么?为什么我得到这个错误?

当SQLite在数据库文件的结构,格式或其他控制元素中检测到错误时,将返回SQLITE_CORRUPT错误。没有外部帮助,SQLite不会损坏数据库文件。如果您的应用程序在更新过程中崩溃,则您的数据是安全的。即使您的操作系统崩溃或电力损失,数据库也是安全的。SQLite的抗崩溃功能已经得到了广泛的研究和测试,并得到数十亿用户的多年实际经验的证明。也就是说,硬件或操作系统中有很多外部程序或错误可以破坏数据库文件。请参阅如何破坏SQLite数据库文件以获取更多信息。您可以使用PRAGMA integrity_check对数据库完整性进行彻底但时间密集的测试。您可以使用PRAGMA quick_check对数据库完整性进行更快速但不太全面的测试。根据您的数据库损坏的程度,您可以通过使用CLI将架构和内容转储到文件然后重新创建来恢复某些数据。不幸的是,一旦虚张声势从墙上掉下来,通常不可能再次将他重新聚合在一起。

(22)SQLite是否支持外键?

版本3.6.19(2009-10-14)开始,SQLite支持外键约束。但是默认情况下外键约束的强制关闭(为了向后兼容)。要启用外键约束实施,请运行PRAGMA foreign_keys = ON或使用-DSQLITE_DEFAULT_FOREIGN_KEYS = 1进行编译。

(23)如果我在构建SQLite时使用SQLITE_OMIT _...编译时选项,会出现编译器错误。

SQLITE_OMIT _...编译时选项仅在从规范源文件构建时才有效。从SQLite合并或从预处理的源文件构建时,它们不起作用。可以构建一个特殊的合并,它将与预定的一组SQLITE_OMIT _...选项配合使用。这样做的说明可以在SQLITE_OMIT _...文档中找到。

(24)我的WHERE子句表达式 不起作用。它会导致返回表的每一行,而不仅仅是column1的值为“column1”的行。column1="column1"

在SQL中围绕字符串文字使用单引号,而不是双引号。这是SQL标准要求的。您的WHERE子句表达式应为:column1='column1'SQL使用包含特殊字符或关键字的标识符(列名或表名)周围的双引号。所以双引号是转义标识符名称的一种方式。因此,当你说column1="column1"这相当于column1=column1显然永远是真的。

(25)SQLite的语法图(又名“铁路”图)如何生成?

该过程在http://wiki.tcl-lang.org/21708解释。

(26)即使约束中的一个或多个列为NULL,SQL标准也要求强制执行UNIQUE约束,但SQLite不执行此操作。这不是一个错误?

也许你指的是SQL92中的以下语句:当且仅当表中没有两行在唯一列中具有相同的非空值时,满足唯一约束。该陈述含糊不清,至少有两种可能的解释:

  • 当且仅当表中没有两行具有相同的值并且唯一列中具有非空值时,满足唯一约束。

  • 当且仅当表中没有两行具有非空的唯一列的子集中的相同值时,才满足唯一约束。

SQLite遵循解释(1),就像PostgreSQL,MySQL,Oracle和Firebird一样。的确,Informix和Microsoft SQL Server使用解释(2),但是我们SQLite开发人员认为解释(1)是对需求的最自然的解读,我们也希望最大化与其他SQL数据库引擎的兼容性,以及大多数其他数据库引擎也与(1)一起使用,所以这就是SQLite所做的。

(27)SQLite的出口管制分类号(ECCN)是什么?

仔细审查商业控制列表(CCL)后,我们确信核心公有领域SQLite源代码不被任何ECCN所描述,因此ECCN应被报告为EAR99。以上内容适用于核心公有领域SQLite。如果通过添加新代码来扩展SQLite,或者将SQLite静态链接到应用程序,那么可能会在您的特定情况下更改ECCN。

(28)我的查询没有返回我期望的列名。这是一个错误?

如果结果集的列由AS子句命名,则SQLite将保证将AS关键字右侧的标识符用作列名称。如果结果集不使用AS子句,那么SQLite可以自由地为列命名任何它想要的东西。有关更多信息,请参阅sqlite3_column_name()文档。

SQLite在公共领域。