Dan*_*iel 5 python postgresql subprocess postgresql-9.3
我在python中使用以下代码,调用PostgreSQL查询subprocess:
import subprocess
claimer_name = 'a_name'
startdate = '2014-04-01'
enddate = '2018-04-01'
data = subprocess.check_output(['/usr/bin/psql -U user_name "SELECT c.asset_id, c.video_id,
c.claim_id, c.claim_date FROM db.claim c JOIN db.claim_history h ON c.claim_id = h.claim_id JOIN
db.users_email e ON LOWER(e.email) = LOWER(h.email) JOIN m.auth_user u ON e.user_id = u.id WHERE
h.list_order = 1 AND c.claim_origin = ‘Descriptive Search’ AND c.claim_date >= \"%s\" AND
c.claim_date < \"%s\" AND concat(u.first_name, concat(chr(32),
u.last_name)) = \"%s\""' % (startdate, enddate, claimer_name)], shell=True)
Run Code Online (Sandbox Code Playgroud)
如何逃避"描述性搜索"周围的单引号?按原样运行此代码会产生错误Only ASCII characters are allowed in an identifier.
我试过了:
[''Descriptive Search''][\'Descriptive Search\'][""Descriptive Search""][concat('Descriptive', concat(chr(32), 'Search'))] 并指定一个变量:i = 'Descriptive Search',然后c.claim_origin = \"%s\".
但是,这些尝试产生相同的ASCII characters错误.使用字符串格式化为我的其他变量正常工作(startdate,enddate,claimer_name),我难倒,为什么它不会为字符串"描述性搜索"工作.
使用PostgreSQL 9.3.
任何正确方向的帮助或要点都会很棒; 谢谢!
这有很多问题.
您应该使用psycopg2而不是尝试shell psql来与数据库通信;
因为您没有使用正确的数据库绑定,所以无法正确使用放置参数(预处理语句),因此您必须自己处理文本中的转义以避免SQL注入风险并引用错误;
在通过调用命令时subprocess,尽可能避免使用shell.这是可能失败的另一点,在这种情况下完全没有必要;
通常应"""在Python中引用长字符串以避免需要转义嵌套"s;
表达式concat(u.first_name, concat(chr(32), u.last_name))是不必要的扭曲.只写u.first_name || ' ' || u.last_name或format('%s %s', u.first_name, u.last_name);
您"double quotes"用来引用替换的文字,这是无效的SQL.根据文档,它们将被视为标识符.所以c.claim_date < \"%s\"会因为错误而失败no column "2014-04-01";
在引用时,您使用的是真正的单引号,而不是撇号‘Descriptive Search‘.猜测你已经在文字处理器中编辑了代码,而不是程序员的文本编辑器.'Descriptive Search'在SQL中引用文字时,您需要撇号.
因为您使用单引号字符(U + 2018)而不是撇号(U + 0027)来引用文字字符串Descriptive Search,PostgreSQL不会将其识别为文字并尝试将其解析为标识符.但是,‘在不带引号的标识符中不是合法字符,因此它报告了您显示的错误.
请参阅有关标识符和文字的文档.
这是你应该做的:
import psycopg2
import datetime
claimer_name = 'a_name'
startdate = datetime.date(2014, 1, 1)
enddate = datetime.date(2018, 1, 1)
conn = psycopg2.connect("user=user_name")
curs = conn.cursor()
curs.execute("""
SELECT
c.asset_id,
c.video_id,
c.claim_id,
c.claim_date
FROM db.claim c
JOIN db.claim_history h ON c.claim_id = h.claim_id
JOIN db.users_email e ON LOWER(e.email) = LOWER(h.email)
JOIN m.auth_user u ON e.user_id = u.id
WHERE h.list_order = 1
AND c.claim_origin = 'Descriptive Search'
AND c.claim_date >= %s
AND c.claim_date < %s
AND u.first_name || ' ' || u.last_name = %s
""", (startdate, enddate, claimer_name)
)
results = curs.fetchall()
Run Code Online (Sandbox Code Playgroud)
特别要注意的是,我并没有使用Python的%字符串格式化操作员上方.的%s条目放置参数that're通过psycopg2适当取代; 请参阅将参数传递给SQL查询.