如何解决此Psycopg错误消息(python)

时间:2018-08-01 12:43:22

标签: python python-3.x postgresql psycopg2

我最近修改了我的插入查询,并开始收到以下错误消息:

error: argument 1 must be a string or unicode object: got tuple instead

这是导致此错误的SQL插入字符串:

timestamp = 'NOW()::timestamp'

sql_insert_command = 
"INSERT INTO test_table(
article_id, 
date_published, 
date_modified, 
row_created_on, 
row_modified_on )" 
"VALUES(%s,%s,%s,%s,%s)",
(new_record[0],new_record[1],new_record[2],timestamp,timestamp)

这是传递给我的查询函数的SQL字符串:

('INSERT INTO test_table(
article_id, 
date_published, 
date_modified, 
row_created_on, 
row_modified_on)
VALUES(%s,%s,%s,%s,%s)', 
('0530973', 
'2018-01-10 17:29:00', 
'2018-02-15 11:58:32', 
'NOW()::timestamp', 
'NOW()::timestamp'))

这是我的旧字符串,可以使用,但是违反了这里的“ NEVER do”语句:http://initd.org/psycopg/docs/usage.html#query-parameters

sql_insert_command = 
"INSERT INTO test_table(
article_id, 
date_published, 
date_modified, 
row_created_on, 
row_modified_on ) " \
"VALUES('" + new_record[0] + "','" + 
new_record[1]+ "','" + 
new_record[2] + "'," + 
timestamp + "," + 
timestamp + ")"

这是通过上面的命令传递给我的查询函数的SQL字符串:

INSERT INTO test_table(article_id, 
date_published, 
date_modified,
row_created_on, 
row_modified_on)
VALUES('0530973',
'2018-01-10 17:29:00',
'2018-02-15 11:58:32',
NOW()::timestamp,
NOW()::timestamp)

是什么导致此错误消息?而我该如何解决这个问题?

这是我用来连接数据库并插入记录的代码:

class DatabaseConnection(object):

_instance = None

def __new__(cls):
    if cls._instance is None:
        cls._instance = object.__new__(cls)

        db_config = {'dbname': 'development', 'host': 'localhost',
                 'password': 'somepassword', 'port': 5432, 'user': 'postgres'}
        try:
            print('connecting to PostgreSQL database...')
            connection = DatabaseConnection._instance.connection = psycopg2.connect(**db_config)
            connection.autocommit = True
            cursor = DatabaseConnection._instance.cursor = connection.cursor()
            cursor.execute('SELECT VERSION()')
            db_version = cursor.fetchone()

        except Exception as error:
            print('Error: connection not established {}'.format(error))
            DatabaseConnection._instance = None

        else:
            print('connection established\n{}'.format(db_version[0]))

    return cls._instance

def __init__(self):
    self.connection = self._instance.connection
    self.cursor = self._instance.cursor

def insert_new_records(self, insert_query):
    try:
        # used for testing
        print (insert_query)

        result = self.cursor.execute(insert_query)

    except Exception as error:
        print('error execting query "{}", error: {}'.format(insert_query, error))
        return None
    else:
        return result

def __del__(self):
    self.connection.close()
    self.cursor.close()

我用来插入记录的代码:

new_record = ("0530973", "2018-01-10 17:29:00", "2018-02-15 11:58:32",
              "0530974", "2018-01-10 17:29:00", "2018-02-15 11:58:32")


timestamp = 'NOW()::timestamp'

sql_insert_command = 
"INSERT INTO test_table(
article_id, 
date_published, 
date_modified, 
row_created_on, 
row_modified_on ) " \
"VALUES('" + new_record[0] + "','" + 
new_record[1]+ "','" + 
new_record[2] + "'," + 
timestamp + "," + 
timestamp + ")"

1 个答案:

答案 0 :(得分:1)

timestamp解释的变量execute被错误地用单引号引起来。

最简单的方法是仅使用字符串而不是sql文本中的变量:

cur.execute("""
    INSERT INTO test_table(
    article_id, 
    date_published, 
    date_modified, 
    row_created_on, 
    row_modified_on )
    VALUES(%s,%s,%s,now()::timestamp,now()::timestamp)""",
    (new_record[0],new_record[1],new_record[2])
    )

使用format()的更优雅的解决方案:

cur.execute("""
    INSERT INTO test_table(
    article_id, 
    date_published, 
    date_modified, 
    row_created_on, 
    row_modified_on )
    VALUES(%s,%s,%s,{},{})""".format(timestamp,timestamp),
    (new_record[0],new_record[1],new_record[2])
    )

您还可以使用扩展名中的功能AsIs()

from psycopg2.extensions import AsIs

cur.execute("""
    INSERT INTO test_table(
    article_id, 
    date_published, 
    date_modified, 
    row_created_on, 
    row_modified_on )
    VALUES(%s,%s,%s,%s,%s)""",
    (new_record[0],new_record[1],new_record[2],AsIs(timestamp),AsIs(timestamp))
    )