在Python和SQLite中使用反引号(`)或双引号

3ks5zfa0  于 2022-11-15  发布在  SQLite
关注(0)|答案(3)|浏览(673)

我在Stack Overflow上看到了一个与Android有关的类似问题,但我想知道我应该使用反引号()还是双引号(“)-使用Python-来选择表名或rowid或其他什么。 我尝试了单引号-就像这个select 'rowid', * from 'tbl' order by 'rowid'。单引号在某些情况下有效,但不是全部。我学会了使用双引号或反引号,当我看着*SQLite数据库浏览器时,我注意到它使用了反引号。 我真的很喜欢在Python中的字符串两边加双引号,因为我来自Java,所以使用cursor.execute("select 'rowid',* from 'table';")`是很自然的,使用反号也很容易(双引号需要一个反斜杠,这会使查询看起来有点混乱)。
然而,我只是想确保反标记是可移植的(所有版本的WindowsLinuxOS X等)。

ojsjcaue

ojsjcaue1#

SQL标准规定字符串必须使用'single quotes',而标识符(如表名和列名)在引用时必须使用"double quotes"
为了与MySQL兼容,SQLite also allows对标识符使用单引号,对字符串使用双引号,但仅当上下文使含义明确时才使用。(在SELECT 'rowid' ...中,允许使用字符串,因此可以使用字符串。)如果可能,请始终使用标准的SQL引号。
为了与MySQL兼容,SQLite还允许使用backticks作为标识符。
为了与Microsoft数据库兼容,SQLite还允许使用[brackets]作为标识符。
(这适用于所有SQLite版本。)

s8vozzvw

s8vozzvw2#

在引用标识符时更喜欢使用双引号,例如列名或表名。这是SQL标准。
反引号也有效,但仅在与MySQL语法兼容时才受支持。
单引号用于字符串文字,而不是标识符。这就是为什么您在使用它们时会获得文字值。
进一步阅读:SQLite Keywords

zsohkypk

zsohkypk3#

与反号不同,如果myol不存在,SQLite会将"mycol"视为字符串

因此,如果您的查询有一个拼写错误并且列名错误,它将被视为一个字符串,而不是给出一个错误,这是任何正常人都想要的。然而,反记号给出了错误。
这种更好的错误检查提供了使用反引号而不是双引号的优势。最大的缺点当然不是标准的SQL。
示例:
Tmp.sql

CREATE TABLE "IntegerNames" ( value INTEGER NOT NULL, name TEXT NOT NULL );
INSERT INTO "IntegerNames" VALUES
  (2, 'two'),
  (3, 'three'),
  (5, 'five')
;
SELECT '"value"';
SELECT * FROM "IntegerNames" WHERE "value" = 2;
SELECT '"valuee"';
SELECT * FROM "IntegerNames" WHERE "valuee" = 2;
SELECT '`value`';
SELECT * FROM "IntegerNames" WHERE `value` = 2;
SELECT '`valuee`';
SELECT * FROM "IntegerNames" WHERE `valuee` = 2;
SELECT 'value';
SELECT * FROM "IntegerNames" WHERE value = 2;
SELECT 'valuee';
SELECT * FROM "IntegerNames" WHERE valuee = 2;

运行:

rm -f tmp.sqlite && sqlite3 tmp.sqlite <tmp.sql

结果:

"value"
2|two
"valuee"
`value`
2|two
`valuee`
Error: near line 14: in prepare, no such column: valuee (1)
value
2|two
valuee
Error: near line 18: in prepare, no such column: valuee (1)

因此,我们可以看到,当使用"valuee"时没有错误:它只是被视为字符串'value'。然后,SQLite对所有内容进行隐式类型转换,而'valuee'不等于任何整数值,因此返回为空。
此查询中的反引号与未加引号的valuevaluee具有相同的行为,因为这不是关键字。但是请注意,为了符合SQL,您必须勾选我认为包含大写字符的行(或者至少在PostgreSQL中是这样),因此它们并不总是相等的,即使不考虑关键字。
在SQLite 3.37.2、Ubuntu 22.04上测试。
这种可怕的行为被记录在:https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted上,开发人员自己也承认这是一个糟糕的想法,最初的动机是希望与MySQL兼容。如今,他们学会了更频繁地复制PostgreSQL;-)

8.接受双引号的字符串文字

SQL标准要求标识符用双引号引起来,字符串文字用单引号引起来。例如:

  • “这是合法的SQL列名”
  • ‘这是一个SQL字符串文字’,SQLite同时接受上述两种情况。但是,为了与MySQL 3.x兼容(在最初设计SQLite时,MySQL 3.x是最广泛使用的RDBMS之一),如果双引号字符串与任何有效的标识符不匹配,SQLite也会将其解释为字符串文字。

这一错误功能意味着拼写错误的双引号标识符将被解释为字符串文字,而不是生成错误。它还诱使刚接触SQL语言的开发人员养成了在真正需要学习使用正确的单引号字符串文字形式时使用双引号字符串文字的坏习惯。
事后看来,我们不应该试图让SQLite接受MySQL3.x语法,并且永远不应该允许双引号的字符串文字。然而,有无数的应用程序使用双引号字符串文字,因此我们继续支持该功能,以避免破坏传统。
从SQLite 3.27.0(2019-02-07)开始,使用双引号的字符串文字会导致向错误日志发送警告消息。
从SQLite 3.29.0(2019-07-10)开始,可以使用SQLITE_DBCONFIG_DQS_DDL和SQLITE_DBCONFIG_DQS_DML操作在运行时禁用双引号字符串文字。可以在编译时使用-DSQLITE_DQS=N编译时选项更改默认设置。鼓励应用程序开发人员使用-DSQLITE_DQS=0进行编译,以便在默认情况下禁用双引号字符串文字错误功能。如果这是不可能的,则使用如下C代码禁用单个数据库连接的双引号字符串文字:

sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DDL, 0, (void*)0);
sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DML, 0, (void*)0);

或者,如果缺省情况下禁用双引号字符串文字,但需要有选择地为某些历史数据库连接启用双引号字符串文字,则可以使用上面所示的相同C代码完成此操作,但第三个参数从0更改为1。

相关问题