psycopg2 postgres 数据库语法错误接近值

moh*_*ous 2 python postgresql psycopg2

我正在尝试使用我编写的函数将 pandas DataFrame 中的信息插入到数据库表中:

\n\n
def insert(table_name="", name="", genere="", year=1, impd_rating=float(1)):\n    conn = psycopg2.connect("dbname=\'database1\' user=\'postgres\' password=\'postgres333\' host=\'localhost\' port=5433 ")\n    cur = conn.cursor()\n    cur.execute("INSERT INTO %s VALUES %s,%s,%s,%s"  % (table_name, name, genere, year, impd_rating))\n    conn.commit()\n    conn.close()\n
Run Code Online (Sandbox Code Playgroud)\n\n

当我尝试像这样使用这个函数时:

\n\n
b=0\nfor row in DF[\'id\']:\n    insert(impd_rating=float(DF[\'idbm_rating\'][b]), \n           year=int(DF[\'year\'][b]), \n           name=str(DF[\'name\'][b]), \n           genere=str(DF[\'genere\'][b]),\n           table_name=\'test_movies\')\n    b = b+1\n
Run Code Online (Sandbox Code Playgroud)\n\n

我收到以下语法错误:

\n\n
SyntaxError:\xc2\xa0invalid\xc2\xa0syntax\nPS\xc2\xa0D:\\tito\\scripts\\database\xc2\xa0training>\xc2\xa0python\xc2\xa0.\\postgres_script.py\nTraceback\xc2\xa0(most\xc2\xa0recent\xc2\xa0call\xc2\xa0last):\nFile\xc2\xa0".\\postgres_script.py",\xc2\xa0line\xc2\xa056,\xc2\xa0in\xc2\xa0<module>insert\xc2\xa0(impd_rating=float(DF[\'idbm_rating\'][b]),year=int(DF[\'year\'][b]),name=str(DF[\'name\'][b]),genere=str(DF[\'genere\'][b]),table_name=\'test_movies\')\nFile\xc2\xa0".\\postgres_script.py",\xc2\xa0line\xc2\xa015,\xc2\xa0in\xc2\xa0insert\ncur.execute("INSERT\xc2\xa0INTO\xc2\xa0%s\xc2\xa0VALUES\xc2\xa0%s,%s,%s,%s"\xc2\xa0\xc2\xa0%\xc2\xa0(table_name\xc2\xa0,name\xc2\xa0,genere\xc2\xa0,\xc2\xa0year,impd_rating))\npsycopg2.ProgrammingError:\xc2\xa0syntax\xc2\xa0error\xc2\xa0at\xc2\xa0or\xc2\xa0near\xc2\xa0"Avatar"\nLINE\xc2\xa01:\xc2\xa0INSERT\xc2\xa0INTO\xc2\xa0test_movies\xc2\xa0VALUES\xc2\xa0Avatar,action,2009,7.9\n
Run Code Online (Sandbox Code Playgroud)\n\n

我还尝试将 str 替换方法从 更改%s.format()\n但我遇到了同样的错误。

\n

Ser*_*sta 6

错误消息很明确,这个 SQL 命令错误在AvatarINSERT INTO test_movies VALUES Avatar,action,2009,7.9。很简单,因为值必须用括号括起来,并且字符串必须用引号引起来,所以正确的 SQL 是:

INSERT INTO test_movies VALUES ('Avatar','action',2009,7.9)
Run Code Online (Sandbox Code Playgroud)

但是通过连接参数构建完整的 SQL 命令是不好的做法 (*),只有表名应该直接插入到命令中,因为 is 不是 SQL 参数。正确的方法是使用参数化查询:

cur.execute("INSERT INTO %s VALUES (?,?,?,?)"  % (table_name,) ,(name ,genere , year,impd_rating)))
Run Code Online (Sandbox Code Playgroud)

(*) 这是许多SQL 注入缺陷的原因,因为如果其中一个参数包含分号 ( ;),后面的内容可能会被解释为一个新命令