关于上述代码的一些注意事项:
一般来说,在纯SQL中遵从now()要比尽可能在Python中尝试更容易。它避免了时区、库差异等许多潜在的陷阱
如果您构造了一个列的列表,则可以根据其大小动态生成一个%s的字符串,而不需要将该长度硬编码为一个重复的字符串,然后将其切片。在
因为insert_daily_data_into_db似乎是要从一个循环中按股票进行调用的,所以我不认为您希望在这里使用executemany,这将需要一个元组的列表,并且在语义上非常不同。在
您在子select中比较符号的id与其本身,而不是一个特定的值(这意味着它总是正确的)。在
为了防止可能的SQL注入,您应该始终在WHERE子句中插入值,包括subselects
注意:我假设您正在使用psycopg2来访问Postgres,并且表的主键是(symbol_id, price_date)的元组。如果没有,下面的代码至少需要调整一下。在
考虑到这些要点,可以尝试这样的方法(未经测试,因为我没有您的数据、数据库等,但它在语法上是有效的Python):def insert_daily_data_into_db(data_vendor_id, symbol_id, daily_data):
"""Takes a list of tuples of daily data and adds it to the
database. Appends the vendor ID and symbol ID to the data.
daily_data: List of tuples of the OHLC data (with
adj_close and volume)"""
column_list = ["data_vendor_id", "symbol_id", "price_date", "created_date",
"last_updated_date", "open_price", "high_price", "low_price",
"close_price", "volume", "adj_close_price"]
insert_list = ['%s'] * len(column_str)
values_tuple = (data_vendor_id, symbol_id, daily_data[0], 'now()', 'now()', daily_data[1],
daily_data[2], daily_data[3], daily_data[4], daily_data[5], daily_data[6])
final_str = """INSERT INTO daily_price ({0})
VALUES ({1})
WHERE NOT EXISTS (SELECT 1
FROM daily_price
WHERE symbol_id = %s
AND price_date = %s)""".format(', '.join(column_list), ', '.join(insert_list))
# Using the postgre connection, carry out an INSERT INTO for every symbol
with con:
cur = con.cursor()
cur.execute(final_str, values_tuple, values_tuple[1], values_tuple[2])