sql >> Databasteknik >  >> RDS >> Oracle

Kan inte läsa SQL-tabellen ordentligt i python:varchar-kolumner importerade som kommaseparerade tecken/tupler

Detta verkar vara ett problem när du använder jaydebeapi med jpype . Jag kan återskapa detta när jag ansluter till en Oracle db på samma sätt som du gör (i mitt fall Oracle 11gR2, men eftersom du använder ojdbc8.jar , jag antar att det också händer med andra versioner).

Det finns olika sätt du kan lösa detta på:

Ändra din anslutning

Eftersom felet bara verkar uppstå i en specifik kombination av paket är det mest förnuftiga att försöka undvika dessa och därmed felet helt och hållet.

  1. Alternativ 1:Använd jaydebeapi utan jpype :

    Som nämnts observerar jag detta bara när jag använder jaydebeapi med jpype . Men i mitt fall, jpype behövs inte alls. Jag har .jar fil lokalt och min anslutning fungerar bra utan den:

    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()
    

    I mitt fall fungerar detta bra och skapar dataramarna normalt.

  2. Alternativ 2:Använd cx_Oracle istället:

    Problemet uppstår inte heller om jag använder cx_Oracle för att ansluta till Oracle db:

    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()
    

    Obs:För cx_Oracle för att fungera måste du ha Oracle Instant Client installerad och korrekt inställd (se t.ex. cx_Oracle-dokumentation för Ubuntu ).

Åtgärda dataramen i efterhand:

Om du av någon anledning inte kan använda ovanstående anslutningsalternativ kan du också transformera din dataram.

  1. Alternativ 3:gå med i tupelinlägg:

    Du kan använda ''.join() för att konvertera tupler till strängar . Du måste göra detta för posterna och kolumnnamnen.

    # 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. Alternativ 4:ändra dtyp av kolumner:

    Genom att ändra dtype för en påverkad kolumn från object till string , kommer alla poster också att konverteras. Observera att detta kan ha oönskade biverkningar, som t.ex. ändra None värden till strängen <N/A> . Du måste också byta namn på kolumnrubrikerna separat, enligt ovan.

    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)
    

Alla dessa borde ge mer eller mindre samma df i slutändan (bortsett från dtypes och möjlig ersättning av None värden):

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



  1. SQL är det möjligt att jämföra beställningar per timme och ta bort aktuellt lager?

  2. Sanering vid lagring av serialiserad array

  3. Migrera postgres dump till RDS

  4. Sök i en JSON-array efter ett objekt som innehåller ett värde som matchar ett mönster