5

MySQL データベースからプル、処理、および更新するための Python スクリプトを作成しています。

私は当初、MySQL データベースのコンマ区切りの値のダンプを使用してこの問題に取り組み始めました。これを (sqlite3 を使用して) sqlite データベースに投入しました。Python (2.7) で処理を行い、出力の CSV ファイルを作成し、それを別のスクリプトを使用して MySQL データベースにアップロードします。

それなら、Python スクリプトから直接 MySQL データベースにプル/プッシュしようと思いました。だから私はMySQLdbをインストールし、それで町に行きました。

私が今見つけているINSERTのは、MySQL データベースから (sqlite データベースへ) が以前のように結合されていないことです。整数の表現の末尾に L が追加され、小数値は のように表現されますDecimal('4.00')

基本的にJOIN、CSV ファイルから挿入したときにうまくいったものが、今はうまく機能していません。

私の質問: 私はこの道を歩み続ける苦痛の世界を求めていますか、それとも MySQLdb と sqlite3 ライブラリを一緒にプレイする簡単な方法はありますか? ない場合は、MySQL サーバーをインストールし、MySQL のみを使用するようにコードをリファクタリングします。

4

2 に答える 2

6

各データベース バックエンドは、さまざまな種類のデータをサポートしています。sqlite および mysqldb python モジュールは、フィールドの型に基づいて適切な型変換を行うことで、あなたを助けようとします。そのため、mysql データベースに DECIMAL フィールドがある場合、MySQLdb はそのフィールドを Python Decimal オブジェクトとして自動的に返します。

MySQLdb (および必要に応じて sqlite) に、データベースと Python の型の間で適切な型変換を行うように要求できます。どの型変換が適切かを判断するのはあなた次第です。たとえば、データベースには DECIMAL フィールドがあるため、ネイティブの DECIMAL フィールドを持たない sqlite でその値をどのように表現するのでしょうか? おそらく REAL を使用することになりますが、もちろん、これは必要な精度を維持する DECIMAL と同じではありません。

あなたはすでに csv データから変換していたので、Python の float 型を使用していたのではないかと思います。これは、MySQL の 10 進フィールドを float に変換することに満足していることを示しています。この場合、MySQLdb がすべてのフィールド結果で DECIMAL から float への変換を行うように要求できます。

mysqldb と sqlite にそれぞれ 1 つずつ、2 つのテーブルを作成するコードの例を次に示します。MySQL バージョンには DECIMAL フィールドがあります。query_dbs関数で、独自の変換関数を作成する方法を確認できます。

#!/usr/bin/env python

import os
import sqlite3
import MySQLdb
from MySQLdb.constants import FIELD_TYPE

user = os.getenv('USER')

def create_mysql_table():
    conn = MySQLdb.connect(user=user, db='foo')
    c = conn.cursor()
    c.execute("DROP TABLE stocks")
    c.execute("CREATE TABLE stocks"
              "(date text, trans text, symbol text, qty real, price Decimal(10,2) UNSIGNED NOT NULL)")
    c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
    conn.commit()

def create_sqlite_table():
    conn = sqlite3.connect('test.db')
    c = conn.cursor()
    c.execute("DROP TABLE stocks")
    c.execute("CREATE TABLE stocks"
              "(date text, trans text, symbol text, qty real, price real)")
    c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
    conn.commit()

def query_dbs(use_type_converters):
    conn = sqlite3.connect('test.db')
    c = conn.cursor()
    for row in c.execute('SELECT * FROM stocks'):
        print 'SQLITE: %s' % str(row)

    type_converters = MySQLdb.converters.conversions.copy()

    if use_type_converters:
        type_converters.update({
            FIELD_TYPE.DECIMAL: float,
            FIELD_TYPE.NEWDECIMAL: float,
        })

    conn = MySQLdb.connect(user=user, db='foo', conv=type_converters)
    c = conn.cursor()
    c.execute('SELECT * FROM stocks')
    for row in c.fetchall():
        print 'MYSQLDB: %s' % str(row)

create_sqlite_table()
create_mysql_table()

print "Without type conversion:"
query_dbs(False)
print "With type conversion:"
query_dbs(True)

このスクリプトは、私のマシンで次の出力を生成します。

Without type conversion:
SQLITE: (u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.14)
MYSQLDB: ('2006-01-05', 'BUY', 'RHAT', 100.0, Decimal('35.14'))
With type conversion:
SQLITE: (u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.14)
MYSQLDB: ('2006-01-05', 'BUY', 'RHAT', 100.0, 35.14)

これが示しているのは、デフォルトで MySQLdb が Decimal 型を返しているが、sqlite での使用に適した別の型を返すように強制できることです。

次に、2 つのデータベース間ですべての型を正規化すると、結合に関する問題は発生しなくなります。

Python MySQLdb ドキュメントはこちら

于 2013-10-04T05:12:25.193 に答える
2

sqlite3 と MySQLdb の間に競合はないため、同じプログラムで使用できるはずです。ただし、両方の種類のデータベースに高レベルのインターフェイスを提供するSQLAlchemyの使用を検討することもできます。

実際にこの問題が発生している理由に関する限り、あなたが説明する症状は、数値を文字列に誤って変換していることを示唆していrepr()ますstr()

于 2013-10-04T04:59:39.370 に答える