ON CONFLICT DO UPDATE 语法和 cursor.executemany 上的 EXCLUDED 错误

ON CONFLICT DO UPDATE syntax and EXCLUDED error on cursor.executemany

我在下面有一个简化的 postgres(版本 13)table,其中包含在 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”

以下错误我在冲突时更新:

错误:“=”处或附近的语法错误

# 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()

我在创建 table.

的位置添加了约束行 (CONSTRAINT com UNIQUE (original_price_date,item)))
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(),
  CONSTRAINT com UNIQUE (original_price_date,item));'''

然后我可以通过以下语句插入数据而不创建 (original_price_date,item) 的重复行。

 sql = '''INSERT INTO ''' + TABLE_ + '''(original_price_date, item, price) 
                VALUES (%s, %s, %s)
                ON CONFLICT (original_price_date, item) 
                DO UPDATE 
                    SET (price, last_updated)  = (EXCLUDED.price,TRANSACTION_TIMESTAMP());'''