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

时间:2017-07-25 07:06:36

标签: python postgresql psycopg2

我试图通过使用我写的函数将pandas DataFrame中的信息插入到数据库表中:

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

当我尝试使用此功能时:

b=0
for row in DF['id']:
    insert(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')
    b = b+1

我收到以下语法错误:

SyntaxError: invalid syntax
PS D:\tito\scripts\database training> python .\postgres_script.py
Traceback (most recent call last):
File ".\postgres_script.py", line 56, in <module>insert (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')
File ".\postgres_script.py", line 15, in insert
cur.execute("INSERT INTO %s VALUES %s,%s,%s,%s"  % (table_name ,name ,genere , year,impd_rating))
psycopg2.ProgrammingError: syntax error at or near "Avatar"
LINE 1: INSERT INTO test_movies VALUES Avatar,action,2009,7.9

我还尝试将str替换方法从%s更改为.format() 但我有同样的错误。

5 个答案:

答案 0 :(得分:2)

Pandas有一个DataFrame方法,to_sql

# Only needs to be executed once.
conn=psycopg2.connect("dbname='database1' user='postgres' password='postgres333' host='localhost' port=5433 ")


df.to_sql('test_movies', con=conn, if_exists='append', index=False)

这应该会让你朝着正确的方向前进。

答案 1 :(得分:2)

错误消息是显式的,Avatar INSERT INTO test_movies VALUES Avatar,action,2009,7.9此SQL命令错误。仅仅因为值必须括在括号中,并且必须引用字符串,所以正确的SQL是:

INSERT INTO test_movies VALUES ('Avatar','action',2009,7.9)

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

cur.execute("INSERT INTO %s VALUES (?,?,?,?)"  % (table_name,) ,(name ,genere , year,impd_rating)))

(*)这是导致大量 SQL注入缺陷的原因,因为如果其中一个参数包含一个半列(;),之后的内容可能会被解释为一个新命令

答案 2 :(得分:1)

你好mohamed mahrous,

首先安装psycopg2包,用于访问PostgreSQL数据库。

请尝试以下代码,

import psycopg2
conn=psycopg2.connect("dbname='database1' user='postgres' password='postgres333' host='localhost' port=5433 ")
cur=conn.cursor()

def insert(table_name,name,genere,year,impd_rating): 
    query = "INSERT INTO "+table_name+"(name,genere,year,impd_rating) VALUES(%s,%s,%s,%s)"
    try:
        print query
        cur.execute(query,(name,genere,year,impd_rating))
    except Exception, e:
        print "Not execute..."
    conn.commit()

b=0
for row in DF['id']:
    insert (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')
    b= b+1

conn.close()

示例,

import psycopg2
conn=psycopg2.connect("dbname='database1' user='postgres' password='postgres333' host='localhost' port=5433 ")
cur=conn.cursor()

def insert(table_name,name,genere,year,impd_rating): 
    query = "INSERT INTO "+table_name+"(name,genere,year,impd_rating) VALUES(%s,%s,%s,%s)"
    try:
        print query
        cur.execute(query,(name,genere,year,impd_rating))
    except Exception, e:
        print "Not execute"
    conn.commit()

b=0
for row in DF['id']:
    insert (impd_rating="7.0",year="2017",name="Er Ceo Vora Mayur",genere="etc",table_name="test_movies")
    b= b+1

conn.close()

我希望我的回答很有帮助 如果有任何疑问请评论。

答案 3 :(得分:1)

在原始查询中

INSERT INTO %s VALUES %s,%s,%s,%s

存在一个SQL问题:您需要围绕值进行大括号,即它应该是VALUES (%s, %s, %s, %s)。最重要的是,表名不能作为参数合并,或者它将作为字符串进行转义,这不是你想要的。

您可以使用psycopg 2.7 sql module将表名合并到查询中,并使用值的占位符:

from psycopg2 import sql

query = sql.SQL("INSERT INTO {} VALUES (%s, %s, %s, %s)").format(
    sql.Identifier('test_movies'))

cur.execute(query, ('Avatar','action',2009,7.9))

这样可以安全地合并表名和查询参数。

答案 4 :(得分:0)

我通过使用sqlalchemy和pandas to_sql方法找到了我的问题的解决方案 感谢大家的帮助

from sqlalchemy import *
import pandas as pd
def connect(user, password, db, host='localhost', port=5433):

    '''Returns a connection and a metadata object'''

    # We connect with the help of the PostgreSQL URL

    # postgresql://federer:grandestslam@localhost:5432/tennis

    url = 'postgresql://{}:{}@{}:{}/{}'

    url = url.format(user, password, host, port, db)

    # The return value of create_engine() is our connection object

    con = sqlalchemy.create_engine(url, client_encoding='utf8')

    # We then bind the connection to MetaData()

    meta = sqlalchemy.MetaData(bind=con, reflect=True)

    return con, meta

con, meta = connect('postgres','postgres333','database1')
movies= Table('test',meta,
Column('id',Integer,primary_key=True),
Column('name',String),
Column('genere',String),
Column('year',Integer),
Column('idbm_rating',REAL))
meta.create_all(con)

DF=pd.read_csv('new_movies.txt',sep='       ',engine='python')
DF.columns=('id','name' ,'genere' ,'year' ,'idbm_rating' )
DF.to_sql('movies', con=con, if_exists='append', index=False)