在属性文件中存储SQL语句以供Python脚本使用?

在属性文件中存储SQL语句以供Python脚本使用?,python,sql,Python,Sql,我不知道如何最好地表达这个问题,但我会努力的 我有两个通过crontab执行的python脚本。这些脚本执行一些数据库操作,例如选择和更新(在不同的数据库上),有些脚本使用相同的SQL语句。目前,我使用的SQL查询存储在util.py文件中的静态字典中,每当需要时,我都会从不同的脚本导入它,但是我想知道存储不同脚本使用的静态SQL语句的最佳实践是什么?可读性很重要,因此我需要一些文件格式,以便正确缩进SQL查询 3个选项 (注意:下面的select*from t,其中custid=%(custi

我不知道如何最好地表达这个问题,但我会努力的

我有两个通过crontab执行的python脚本。这些脚本执行一些数据库操作,例如选择和更新(在不同的数据库上),有些脚本使用相同的SQL语句。目前,我使用的SQL查询存储在util.py文件中的静态字典中,每当需要时,我都会从不同的脚本导入它,但是我想知道存储不同脚本使用的静态SQL语句的最佳实践是什么?可读性很重要,因此我需要一些文件格式,以便正确缩进SQL查询

3个选项

(注意:下面的
select*from t,其中custid=%(custid)s
等内容稍后将被提供给postgresql参数化查询。使用RDBMS的参数化查询语法,切勿在没有非常好的理由的情况下手动生成查询字符串。即使如此,也将其限制为来自应用程序本身的配置-外部“数据源文件”坐在某个地方的文件系统可能会被坏角色破坏,然后可能会搭便车进入你的应用程序凭据)

配置分析器 我会使用旧的INI/ConfigParser格式。以前经常使用它们,但现在更倾向于使用json,除了json对sql不太好

这是Python

import ConfigParser
cfp = ConfigParser.ConfigParser()
cfp.read("test_so08.ini")
myselect = cfp.get("sql", "select", raw=True)
for line in myselect.split("\n"):
    print ":%s:" % (line)
还有ini。请注意,您需要在select=之后的每一行上缩进至少一个空格,否则configparser将尝试解析其他行,而不是使用select将它们分组

优点:它不是一个代码文件,所以理论上你可以让任何人配置sql。理论上

缺点:基于ini的sql在获取变量方面有相当大的开销,当您想要添加更多的特性时,您最终需要做很多变通

模块中的普通旧三重字符串变量: 另一种选择是只使用Python模块并使用三重引号字符串。我倾向于将其用于sqls,而不是ini

优点:简单。
缺点:只有Python和无效的语法输入将停止调用脚本

say this is sql_test_so08.py

select = """
  select *
  from customers
  where custid = %(custid)s
  """

select2 = """<some other stuff>"""
一个优点是,我可以使用Template/$var替换来替换从其他地方导入的应用程序常量,而不是在sql中硬编码它们。假设您有一个无效的\u客户\u未付标志设置为3

在sql.py文件中,您可能需要:

from constants import invalid_customer_unpaid

di_constants = dict(invalid_customer_unpaid=invalid_customer_unpaid)

select_bad="""select... where ... $invalid_customer_unpaid"""

select_bad = Template(select_bad).substitute(di_constants)
注意:我很少使用直接变量替换,如下所示。SQL注入带来的风险太大。但是您可以使用RDBMS的绑定参数支持应用相同的思想

亚马尔: 这些天做了很多YAML

  • 用于机器写入和机器读取的JSON
  • YAML用于手写、机器阅读,因为它在支持引号和格式方面比JSON好得多
给定测试。yaml

sql:
  select: select * from customers where custid = %(custid)s
  text: 'some text with ''abc'' and "xyz" '   
然后


将输出:
select*from custid=%(custid)s的客户

为什么不使用存储过程?为什么这样评论?有很多可能的原因,OP的分数很高,足以了解他的情况,而你的答案并不是基于提议方法中的任何特定缺陷。@Talvalin,正如我在问题中提到的,我在多个数据库上调用这些语句,因此我希望将它们都放在一个位置,在较小的程度上,我可以在Python代码中查看和更改它们。您采用了哪种解决方案?@leoschet我将SQL语句存储在dict中,存储在repo/项目根目录下的Python文件中。当我有一个需要SQL语句的模块或脚本时,我从python文件导入dict并从中提取我需要的SQL语句:
from config\u files.SQL\u statements import data\u processing\u SQL\u statements data\u processing\u SQL\u statements['SQL\u statement\u I\u need']
诸如此类
import sql_test_so08
print sql_test_so08.select
from constants import invalid_customer_unpaid

di_constants = dict(invalid_customer_unpaid=invalid_customer_unpaid)

select_bad="""select... where ... $invalid_customer_unpaid"""

select_bad = Template(select_bad).substitute(di_constants)
sql:
  select: select * from customers where custid = %(custid)s
  text: 'some text with ''abc'' and "xyz" '   
from yaml import safe_load as yload

with open("test.yaml") as fi:
    di2 = yload(fi)

print (di2["sql"]["select"])