2015-06-16 8 views
10

मैं जो एक प्राथमिक कुंजी है पांडा 'to_sql समारोह के साथ एक MySQL तालिका बनाने के लिए चाहते हैं (यह एक mysql तालिका में प्राथमिक कुंजी के लिए आम तौर पर एक तरह से अच्छा है) के रूप में तो:पायथन पांडस to_sql, प्राथमिक कुंजी के साथ तालिका कैसे बनाएं?

group_export.to_sql(con = db, name = config.table_group_export, if_exists = 'replace', flavor = 'mysql', index = False) 

लेकिन इस बनाता है किसी भी प्राथमिक कुंजी के बिना एक टेबल, (या किसी भी सूचकांक के बिना भी)।

प्रलेखन indel_label पैरामीटर का उल्लेख करता है जिसका उपयोग इंडेक्स बनाने के लिए किया जा सकता है लेकिन प्राथमिक कुंजी के लिए किसी भी विकल्प का उल्लेख नहीं करता है।

Documentation

+3

@unutbu मैं 'सूचकांक = TRUE' बस सुनिश्चित करता सूचकांक तालिका में लिखा है लगता है और यह एसक्यूएल में एक सूचकांक है, और अभी तक नहीं है कि एक प्राथमिक कुंजी – joris

+0

हाँ, सूचकांक सिर्फ पंक्ति संख्या के रूप में उपयोग करता है एक सूचकांक जो मैं नहीं चाहता हूं। –

+3

अभी के लिए, प्राथमिक कुंजी निर्दिष्ट करने के लिए अभी तक समर्थन नहीं है (यह सुविधा इच्छासूची पर है)। पहले तालिका बनाने के लिए संभावित वर्कअराउंड, और फिर 'to_sql' में 'append' विकल्प का उपयोग करें। तालिका बनाने के लिए, 'pd.io.sql.get_schema' स्कीमा बनाने के लिए सहायक हो सकता है (जिसे तब तालिका बनाने के लिए अनुकूलित/निष्पादित किया जा सकता है) – joris

उत्तर

8

अस्वीकरण: इस सवाल का जवाब अधिक प्रयोगात्मक तो व्यावहारिक, लेकिन शायद उल्लेख के लायक है।

मुझे लगता है कि वर्ग pandas.io.sql.SQLTable तर्क key का नाम दिया है मिल गया है और यदि आप इसे फ़ील्ड का नाम आवंटित तो इस क्षेत्र प्राथमिक कुंजी हो जाता है:

दुर्भाग्य से तुम सिर्फ DataFrame.to_sql() समारोह से इस तर्क को स्थानांतरित नहीं कर सकते। इसका इस्तेमाल करने के लिए आपको:

  1. pandas.io.SQLDatabase उदाहरण बनाने

    engine = sa.create_engine('postgresql:///somedb') 
    pandas_sql = pd.io.sql.pandasSQL_builder(engine, schema=None, flavor=None) 
    
  2. pandas.io.SQLDatabase.to_sql() के लिए, लेकिन अतिरिक्त *kwargs तर्क जो (मैं सिर्फ मूल कॉपी किया है pandas.io.SQLTable इसके अंदर बनाई गई वस्तु को पारित कर दिया है के साथ समारोह analoguous को परिभाषित to_sql() विधि और *kwargs जोड़ा गया):

    def to_sql_k(self, frame, name, if_exists='fail', index=True, 
          index_label=None, schema=None, chunksize=None, dtype=None, **kwargs): 
        if dtype is not None: 
         from sqlalchemy.types import to_instance, TypeEngine 
         for col, my_type in dtype.items(): 
          if not isinstance(to_instance(my_type), TypeEngine): 
           raise ValueError('The type of %s is not a SQLAlchemy ' 
               'type ' % col) 
    
        table = pd.io.sql.SQLTable(name, self, frame=frame, index=index, 
            if_exists=if_exists, index_label=index_label, 
            schema=schema, dtype=dtype, **kwargs) 
        table.create() 
        table.insert(chunksize) 
    
  3. कॉल अपने SQLDatabase उदाहरण के साथ इस समारोह और dataframe आप

    to_sql_k(pandas_sql, df2save, 'tmp', 
         index=True, index_label='id', keys='id', if_exists='replace') 
    

सहेजना चाहते और हम जैसे

CREATE TABLE public.tmp 
(
    id bigint NOT NULL DEFAULT nextval('tmp_id_seq'::regclass), 
... 
) 
डेटाबेस में

कुछ मिलता है।

पीएस आप निश्चित रूप से बंदर-पैच DataFrame, io.SQLDatabase और io.to_sql() सुविधा के साथ इस कार्यवाही का उपयोग करने के लिए कार्य कर सकते हैं।

metadata = MetaData() 
metadata.reflect(db.engine, only=tableNamesDict.values()) 
Base = automap_base(metadata=metadata) 
Base.prepare() 

जो पूरी तरह से काम किया होता, एक समस्या के अलावा, automap तालिकाओं की आवश्यकता है एक प्राथमिक कुंजी के लिए:

+1

अच्छा। धन्यवाद। अंत में हालांकि मुझे पहले टेबल बनाने और इसे जोड़ने के लिए आसान लगता है। –

+1

मैं यह भी उम्मीद कर रहा था कि to_sql का index_label विकल्प मदद करेगा। –

+1

ग्रेट उत्तर, दुर्भाग्य से यह MySQL के साथ काम नहीं करता है यदि कुंजी कॉलम एक टेक्स्ट प्रकार है क्योंकि पांडा में कुंजी लंबाई निर्दिष्ट करने का कोई तरीका नहीं है। यह त्रुटि 1170 देता है, "मुख्य लंबाई के बिना मुख्य विनिर्देश में उपयोग किए गए BLOB/टेक्स्ट कॉलम" – danio

0

sqlalchemy.ext.automap से automap_base (tableNamesDict केवल पांडा टेबल के साथ एक dict है)। ठीक है, कोई समस्या नहीं, मुझे यकीन है कि पांडस to_sql प्राथमिक कुंजी को इंगित करने का एक तरीका है ... नहीं। यह जहां यह एक छोटे hacky हो जाता है:

for df in dfs.keys(): 
    cols = dfs[df].columns 
    cols = [str(col) for col in cols if 'id' in col.lower()] 
    schema = pd.io.sql.get_schema(dfs[df],df, con=db.engine, keys=cols) 
    db.engine.execute('DROP TABLE ' + df + ';') 
    db.engine.execute(schema) 
    dfs[df].to_sql(df,con=db.engine, index=False, if_exists='append') 

मैं DataFrames की dict के माध्यम से पुनरावृति, प्राथमिक कुंजी के लिए उपयोग करने के लिए कॉलम की एक सूची प्राप्त (अर्थातid युक्त), खाली तालिका बनाने के लिए get_schema का उपयोग करें, फिर तालिका में DataFrame संलग्न करें।

अब आप मॉडल है कि, आप स्पष्ट रूप से नाम और उन्हें session.query साथ (यानी User = Base.classes.user) का उपयोग करें या कुछ इस तरह के साथ सभी वर्गों के एक dict बना सकते हैं: साथ

alchemyClassDict = {} 
for t in Base.classes.keys(): 
    alchemyClassDict[t] = Base.classes[t] 

और क्वेरी:

res = db.session.query(alchemyClassDict['user']).first() 
+2

[pd.io.sql.get_schema सार्वजनिक इंटरफ़ेस में नहीं है] (https://github.com/pydata/pandas/issues/ 9960) इस पर भरोसा करने के लिए अच्छा नहीं है। कोड भी तभी काम करेगा यदि डेटाफ्रेम में इंडेक्स नहीं है। अन्यथा 'schema = pd.io.sql.get_schema (df.reset_index(), table_name, con = db.engine, keys = cols जैसे कुछ का उपयोग करना होगा' – danio

11

बस पांडा के साथ तालिका अपलोड करने के बाद प्राथमिक कुंजी जोड़ें।

group_export.to_sql(con=engine, name=example_table, if_exists='replace', 
        flavor='mysql', index=False) 

with engine.connect() as con: 
    con.execute('ALTER TABLE `example_table` ADD PRIMARY KEY (`ID_column`);') 
संबंधित मुद्दे