Python构建SQL查询语句并与数据库交互
作者:weixin_48092311
在Python中构建SQL查询语句通常涉及到使用sqlite3、MySQLdb、psycopg2(针对PostgreSQL)、pymysql(针对MySQL)等库。下面我将分别介绍如何使用这些库来构建和执行SQL查询。
1、概念和构建流程介绍
Python构建SQL查询语句,就是把arcmap里查询语句构建出来,并且把查询语句整个作为字符串发给数据库。
- Python 语法:负责把数据(列表、字符串)通过用
join和format等方法拼成一个纯文本。 - 数据库引擎:只认这个最终生成的纯文本字符串,并把它当作 SQL 指令来执行。
# 如果是判断字段值是否在一个列表中
# 1.通过AddFieldDelimiters方法将字段名标准化
# 因为不同数据库来用,如gdb,mdb对字段名书写要求不同,AddFieldDelimiters可以自动标准化字段格式
GTFL = arcpy.AddFieldDelimiters(output_features, u"国土分类")
land_use = [u"01_耕地", u"02_园地", u"03_林地"]
# 2.通过join拼接查询的列表
# join的作用是将一个列表中的元素用指定的连接符连接为一个字符串
# 要插入的连接符.join(列表)
# 这里插入的连接符是 ',',连接后是值为01_耕地','02_园地','03_林地的字符串
land_use_list = u"','".join(land_use)
# ('{}')这里的目的就是,把{}中的内容01_耕地','02_园地','03_林地替换进来,
# {}两侧的'是为了补充01_耕地','02_园地','03_林地这个字符串缺失的两侧未封闭的'
# 最后实现 ('01_耕地','02_园地','03_林地')的效果
# 3.拼接整个查询语句字符串
where_clause = "{} NOT IN ('{}')".format(GTFL, land_use_list)
# 完全可以在land_use_list里直接前后拼接一个'。land_use = "'" + land_use + "'"
# 最后查询时
# where_clause = "{} NOT IN ({})".format(GTFL, land_use_list)
# 注意:
# 对于字符串来说,引号包裹只是为了Python区分是都是字符串。实际的值是引号包裹的内容。join处理的时候,也只是处理引号包裹的内容,并在每个值之间插入','这个分隔
# 比如land_use实际上元素不是u"01_耕地",而是01_耕地,双引号并不是元素的值
# 对于join字符串连接的问题,也可以从Python的角度理解,两个字符串拼接后,包裹其的双引号并不会被拼接进来
# 即"a" + "b" + "c"最后得到的是 "abc"2、join的原理
join可以理解成,定义一个空字符串,然后遍历要拼接的列表,每次遍历都把列表元素和分隔符拼接到空字符串里(但注意最后一个元素不再拼接分隔符)。
land_use = ["01_耕地", "02_园地", "03_林地"]
result = ""
sep = "','"
for i in range(len(land_use)):
result = result + land_use[i]
if i < len(land_use) - 1: # 不是最后一个才加分隔符
result = result + sep
print(result)
# 结果:01_耕地','02_园地','03_林地 (完美,没尾巴)3、Python构建的SQL查询语句如何与数据库交互
在使用Arcpy时,**数据库执行查询时,完整的 SQL 语句是由 ArcGIS 自动生成的。**Python构建的 where_clause 只是完整的SQL语句中的一部分,即 WHERE 子句。
1. 完整的 SQL 语句是如何生成的?
这个自动生成的过程,可以理解为“填空”:
- ArcGIS 自动补全部分:
SELECT(选择哪些字段)、FROM(从哪个表或要素类查询)等。 - 你负责提供部分:
WHERE(筛选条件,即你写的where_clause)。
最终,这些部分会被拼接成一条完整的 SQL 查询语句发给数据库。
2. 不同场景下的完整 SQL 示例
无论是哪种工具,你传入的 where_clause 都是作为 WHERE 子句被使用:
- 使用
SelectLayerByAttribute时- 你提供:
where_clause = "字段名 = '值'" - 数据库实际执行:
SELECT * FROM 表 WHERE 字段名 = '值'
- 你提供:
- 使用
SearchCursor时- 你提供:
where_clause = "字段名 = '值'" - 数据库实际执行:
SELECT 字段1, 字段2 FROM 表 WHERE 字段名 = '值'
- 你提供:
总结
你不需要在 where_clause 里写 SELECT 或 FROM,这些前置部分由 ArcGIS 在后台自动处理。只需专注于构建正确的 WHERE 条件,其余的交由 ArcGIS 完成。
4、字段名格式的要求
不同数据库来源,对于字段名的书写要求不同。
不同数据源的字段名书写形式,除了gdb,其他都要加双引号。原因是在 SQL 标准中:
- 双引号
" ":用来包裹数据库对象名,比如字段名、表名。 - 单引号
' ':用来包裹数据值,比如文本字符串。
实际开发中,直接使用 arcpy.AddFieldDelimiters 即可自动适配所有数据源,无需手动判断字段名格式。
| 数据源类型 | 字段名直接写 | 字段写法要求 | 用什么符号 |
|---|---|---|---|
| 文件地理数据库 (.gdb) | ✅ 直接写,不加额外符号 | 特殊情况才加 | 双引号 " "(字段名有空格或特殊字符时) |
| 个人地理数据库 (.mdb) | ❌ 必须用方括号包裹 | 必须 | 方括号 [ ] |
| Shapefile (.shp) | ❌ 必须用双引号包裹 | 必须 | 双引号 " " |
| 企业级地理数据库 (SDE) | ❌ 必须用双引号包裹 | 必须 | 双引号 " " |
| CSV、TXT等文本文件 | ❌ 必须用双引号包裹 | 必须 | 双引号 " " |
为什么Arcmap中字段名都是[]包裹
在 ArcMap 界面里字段名被 [] 括起来。主要是因为它自动适配了在 ArcMap 中当前使用的数据源类型。
方括号 [] 是个人地理数据库(Personal Geodatabase,即 .mdb) 专用的字段分隔符。
当你在 ArcMap 里打开一个 Personal Geodatabase 的表来构造查询时,对话框就会自动使用 [] 作为字段名分隔符,让你看到 [字段名] 这样的写法。
但对于不同数据源,ArcMap 显示的字段名分隔符会不一样:
| 数据源类型 | ArcMap中显示的字段名格式 |
|---|---|
| 个人地理数据库 (.mdb) | [字段名] |
| 文件地理数据库 (.gdb) | 通常直接显示 字段名,不加额外符号 |
| Shapefile (.shp) | "字段名" |
| CSV、TXT等文本文件 | "字段名" |
所以,结论是:不能因为 ArcMap 界面上看到 [],就认为所有数据源都这么用。
在 ArcPy 中编写代码时,就需要根据实际情况,遵循之前讨论的规则来选择正确的写法。例如,查询一个 Shapefile 时,代码里字段名就应该用双引号 " ",而不是方括号 [ ]。
如果想确认当前数据具体应该用哪种分隔符,最可靠的办法还是使用 arcpy.AddFieldDelimiters() 函数,它会自动帮你处理好这一切。
5、查询语句拼接时外层单引号 vs 双引号,怎么选?
构建的SQL查询条件where_clause这里,选择的最外层是用双引号包裹成一个字符串,但查询语句整个字符串是既可以用单引号,也可以用双引号,三引号(三引号可以是三个双引号 """,也可以是三个单引号 ''',两者在 Python 中完全等价。)。
where_clause = "{} NOT IN ('{}')".format(GTFL, land_use_list)选哪个取决于内部 SQL 语句里要用什么引号,原则是内外尽量用不同的引号,避免转义。
| 场景 | 外层用 | 内部写法 | 示例 |
|---|---|---|---|
| 字段名用双引号(Shapefile/SDE) | 外层用 单引号 ' | 内部用双引号 " | '"CITY" = \'北京\''(需要转义单引号) 或 """ "CITY" = '北京' """(推荐) |
| 字段名不加引号(GDB) | 外层用 双引号 " | 内部用单引号 ' | "CITY = '北京'" |
| 字段名用方括号(MDB) | 外层用 双引号 " | 内部用单引号 ' | "[CITY] = '北京'" |
| 字段名用方括号(MDB) | 外层用 三引号 """ | 内部用单引号 ' | “”" [CITY] = ‘北京’ “”" |
# 写法1:外层单引号 where_clause = '"CITY" = \'北京\'' # 内部双引号 + 内部单引号需要转义(\) # ↑外层单引号 ↑字段名双引号 ↑字符串值单引号需转义 # 写法2:外层双引号(适用于 GDB,字段名不加引号) where_clause = "CITY = '北京'" # 内部只有单引号,无需转义 # ↑外层双引号 ↑字符串值单引号 # 写法3:外层三重引号(最省心,任何情况都不用转义) where_clause = """ "CITY" = '北京' """ # 内部双引号和单引号和谐共存 # ↑外层三重双引号 ↑字段名双引号 ↑字符串值单引号
6、Arcpy中的不等于符号
在python中构建SQL查询语句时,不等于符号可以有两种形式,<>和!=,两者在功能上没有区别。
不过,为了确保代码的最佳兼容性,更推荐使用 <>。以下是具体原因:
- 标准 vs 别名:
<>是SQL-92的国际标准语法;而!=并非标准,只是部分数据库支持的“别名”或“非标准写法”。 - 数据库兼容性:主流数据库(如MySQL、PostgreSQL、SQLite)都同时支持两者。但在一些非常老旧的数据库(如SQL Server 2000)中,
!=可能无法识别。 - Python中的使用:在Python的ORM框架(如SQLAlchemy)或原生SQL字符串中,这两种写法都能被正常识别和执行。
虽然两者效果一样,但为了代码有更好的跨数据库移植性,优先考虑使用 <> 会是更稳妥的选择。
到此这篇关于Python构建SQL查询语句的文章就介绍到这了,更多相关Python SQL查询语句内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
