SQLite数据库名中单引号转义及合法库名跨库引用方法
SQLite特殊名称附加数据库的正确引用方法
问题场景
存在三个SQLite数据库,名称分别为Main、AA、A'A,三个库均包含名为MyTable的数据表。其中Main为初始连接打开的数据库,AA与A'A为后续通过ATTACH命令附加的数据库:
- 执行
select * from 'AA'.'MyTable'可以正常查询AA库中的MyTable表 - 尝试使用同类单引号包裹语法引用
A'A数据库,先后测试'A'A'、'A''A'等转义写法均执行失败,需要实现所有合法SQLite数据库名的正常引用寻址。
错误原因
单引号是SQL标准中字符串字面量的边界符,并不是数据库、表、列这类对象标识符的标准引用符号。SQLite对单引号包裹标识符的写法做了容错兼容,但一旦标识符本身包含单引号,就会和边界符产生语法解析歧义,哪怕按照字符串规则做单引号双写转义,也会因为解析逻辑优先级问题无法稳定寻址。
可用引用方案
SQLite原生支持三种标准标识符引用语法,全部可以正确处理包含特殊字符、保留字的对象名,针对A'A库的MyTable表查询,三种写法均能正常执行:
- 双引号引用(SQL标准语法,优先推荐)
标识符内部如果存在双引号,只需要将双引号双写转义即可,单引号不需要额外处理:SELECT * FROM "A'A"."MyTable"; - 反引号引用(兼容MySQL语法习惯)
标识符内部如果存在反引号,将反引号双写转义即可:SELECT * FROM `A'A`.`MyTable`; - 方括号引用(兼容SQL Server语法习惯)
标识符内部如果存在右方括号],将右方括号双写转义即可:SELECT * FROM [A'A].[MyTable];
通用转义规则
所有合法SQLite标识符(包含空格、单引号、特殊符号、SQL保留字的库名/表名/列名/索引名)都可以通过上述三种方式引用,转义逻辑完全统一:
选定某类符号作为标识符的包裹边界后,仅需要把标识符内容中出现的同类型边界符号双写,其余字符不需要做任何额外转义处理。
例如库名为A"BC]时,三种合法写法如下:
-- 双引号写法,内部双引号双写 SELECT * FROM "A""B`C]"."MyTable"; -- 反引号写法,内部反引号双写 SELECT * FROM `A"B``C]`.`MyTable`; -- 方括号写法,内部右方括号双写 SELECT * FROM [A"B`C]]].[MyTable];
以上写法均可被SQLite解析器正常识别,不会出现语法错误或寻址失败问题。
内容的提问来源于stack exchange,提问作者András Kovács
相关产品推荐
相关产品推荐

