2014-07-07 2 views
0

저는 MySQL을 처음 사용하지만 파이썬에서 탄탄한 기반을 갖추고 있습니다. 많은 stackoverflow 질문과 답변을 읽는 것을 포함하여 지난 2 일 동안 이것을 광범위하게 조사한 후에도이 문제를 해결할 수 없었으므로이 문제와 관련된 도움을 주시면 감사하겠습니다. 업데이트 됨 : 오류는 아래에 게시됩니다.MySQL과 Python에서 중복 항목 오류가 발생합니다. 해결할 수 없습니다.

나는 야후로부터 일일 가격 데이터를 검색하고 해당 테이블에 데이터를 입력하는 데이터베이스를 만들려고하고있다.

MySQL 테이블과 데이터베이스는 MySQL Workbench 6.1을 사용하여 생성되었습니다. Windows 8.1 64 비트에서 Python 2.7 Anaconda 배포를 사용하고 있습니다.

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 MySQL 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) 
    ''' 

    # Create the time now 
    now = datetime.datetime.utcnow() 

    # Amend the data to include the vendor ID and symbol ID 
    daily_data = [(data_vendor_id, symbol_id, d[0], now, now, 
        d[1], d[2], d[3], d[4], d[5], d[6]) for d in daily_data] 

    # Create the insert strings 
    column_str = '''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_str = ('%s, ' * 11)[:-2] 
    final_str = 'INSERT INTO daily_price (%s) VALUES (%s)' % \ 
       (column_str, insert_str) 

    # Using the MySQL connection, carry out an INSERT INTO for every symbol 
    with con: 
     cur = con.cursor() 
     cur.executemany(final_str, daily_data) 

if __name__ == '__main__': 
    # Loop over the tickers and insert the daily historical data into the database 
    tickers = obtain_list_of_db_tickers() 
    for t in tickers: 
     print 'Adding data for %s' % t[1] 
     yf_data = get_daily_historic_data_yahoo(t[1]) 
     insert_daily_data_into_db('1', t[0], yf_data) # I believe the error is here relating to the data vendor id # but am unclear on the method to solve the problem 

오류 코드 :

Adding data for ABT 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "C:\Users\Owner\Anaconda\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 585, in runfile 
    execfile(filename, namespace) 
    File "C:/Users/Owner/Documents/Python Scripts/price_retrieval_mine.py", line 99, in <module> 
    insert_daily_data_into_db('1', t[0], yf_data) 
    File "C:/Users/Owner/Documents/Python Scripts/price_retrieval_mine.py", line 91, in insert_daily_data_into_db 
    cur.executemany(final_str, daily_data) 
    File "C:\Users\Owner\Anaconda\lib\site-packages\MySQLdb\cursors.py", line 262, in executemany 
    r = self._query('\n'.join([query[:p], ',\n'.join(q), query[e:]])) 
    File "C:\Users\Owner\Anaconda\lib\site-packages\MySQLdb\cursors.py", line 354, in _query 
    rowcount = self._do_query(q) 
    File "C:\Users\Owner\Anaconda\lib\site-packages\MySQLdb\cursors.py", line 318, in _do_query 
    db.query(q) 
_mysql_exceptions.IntegrityError: (1062, "Duplicate entry '1' for key 'data_vendor_id_UNIQUE'") 

UPDATED 출력하여 SQL 명령

여기
-- ----------------------------------------------------- 
-- Table `securities_master_00`.`daily_price` 
-- ----------------------------------------------------- 
CREATE TABLE IF NOT EXISTS `securities_master_00`.`daily_price` (
    `id` INT NOT NULL AUTO_INCREMENT, 
    `data_vendor_id` INT NOT NULL, 
    `symbol_id` INT NOT NULL, 
    `price_date` DATETIME NOT NULL, 
    `created_date` DATETIME NOT NULL, 
    `last_updated_date` DATETIME NOT NULL, 
    `open_price` DECIMAL(19,4) NULL DEFAULT NULL, 
    `high_price` DECIMAL(19,4) NULL DEFAULT NULL, 
    `low_price` DECIMAL(19,4) NULL DEFAULT NULL, 
    `close_price` DECIMAL(19,4) NULL DEFAULT NULL, 
    `adj_close_price` DECIMAL(19,4) NULL DEFAULT NULL, 
    `volume` BIGINT NULL DEFAULT NULL, 
    INDEX `index_data_vendor_id_idx` (`data_vendor_id` ASC), 
    PRIMARY KEY (`id`), 
    INDEX `index_symbol_id_idx` (`symbol_id` ASC), 
    CONSTRAINT `index_data_vendor_id` 
    FOREIGN KEY (`data_vendor_id`) 
    REFERENCES `securities_master_00`.`data_vendor` (`id`) 
    ON DELETE NO ACTION 
    ON UPDATE CASCADE, 
    CONSTRAINT `index_symbol_id` 
    FOREIGN KEY (`symbol_id`) 
    REFERENCES `securities_master_00`.`symbol` (`id`) 
    ON DELETE NO ACTION 
    ON UPDATE CASCADE) 
ENGINE = InnoDB 
DEFAULT CHARACTER SET = utf8; 

오류를 생성하는 대응 파이썬 코드이다 : 여기

는 MySQL의 테이블 : SHOW INDEXES FROM securities_master_00.daily_price

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part   Packed Null Index_type 
    daily_price 0 PRIMARY 1 id A 2 NULL NULL  BTREE 
    daily_price 0 data_vendor_id_UNIQUE 1 data_vendor_id A 2 NULL NULL  BTREE 
    daily_price 0 symbol_id_UNIQUE 1 symbol_id A 2 NULL NULL  BTREE 
    daily_price 1 index_data_vendor_id_idx 1 data_vendor_id A 2 NULL NULL  BTREE 
    daily_price 1 index_symbol_id_idx 1 symbol_id A 2 NULL NULL  BTREE 
+0

문제가 무엇인지 알려주는 것을 잊어 버린 것 같습니다. –

+0

python 오류를 포함하도록 질문이 업데이트되었습니다. 다니엘 고마워. – BCR

+0

오류가 당신의'CREATE TABLE' 문에 나타나지 않는 키를보고하고 있습니다. 'securities_master_00.daily_price'의'SHOW INDEXES FROM securities'의 결과는 무엇입니까? – Air

답변

1

SHOW INDEXES 성명 결과에 나와 있듯이 CREATE TABLE 문에는 3 개만 선언되었지만 테이블에는 5 개의 색인이 있습니다. 두 개의 추가 색인은 외래 키 열의 UNIQUE 색인입니다. 이는 daily_price 테이블과 data_vendorsymbol 테이블 사이에 다 대일 관계가 있어야하기 때문에 문제가됩니다. 이것은 많은 공급 업체가 동일한 공급 업체에 의해 생성되며 일정 기간 동안 동일한 기호에 대해 생성된다는 사실을 반영합니다. DROP, 또는 대안으로 daily_price 표를 당신이이 질문에 게시 테이블 정의를 사용하여 다시 - -

당신은 DROP 이러한 추가 인덱스 둘 필요 당신이에 행을 삽입하려고하면 IntegrityError을 던지는 중지하기 위해 표.

테이블에 data_vendor_id_UNIQUE 색인을 추가하면 동일한 테이블에 두 개의 행 (동일한 data_vendor_id)을 사용할 수 없습니다. Python 코드의 마지막 줄 (아마도 data_vendor 테이블의 Yahoo! 항목에 해당)에 따르면 Yahoo의 데이터를 삽입하는 모든 행에 data_vendor_id = 1이 있으므로 삽입하려고하는 두 번째 행은 해당 색인의 고유 제한 조건을 위반하여 여기에 보이는 오류.

특히이 프로젝트에서 다른 사람과 함께 작업하거나 다른 사람의 코드를 사용하는 경우 이러한 추가 색인이 어디서 왔는지 파악하는 것이 좋습니다. 이 오류 뒤에 숨어있는 명백한 문제가있을 수 있습니다.

마지막으로, MySQL에 대해 진지한 작업을 수행하려는 경우 인덱스, 작동 방식 및 사용시기에 대해 배우는 것이 좋습니다. 쿼리 실행 계획에 관해서는 SHOW INDEXES 및 특히 EXPLAIN과 같은 문구에 익숙해 지도록 노력해야합니다. 그러면 이와 같은 오류를 쉽고 빠르게 진단 할 수 있습니다.

관련 문제