"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > قم بالوصول إلى قاعدة بيانات IRIS باستخدام ODBC أو JDBC باستخدام Python

قم بالوصول إلى قاعدة بيانات IRIS باستخدام ODBC أو JDBC باستخدام Python

تم النشر بتاريخ 2024-11-15
تصفح:596

Access IRIS database with ODBC or JDBC using Python

مشاكل مع السلاسل

أقوم بالوصول إلى قواعد بيانات IRIS باستخدام JDBC (أو ODBC) باستخدام Python. أرغب في جلب البيانات إلى إطار بيانات pandas لمعالجة البيانات وإنشاء مخططات منها. لقد واجهت مشكلة في التعامل مع السلسلة أثناء استخدام JDBC. هذه المشاركة هي للمساعدة إذا كان أي شخص آخر لديه نفس المشاكل. أو إذا كانت هناك طريقة أسهل لحل هذه المشكلة، فأخبرني بها في التعليقات!

أنا أستخدم OSX، لذلك لست متأكدًا من مدى تميز مشكلتي. أنا أستخدم Jupyter Notebooks، على الرغم من أن الكود سيكون هو نفسه بشكل عام إذا كنت تستخدم أي برنامج أو إطار عمل آخر لـ Python.

مشكلة JDBC

عندما أقوم بإحضار البيانات من قاعدة البيانات، يتم إرجاع أوصاف الأعمدة وأي بيانات سلسلة كنوع بيانات java.lang.String. إذا قمت بطباعة بيانات سلسلة البيانات فستبدو كما يلي: "(p,a,i,n,i,n,t,h,e,r,e,a,r)" بدلاً من "painintherear" المتوقع.

ربما يرجع هذا إلى أن سلاسل الأحرف من نوع البيانات java.lang.String تأتي كمصفوفة أو قابلة للتكرار عند جلبها باستخدام JDBC. يمكن أن يحدث هذا إذا كان جسر Python-Java الذي تستخدمه (على سبيل المثال، JayDeBeApi، JDBC) لا يقوم تلقائيًا بتحويل java.lang.String إلى سلسلة Python في خطوة واحدة.

في المقابل، تمثيل سلسلة str في بايثون يحتوي على السلسلة بأكملها كوحدة واحدة. عندما تسترد بايثون سلسلة عادية (على سبيل المثال عبر ODBC)، فإنها لا تنقسم إلى أحرف فردية.

حل JDBC

لإصلاح هذه المشكلة، يجب عليك التأكد من تحويل java.lang.String بشكل صحيح إلى نوع str الخاص بـ Python. يمكنك التعامل بشكل صريح مع هذا التحويل عند معالجة البيانات التي تم جلبها بحيث لا يتم تفسيرها على أنها قابلة للتكرار أو قائمة من الأحرف.

هناك العديد من الطرق للقيام بهذه المعالجة للسلسلة؛ وهذا ما فعلته.

import pandas as pd

import pyodbc

import jaydebeapi
import jpype

def my_function(jdbc_used)

    # Some other code to create the connection goes here

    cursor.execute(query_string)

    if jdbc_used:
        # Fetch the results, convert java.lang.String in the data to Python str
        # (java.lang.String is returned "(p,a,i,n,i,n,t,h,e,r,e,a,r)" Convert to str type "painintherear"
        results = []
        for row in cursor.fetchall():
            converted_row = [str(item) if isinstance(item, jpype.java.lang.String) else item for item in row]
            results.append(converted_row)

        # Get the column names and ensure they are Python strings 
        column_names = [str(col[0]) for col in cursor.description]

        # Create the dataframe
        df = pd.DataFrame.from_records(results, columns=column_names)

        # Check the results
        print(df.head().to_string())

    else:  
        # I was also testing ODBC
        # For very large result sets get results in chunks using cursor.fetchmany(). or fetchall()
        results = cursor.fetchall()
        # Get the column names
        column_names = [column[0] for column in cursor.description]
        # Create the dataframe
        df = pd.DataFrame.from_records(results, columns=column_names)

    # Do stuff with your dataframe

مشكلة ODBC

عند استخدام اتصال ODBC، لا يتم إرجاع السلاسل أو تكون غير متوفرة.

إذا كنت تتصل بقاعدة بيانات تحتوي على بيانات Unicode (على سبيل المثال، أسماء بلغات مختلفة) أو إذا كان تطبيقك يحتاج إلى تخزين أو استرداد أحرف غير ASCII، فيجب عليك التأكد من بقاء البيانات مشفرة بشكل صحيح عند تمريرها بين قاعدة البيانات وتطبيق بايثون الخاص بك.

الحل ODBC

يضمن هذا الرمز تشفير بيانات السلسلة وفك تشفيرها باستخدام UTF-8 عند إرسال البيانات واسترجاعها إلى قاعدة البيانات. وهذا مهم بشكل خاص عند التعامل مع أحرف غير ASCII أو ضمان التوافق مع بيانات Unicode.

def create_connection(connection_string, password):
    connection = None

    try:
        # print(f"Connecting to {connection_string}")
        connection = pyodbc.connect(connection_string   ";PWD="   password)

        # Ensure strings are read correctly
        connection.setdecoding(pyodbc.SQL_CHAR, encoding="utf8")
        connection.setdecoding(pyodbc.SQL_WCHAR, encoding="utf8")
        connection.setencoding(encoding="utf8")

    except pyodbc.Error as e:
        print(f"The error '{e}' occurred")

    return connection

connection.setdecoding(pyodbc.SQL_CHAR, encoding="utf8")

يخبر pyodbc كيفية فك تشفير بيانات الأحرف من قاعدة البيانات عند جلب أنواع SQL_CHAR (عادةً، حقول الأحرف ذات الطول الثابت).

connection.setdecoding(pyodbc.SQL_WCHAR, encoding="utf8")

تعيين فك التشفير لـ SQL_WCHAR، وأنواع الأحرف العريضة (أي سلاسل Unicode، مثل NVARCHAR أو NCHAR في SQL Server).

connection.setencoding(encoding="utf8")

يضمن أن أي سلاسل أو بيانات أحرف مرسلة من Python إلى قاعدة البيانات سيتم تشفيرها باستخدام UTF-8،
وهذا يعني أن بايثون ستترجم نوع str الداخلي الخاص بها (وهو Unicode) إلى بايت UTF-8 عند الاتصال بقاعدة البيانات.


وضع كل ذلك معا

قم بتثبيت JDBC

تثبيت جافا - استخدم dmg

https://www.Oracle.com/middleeast/Java/technologies/downloads/#jdk23-mac

تحديث الصدفة لتعيين الإصدار الافتراضي

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (2):
    23 (arm64) "Oracle Corporation" - "Java SE 23" /Library/Java/JavaVirtualMachines/jdk-23.jdk/Contents/Home
    1.8.421.09 (arm64) "Oracle Corporation" - "Java" /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home
/Library/Java/JavaVirtualMachines/jdk-23.jdk/Contents/Home
$ echo $SHELL
/opt/homebrew/bin/bash
$ vi ~/.bash_profile

أضف Java_HOME إلى المسار الخاص بك

export JAVA_HOME=$(/usr/libexec/java_home -v 23)
export PATH=$JAVA_HOME/bin:$PATH

الحصول على برنامج تشغيل JDBC

https://intersystems-community.github.io/iris-driver-distribution/

ضع ملف الجرة في مكان ما... لقد وضعته في $HOME

$ ls $HOME/*.jar
/Users/myname/intersystems-jdbc-3.8.4.jar

رمز العينة

يفترض أنك قمت بإعداد ODBC (مثال ليوم آخر، أكل الكلب ملاحظاتي...).

ملاحظة: هذا اختراق للشفرة الحقيقية الخاصة بي. لاحظ أسماء المتغيرات.

import os

import datetime
from datetime import date, time, datetime, timedelta

import pandas as pd
import pyodbc

import jaydebeapi
import jpype

def jdbc_create_connection(jdbc_url, jdbc_username, jdbc_password):

    # Path to JDBC driver
    jdbc_driver_path = '/Users/yourname/intersystems-jdbc-3.8.4.jar'

    # Ensure JAVA_HOME is set
    os.environ['JAVA_HOME']='/Library/Java/JavaVirtualMachines/jdk-23.jdk/Contents/Home'
    os.environ['CLASSPATH'] = jdbc_driver_path

    # Start the JVM (if not already running)
    if not jpype.isJVMStarted():
        jpype.startJVM(jpype.getDefaultJVMPath(), classpath=[jdbc_driver_path])

    # Connect to the database
    connection = None

    try:
        connection = jaydebeapi.connect("com.intersystems.jdbc.IRISDriver",
                                  jdbc_url,
                                  [jdbc_username, jdbc_password],
                                  jdbc_driver_path)
        print("Connection successful")
    except Exception as e:
        print(f"An error occurred: {e}")

    return connection


def odbc_create_connection(connection_string):
    connection = None

    try:
        # print(f"Connecting to {connection_string}")
        connection = pyodbc.connect(connection_string)

        # Ensure strings are read correctly
        connection.setdecoding(pyodbc.SQL_CHAR, encoding="utf8")
        connection.setdecoding(pyodbc.SQL_WCHAR, encoding="utf8")
        connection.setencoding(encoding="utf8")

    except pyodbc.Error as e:
        print(f"The error '{e}' occurred")

    return connection

# Parameters

odbc_driver = "InterSystems ODBC"
odbc_host = "your_host"
odbc_port = "51773"
odbc_namespace = "your_namespace"
odbc_username = "username"
odbc_password = "password"

jdbc_host = "your_host"
jdbc_port = "51773"
jdbc_namespace = "your_namespace"
jdbc_username = "username"
jdbc_password = "password"

# Create connection and create charts

jdbc_used = True

if jdbc_used:
    print("Using JDBC")
    jdbc_url = f"jdbc:IRIS://{jdbc_host}:{jdbc_port}/{jdbc_namespace}?useUnicode=true&characterEncoding=UTF-8"
    connection = jdbc_create_connection(jdbc_url, jdbc_username, jdbc_password)
else:
    print("Using ODBC")
    connection_string = f"Driver={odbc_driver};Host={odbc_host};Port={odbc_port};Database={odbc_namespace};UID={odbc_username};PWD={odbc_password}"
    connection = odbc_create_connection(connection_string)


if connection is None:
    print("Unable to connect to IRIS")
    exit()

cursor = connection.cursor()

site = "SAMPLE"
table_name = "your.TableNAME"

desired_columns = [
    "RunDate",
    "ActiveUsersCount",
    "EpisodeCountEmergency",
    "EpisodeCountInpatient",
    "EpisodeCountOutpatient",
    "EpisodeCountTotal",
    "AppointmentCount",
    "PrintCountTotal",
    "site",
]

# Construct the column selection part of the query
column_selection = ", ".join(desired_columns)

query_string = f"SELECT {column_selection} FROM {table_name} WHERE Site = '{site}'"

print(query_string)
cursor.execute(query_string)

if jdbc_used:
    # Fetch the results
    results = []
    for row in cursor.fetchall():
        converted_row = [str(item) if isinstance(item, jpype.java.lang.String) else item for item in row]
        results.append(converted_row)

    # Get the column names and ensure they are Python strings (java.lang.String is returned "(p,a,i,n,i,n,t,h,e,a,r,s,e)"
    column_names = [str(col[0]) for col in cursor.description]

    # Create the dataframe
    df = pd.DataFrame.from_records(results, columns=column_names)
    print(df.head().to_string())
else:
    # For very large result sets get results in chunks using cursor.fetchmany(). or fetchall()
    results = cursor.fetchall()
    # Get the column names
    column_names = [column[0] for column in cursor.description]
    # Create the dataframe
    df = pd.DataFrame.from_records(results, columns=column_names)

    print(df.head().to_string())

# # Build charts for a site
# cf.build_7_day_rolling_average_chart(site, cursor, jdbc_used)

cursor.close()
connection.close()

# Shutdown the JVM (if you started it)
# jpype.shutdownJVM()
بيان الافراج تم إعادة إنتاج هذه المقالة على: https://dev.to/intersystems/access-iris-database-with-odbc-or-jdbc-using-python-54ok?1 إذا كان هناك أي انتهاك، يرجى الاتصال بـ [email protected] لحذفه
أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3