此字符串:
"CREATE USER %s PASSWORD %s", (user, pw)
总是扩大到:
CREATE USER E'someuser' PASSWORD E'somepassword'
谁能告诉我为什么?
编辑: 上面的扩展字符串是我的数据库在错误消息中返回的字符串。我正在使用psycopg2来访问我的postgres数据库。真正的代码如下所示:
conn=psycopg2.connect(user=adminuser, password=adminpass, host=host)
cur = conn.cursor()
#user and pw are simple standard python strings the function gets as parameter
cur.execute("CREATE USER %s PASSWORD %s", (user, pw))
conn.commit()
答案 0 :(得分:17)
要通过psycopg将标识符传递给postgresql,请使用AsIs
模块中的extensions
from psycopg2.extensions import AsIs
import psycopg2
connection = psycopg2.connect(database='db', user='user')
cur = connection.cursor()
cur.mogrify(
'CREATE USER %s PASSWORD %s', (AsIs('someuser'), AsIs('somepassword'))
)
'CREATE USER someuser PASSWORD somepassword'
这也适用于将条件传递给像order by
这样的条款:
cur.mogrify(
'select * from t order by %s', (AsIs('some_column, another column desc'),)
)
'select * from t order by some_column, another column desc'
答案 1 :(得分:10)
由于OP的编辑显示他正在使用PostgreSQL,the docs因为它是相关的,他们说:
PostgreSQL也接受“逃避” 字符串常量,是一个 SQL标准的扩展。一个 转义字符串常量由。指定 写字母E(上面或下面 案例)就在开幕单之前 引用,例如E'foo”。
换句话说,psycopg正确地为你的字符串生成转义字符串常量(因此,正如文档所说:
在转义字符串中,反斜杠 character()开始像C一样 反斜杠转义序列,其中 反斜杠和。的组合 以下字符代表a 特殊字节值。
(碰巧也是非原始Python字符串文字的转义约定)。
OP的错误显然与此无关,除了研究PostgreSQL优秀文档的优秀想法之外,他不应该担心这种情况下的E'...'
形式; - )。
答案 2 :(得分:8)
不仅E而且引号似乎来自用户和pw所具有的任何类型。 %s只执行str()所做的事情,这可能会回退到repr(),两者都有相应的方法__str__
和__repr__
。此外,这不是生成结果的代码(我假设有一个%,但现在只看到一个逗号)。请使用实际代码,类型和值扩展您的问题。
附录:考虑到它看起来像SQL,我猜测你看到escape string constants,可能是你的数据库接口模块或库正确生成的。{/ p>
答案 3 :(得分:2)
在尝试之前:
statement = "CREATE USER %s PASSWORD %s" % (user, pw)
请确保您阅读:http://www.initd.org/psycopg/docs/usage.html
基本上问题是,如果你接受用户输入(我假设有人进入用户和pw)你可能会让自己开放SQL注入。
正如PsyCopg2所述:
Warning Never, never, NEVER use Python string concatenation (+) or string parameters interpolation (%) to pass variables to a SQL query string. Not even at gunpoint.
正如已经确定的那样,Postgres(或Psycopg2)似乎没有为转义标识符提供一个好的答案。在我看来,解决此问题的最佳方法是提供“白名单”过滤方法。
ie:确定“用户”和“pw”中允许的字符数。 (也许是A-Za-z0-9_)。请注意,不要包含转义字符('或;等等),或者如果你这样做,则要转义这些值。