Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Nie można poprawnie odczytać tabeli SQL w pythonie:kolumny varchar zaimportowane jako znaki / krotki oddzielone przecinkami

Wydaje się to być problemem podczas korzystania z jaydebeapi z jpype . Mogę to odtworzyć podczas łączenia się z bazą danych Oracle w taki sam sposób, jak ty (w moim przypadku Oracle 11gR2, ale ponieważ używasz ojdbc8.jar , wydaje mi się, że dzieje się tak również z innymi wersjami).

Można to rozwiązać na różne sposoby:

Zmień połączenie

Ponieważ błąd wydaje się występować tylko w określonej kombinacji pakietów, najrozsądniejszą rzeczą do zrobienia jest próba ich uniknięcia, a tym samym całkowitego błędu.

  1. Alternatywna 1:Użyj jaydebeapi bez jpype :

    Jak wspomniano, obserwuję to tylko podczas używania jaydebeapi z jpype . Jednak w moim przypadku jpype w ogóle nie jest potrzebna. Mam plik .jar plik lokalnie, a moje połączenie działa bez niego:

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

    W moim przypadku działa to dobrze i normalnie tworzy ramki danych.

  2. Alternatywna 2:użyj cx_Oracle zamiast tego:

    Problem nie występuje również, jeśli używam cx_Oracle aby połączyć się z bazą danych 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()
    

    Uwaga:dla cx_Oracle aby pracować, musisz mieć Oracle Instant Client zainstalowane i poprawnie skonfigurowane (patrz np. Dokumentacja cx_Oracle dla Ubuntu ).

Napraw ramkę danych po fakcie:

Jeśli z jakiegoś powodu nie możesz użyć powyższych alternatyw połączeń, możesz również przekształcić ramkę danych.

  1. Alternatywna 3:połącz wpisy krotek:

    Możesz użyć ''.join() do konwertowania krotek na ciągi . Musisz to zrobić dla wpisów i nazw kolumn.

    # 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. Alternatywnie 4:zmień typ kolumn:

    Zmieniając dtype danej kolumny z object do string , wszystkie wpisy również zostaną przekonwertowane. Pamiętaj, że może to mieć niepożądane skutki uboczne, takie jak np. zmiana None wartości do ciągu <N/A> . Ponadto będziesz musiał osobno zmienić nazwy nagłówków kolumn, jak powyżej.

    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)
    

Wszystkie te powinny dać mniej więcej to samo df na końcu (oprócz dtypes i możliwe zastąpienie None wartości):

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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. nPLS-00306:zła liczba lub typy argumentów w wywołaniu

  2. Jak zamienić 2 zapytania ze wspólnymi kolumnami (A, B) i (A, C) w jedno (A, B, C)?

  3. BŁĄD Oracle:ORA-00900:nieprawidłowa instrukcja SQL

  4. Czy SELECT FOR UPDATE zapobiega wstawianiu innych połączeń, gdy wiersz nie jest obecny?

  5. Jak wybrać Top 100 wierszy w Oracle?