sql >> Databáze >  >> RDS >> Oracle

Nelze správně číst tabulku SQL v pythonu:sloupce varchar importované jako znaky / n-tice oddělené čárkami

To se zdá být problém při použití jaydebeapi pomocí jpype . Mohu to reprodukovat při připojení k databázi Oracle stejným způsobem jako vy (v mém případě Oracle 11gR2, ale protože používáte ojdbc8.jar , předpokládám, že se to stává i u jiných verzí).

Existují různé způsoby, jak to můžete vyřešit:

Změňte připojení

Protože se zdá, že k chybě dochází pouze v určité kombinaci balíčků, nejrozumnější věcí, kterou můžete udělat, je pokusit se vyhnout se těmto chybám a tím i chybě.

  1. Alternativa 1:Použijte jaydebeapi bez jpype :

    Jak bylo uvedeno, pozoruji to pouze při použití jaydebeapi pomocí jpype . Nicméně v mém případě jpype není vůbec potřeba. Mám .jar soubor lokálně a moje připojení bez něj funguje dobře:

    import jaydebeapi as jdba
    import pandas as pd
    import os
    
    db_host = 'db.host.com'
    db_port = 1521
    db_sid = 'YOURSID'
    
    jar=os.getcwd()+'/ojdbc6.jar'
    
    conn = jdba.connect('oracle.jdbc.driver.OracleDriver', 
                    'jdbc:oracle:thin:@' + db_host + ':' + str(db_port) + ':' + db_sid, 
                    {'user': 'USERNAME', 'password': 'PASSWORD'}, 
                    jar
                    )
    
    df_jay = pd.read_sql('SELECT * FROM YOURSID.table1', conn)
    
    conn.close()
    

    V mém případě to funguje dobře a vytváří datové rámce normálně.

  2. Alternativa 2:Použijte cx_Oracle místo toho:

    Problém také nenastane, pokud použiji cx_Oracle pro připojení k databázi Oracle:

    import cx_Oracle
    import pandas as pd
    import os
    
    db_host = 'db.host.com'
    db_port = 1521
    db_sid = 'YOURSID'
    
    dsn_tns = cx_Oracle.makedsn(db_host, db_port, db_sid)
    cx_conn = cx_Oracle.connect('USERNAME', 'PASSWORD', dsn_tns)
    
    df_cxo = pd.read_sql('SELECT * FROM YOURSID.table1', con=cx_conn)
    
    cx_conn.close()
    

    Poznámka:Pro cx_Oracle abyste mohli pracovat, musíte mít Oracle Instant Client nainstalováno a správně nastaveno (viz např. dokumentace cx_Oracle pro Ubuntu ).

Následně opravit datový rámec:

Pokud z nějakého důvodu nemůžete použít výše uvedené alternativy připojení, můžete také transformovat svůj datový rámec.

  1. Alternativa 3:spojení n-ticových záznamů:

    Můžete použít ''.join() jak převést n-tice na řetězce . Musíte to udělat pro položky a názvy sloupců.

    # for all entries that are not None, join the tuples
    for col in df.select_dtypes(include=['object']).columns:
        df[col] = df[col].apply(lambda x: ''.join(x) if x is not None else x)
    
    # also rename the column headings in the same way
    df.rename(columns=lambda x: ''.join(x) if x is not None else x, inplace=True)
    
  2. Alternativa 4:změna dtype sloupců:

    Změnou dtype ovlivněného sloupce z object na string , budou také převedeny všechny položky. Upozorňujeme, že to může mít nežádoucí vedlejší účinky, jako např. změna None hodnoty do řetězce <N/A> . Také budete muset samostatně přejmenovat záhlaví sloupců, jak je uvedeno výše.

    for col in df.select_dtypes(include=['object']).columns:
        df[col] = df[col].astype('string')
    
    # again, rename headings
    df.rename(columns=lambda x: ''.join(x) if x is not None else x, inplace=True)
    

Všechny by měly přinést víceméně stejné df nakonec (kromě dtypes a možné nahrazení None hodnoty):

+---+---------+---------+---------+
|   | COLUMN1 | COLUMN2 | COLUMN3 |
+---+---------+---------+---------+
| 1 | test    | test2   | 1       |
+---+---------+---------+---------+
| 2 | foo     | bar     | 100     |
+---+---------+---------+---------+



  1. MySQL JOIN pouze k nejnovějšímu řádku?

  2. MySQL WHERE IN Query - ORDER BY Match

  3. MySQL s Entity Framework 6

  4. Optimalizujte dotazy MySQL pomocí mnoha LEFT JOINů a GROUP BY