SQL executemany() with python 和一个数组以及 ON DUPLICATE KEY

SQL executemany() with python and an array and ON DUPLICATE KEY

我正在努力使用 ON DUPLICATE KEY 和我当前的代码:

def upload_to_database(ticker_collection):
  trend_data = []
  trend_data_table = "trend_data"
  trend_data_columns = "Ticker, Subreddit, Score, Rockets, Date"
  
  trend_data_sql = "INSERT INTO " + trend_data_table +\
                   " (" + trend_data_columns + ") VALUES (%s, %s, %s, %s, %s) " +\
                   "ON DUPLICATE KEY UPDATE " +\
                   "Score = Score + %s, " +\
                   "Rockets = Rockets + %s"

  for ticker in ticker_collection:
    ticker_subreddit = ticker_collection[ticker]['subreddit']
    ticker_score = int(ticker_collection[ticker]['score'])
    ticker_rockets = int(ticker_collection[ticker]['rockets'])
    insert_date = datetime.date(datetime.now(est))
    
    ticker_data = (ticker, ticker_subreddit, ticker_score, ticker_rockets, insert_date, 1, 1)

    trend_data.append(ticker_data)
  
  the_db_cursor.executemany(trend_data_sql, trend_data)
  the_database.commit()
  
  return the_db_cursor.rowcount, "was inserted."

trend_data_sql 是我的查询,最后有 Score 和 Rockets,如果存在具有相同 Ticker 和 DateTime(我的唯一键)的条目,我只想更新分数和火箭条目。

但是,我正在尝试使用 executemany() 来执行此操作以节省数据库性能。我对如何将 ON DUPLICATE KEY 与 for 循环和 executemany().

结合起来有些困惑

任何指导或建议将不胜感激。

Table结构:

CREATE TABLE `trend_data` (
  `Ticker` varchar(255) NOT NULL,
  `Subreddit` varchar(255) NOT NULL,
  `Score` int(11) NOT NULL,
  `Rockets` int(11) NOT NULL,
  `Date` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Table 索引:

ALTER TABLE `trend_data`
  ADD UNIQUE KEY `Unique_Keys` (`Ticker`,`Date`,`Subreddit`) USING BTREE;

请试试这个:

  trend_data_sql = "INSERT INTO " + trend_data_table +\
                   " (" + trend_data_columns + ") VALUES (%s, %s, %s, %s) " +\
                   "ON DUPLICATE KEY UPDATE " +\ 
                   "Score = Score + %s, " +\
                   "Rockets = Rockets + %s" 

  for ticker in ticker_collection:
    ...

    value = ...

    ...
    
    ticker_data = (ticker, ticker_subreddit, ticker_score, ticker_rockets, value, value)

    trend_data.append(ticker_data)

已在 MariaDB 上测试。如果因为您正在使用 MySQL 而无法正常工作,我认为您可以尝试以下操作。 (我无法测试,因为我没有 MySQL 不过...)

  trend_data_sql = "INSERT INTO " + trend_data_table +\
                   " (" + trend_data_columns + ") VALUES (%(ticker)s, %(reddit)s, %(score)s, %(rocket)s, %(date)s) " +\
                   "ON DUPLICATE KEY UPDATE " +\
                   "Score = Score + %(value)s, " +\
                   "Rockets = Rockets + %(value)s"

  for ticker in ticker_collection:
    ...
        
    ticker_data = {
      'ticker': ticker,
      'reddit': ticker_subreddit, 
      'score': ticker_score, 
      'rocket': ticker_rockets, 
      'date': insert_date, 
      'value': 1
    }    

    trend_data.append(ticker_data)
  
  the_db_cursor.executemany(trend_data_sql, trend_data)
  the_database.commit()
  
  return the_db_cursor.rowcount, "was inserted."


ticker_collection = {
    'a': {'subreddit': 'aa', 'score': 1, 'rockets': 11},
    'b': {'subreddit': 'bb', 'score': 2, 'rockets': 22},
    'c': {'subreddit': 'cc', 'score': 3, 'rockets': 33},
    'd': {'subreddit': 'dd', 'score': 4, 'rockets': 44}
}

print(upload_to_database(ticker_collection))