2015-09-13 20 views
0

从PostgreSQL文档中,如果您在不指定模式的情况下执行INSERT,则它应该是public模式。PostgreSQL架构“www”不存在?

conn = psycopg2.connect(dbname = 'orion', 
       host = 'localhost', 
       port = 5432, 
       user = 'earthling', 
       password = 'mysupersecretpassword') 
sql = conn.cursor() 

def INSERT(table, info, text): 
    date = datetime.date.today() 
    query = "INSERT INTO %s (info, text, date) " \ 
     "VALUES (%s, %s, %s)" %(table, info, text, date) 
    sql.execute(query) 

INSERT("main", "www.capecod.edu", "test") 

出于某种原因,我看到以下错误?

psycopg2.ProgrammingError: schema "www" does not exist 

回答

3

您正在使用字符串插值来创建查询。这是psycopg2执行什么:

INSERT INTO main (info, text, date) 
    VALUES (www.capecod.edu, test, 2015-09-12) 

如果不是很明显出了什么问题在这里,它是没有价值的被引用。这里是正确引用版本:

INSERT INTO main (info, text, date) 
    VALUES ('www.capecod.edu', 'test', '2015-09-12') 

错误是由未加引号www.capecod.edu引起的。由于这些点,它被解释为schema.table.column

执行此操作的“正确”方法是使用参数化查询。

query = "INSERT INTO main (info, text, date) VALUES (%s, %s, %s)" 
params = (info, text, date) 
sql.execute(query, params) 

psycopg2将弄清楚应该引用什么以及如何。这比你自己插入字符串更安全,这往往会让你打开SQL注入攻击。

http://initd.org/psycopg/articles/2012/10/01/prepared-statements-psycopg/

不幸的是,你不能只是折腾标识符,如作为参数表名,因为那时他们引述字符串值,这是不好的SQL语法。我找到了一个答案(python adds "E" to string),它指向psycopg2.extensions.AsIs作为安全地将诸如表名之类的标识符作为参数传递的方式。不过,我无法在测试中完成这项工作。

如果你走的是AsIs路由,你应该小心检查表名是否有效,如果它们以某种方式来自用户输入。类似于

valid_tables = ["main", "foo", "bar", "baz"] 

if table not in valid_tables: 
    return False 
+0

这不会像书面的那样工作。你必须自己插入字符串,因为psycopg2不知道它是一个标识符而不是文字。 –

+0

@CraigRinger谢谢,我没有抓到。实际上,您可以将表名作为参数传递,您只需要更加谨慎......我将编辑答案。 –

+0

在名称周围添加''后,似乎只有工作,我没有看到我的表中的条目?这是因为我需要使用参数总是?或者,也许日期需要PostgreSQL风格而不是Python风格? – htmlfarmer