【发布时间】:2021-03-19 03:37:13
【问题描述】:
我在下面有一个简化的 postgres(版本 13)表,其中包含在 python 中使用 psycopg2 生成的更新行。 我的问题是当我更新行中的价格字段时,由于出现以下 ON CONFLICT DO UPDATE 错误,我无法完成更新。如果我不使用 ON CONFLICT DO UPDATE ,我可以更新图表,但我想要 ON CONFLICT DO UPDATE 因为它消除了重复的行。
使用 ON CONFLICT DO UPDATE ,我只需要更新字段“price”和“last_updated”,但仅当行匹配“id,item,original_price_date”时才更新
我在 CONFLICT DO UPDATE 上遇到以下错误:
错误:“=”处或附近的语法错误
# update the prices within the existing data
df = pd.DataFrame(np.array([['5/3/2010', 'rock', 15],
['4/15/2010', 'paper', 11],
['2/3/2015', 'scissor', 13]]),
columns = ['original_price_date', 'item', 'price'])
tuples_for_dB = [tuple(x) for x in df.to_numpy()]
sql_script = '''INSERT INTO ''' + TABLE_ + ''' (
original_price_date, item, price, created_date, last_updated)
VALUES (%s, %s, %s, transaction_timestamp(), transaction_timestamp())
ON CONFLICT (id, item, original_price_date)
DO UPDATE SET (price, last_updated = EXCLUDED.price, EXCLUDED.transaction_timestamp());'''
错误:关系“price_data”不存在
sql_script = '''INSERT INTO ''' + TABLE_ + ''' (
original_price_date, item, price, created_date, last_updated)
VALUES (%s, %s, %s, transaction_timestamp(), transaction_timestamp())
ON CONFLICT (id, item, original_price_date)
DO UPDATE SET (price, last_updated) = (EXCLUDED.price, EXCLUDED.transaction_timestamp());'''
我原创的数据:
# postGRESQL connection details
DATABASE_INITIAL_ = 'postgres'
DATABASE_ = 'data'
TABLE_ = 'price_data'
USER_ = 'postgres'
SERVERNAME_ = 'localhost'
PASSWORD_ = password_
HOST_ = '127.0.0.1'
PORT_ = '5432'
#establishing the connection
conn = psycopg2.connect(database = DATABASE_,
user = USER_,
password = PASSWORD_,
host = HOST_,
port = PORT_);
conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT);
conn.autocommit = True
# Creating a cursor object using the cursor() method
cursor = conn.cursor()
sql = "SELECT 1 FROM pg_catalog.pg_database WHERE datname = " + "'" + DATABASE_ + "'"
cursor.execute(sql)
# If dB does not exist create the dB
exists = cursor.fetchone()
print(exists)
if not exists:
print('does not exist')
#Preparing query to create a database
sql = '''CREATE database '''+DATABASE_;
#Creating a database
cursor.execute(sql)
# Creating the table
sql = '''CREATE TABLE IF NOT EXISTS ''' + TABLE_ + ''' (
id SERIAL PRIMARY KEY,
original_price_date DATE NOT NULL,
item TEXT NOT NULL,
price NUMERIC NULL DEFAULT NULL,
created_date TIMESTAMPTZ NULL DEFAULT TRANSACTION_TIMESTAMP(),
last_updated TIMESTAMPTZ NULL DEFAULT TRANSACTION_TIMESTAMP());'''
cursor.execute(sql)
# update the table with data
df = pd.DataFrame(np.array([['5/3/2010', 'rock', 0.9],
['4/15/2010', 'paper', 6.5],
['2/3/2015', 'scissor', 3.9],
['3/23/2017', 'ball', 1.1],
['4/7/2013', 'tire', 5.4]]),
columns = ['original_price_date', 'item', 'price'])
tuples_for_dB = [tuple(x) for x in df.to_numpy()]
sql_script = '''INSERT INTO ''' + TABLE_ + ''' (
original_price_date, item, price, created_date, last_updated)
VALUES (%s, %s, %s, transaction_timestamp(), transaction_timestamp());'''
try:
cursor.executemany(sql_script, tuples_for_dB);
success = True
except psycopg2.Error as e:
error = e.pgcode
print(f'Error : {e.args[0]}')
success = False
if success:
print(f'\nData inserted successfully........')
print(f'Table INSERT sql commit comment :\n"{sql_script}"\n')
elif success == False:
print(f'\nData NOT inserted successfully XXXXXX')
# Preparing query to drop a table
sql = '''DROP TABLE IF EXISTS ''' + TABLE_ + ";"
# Creating the table
cursor.execute(sql)
conn.close()
【问题讨论】:
-
第一个片段中的问题是括号。它必须是
(field,field,field) = (value,value,value)。您在第二个 sn-p 中解决了这个问题。至于price_data does not exist error,在发生这种情况的文件中,您是否连接到正确的数据库? -
我没有看到你在创建脚本的任何地方调用
conn.commt()。如果在psql命令行工具中打开数据库,看到表了吗? -
是的。我看到带有 cmd 行的表,所以它确实在数据库中。最后运行我的脚本是一个 DROP TABLE cmd。如果我将此表注释掉,初始数据将保留在 postgres 中。抱歉,我添加了它,因为我不得不一遍又一遍地重新创建表格。根据提交问题,我添加了 conn.autocommit = True。
-
好的,但是您向我们展示的失败代码不是来自创建脚本,对吧?如果您在创建脚本的末尾删除了表,那么当您执行数据框时它就不会存在。对吗?
-
这个表对于这个问题非常简化。 ON CONFLICT DO UPDATE 错误是由我的百万行数据库引起的。同样的错误在这里也适用。我仍然收到语法错误错误:“=”处或附近的语法错误。我可以编辑我的原始帖子以删除 DROP TABLE。
标签: python postgresql psycopg2