Скопируйте или перенесите таблицы из базы данных MySQL в Oracle 11g и наоборот, используя Python - PullRequest
0 голосов
/ 31 января 2020

Я прошу прощения, если вопрос был задан ранее, я попытался с помощью Google и прочитал довольно много ответов на stackoverflow, но ни один не был так конкретно, как c, как мой.

Итак, в чем проблема? Ну, у меня есть этот проект в python, и я хотел бы реализовать одну из копий таблиц из одной базы данных в другую со всеми ее ограничениями, а что нет.

Что касается того, что я пробовал, я пытался использовать etlalchemy, но он недоступен для windows. Я думал о сохранении таблиц в pandas фреймах данных и использовании to_ sql, но я не уверен в точности копий.

Я думал о sqlalchemy и alembi c, но на самом деле не нашел учебника о том, как это сделать.

Что касается систем баз данных, которые я использую. На моем компьютере установлены MySQL Workbench 8.0 CE и Oracle 11g.

В основном я хочу скопировать или перенести таблицы со всеми их ключами, ограничениями и т. Д. c .. из одной базы данных в другой использует Python 3.x. Спасибо за ваше время.

Это код, с которым я работаю:

from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QCoreApplication
from sqlalchemy import types, create_engine
import MySQLdb
import cx_Oracle
import pandas as pd
import sys

mySQLConn = MySQLdb.connect(host="localhost",    # your host, usually localhost 
                     user="user",         # your username
                     passwd="pass",  # your password
                     db="sakila")        # name of the data base

#dsn_tns = cx_Oracle.makedsn('user', '1521', service_name='XE')
dsn_tns = cx_Oracle.makedsn('localhost', '1521', service_name='XE')
myOracleConn = cx_Oracle.connect(user=r'user', password='pass', dsn=dsn_tns) 

#conn = create_engine('oracle+cx_oracle://user:pass@host:1521/?service_name=servicename')

class PandasModel(QtCore.QAbstractTableModel): 
    def __init__(self, df = pd.DataFrame(), parent=None): 
        QtCore.QAbstractTableModel.__init__(self, parent=parent)
        self._df = df.copy()

    def toDataFrame(self):
        return self._df.copy()

    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if role != QtCore.Qt.DisplayRole:
            return QtCore.QVariant()

        if orientation == QtCore.Qt.Horizontal:
            try:
                return self._df.columns.tolist()[section]
            except (IndexError, ):
                return QtCore.QVariant()
        elif orientation == QtCore.Qt.Vertical:
            try:
                # return self.df.index.tolist()
                return self._df.index.tolist()[section]
            except (IndexError, ):
                return QtCore.QVariant()

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if role != QtCore.Qt.DisplayRole:
            return QtCore.QVariant()

        if not index.isValid():
            return QtCore.QVariant()

        return QtCore.QVariant(str(self._df.ix[index.row(), index.column()]))

    def setData(self, index, value, role):
        row = self._df.index[index.row()]
        col = self._df.columns[index.column()]
        if hasattr(value, 'toPyObject'):
            # PyQt4 gets a QVariant
            value = value.toPyObject()
        else:
            # PySide gets an unicode
            dtype = self._df[col].dtype
            if dtype != object:
                value = None if value == '' else dtype.type(value)
        self._df.set_value(row, col, value)
        return True

    def rowCount(self, parent=QtCore.QModelIndex()): 
        return len(self._df.index)

    def columnCount(self, parent=QtCore.QModelIndex()): 
        return len(self._df.columns)

    def sort(self, column, order):
        colname = self._df.columns.tolist()[column]
        self.layoutAboutToBeChanged.emit()
        self._df.sort_values(colname, ascending= order == QtCore.Qt.AscendingOrder, inplace=True)
        self._df.reset_index(inplace=True, drop=True)
        self.layoutChanged.emit()

#class usefulDatabaseFunctions():


#    emptyDatabase = ""

    #def getMySQLTables:



class usefulFunctions():

    def connectToMySQL(self): 
        window.label.setText("Connected to MySQL")
        window.setStyleSheet('QLabel#label {color: Green}')
        #cur = db.cursor() 
        #cur.execute("SELECT * FROM actor")
        #print(cur.fetchall())

    def disconnectMySQL(self):
        mySQLConn.close()
        window.label.setText("Disconnected from MySQL")
        window.setStyleSheet('QLabel#label {color: Red}')
        print("Disconnected")

    def connectToOracle(self): 
        window.label.setText("Connected to Oracle")
        window.setStyleSheet('QLabel#label {color: Green}')
        #cursorOracle = myOracleConn.cursor()
        #cursorOracle.execute("SELECT * FROM countries")
        #print(cursorOracle.fetchall())

    def disconnectOracle(self):
        window.label.setText("Disconnected from Oracle")
        window.setStyleSheet('QLabel#label {color: Red}')
        myOracleConn.close()

#    def clearWork(self):  
#        window.queryTextEdit.setText("")
#        window.resultsTextEdit.setText("")
#        window.tableView.clearSpans()
#        window.tableView.clear()

    def executeMySQLUserQuery(self):
        userQuery = window.queryTextEdit.toPlainText()
        cursorMySQL = mySQLConn.cursor()
        cursorMySQL.execute(userQuery)
        print(cursorMySQL.fetchall())
        df = pd.read_sql(userQuery, con = mySQLConn)
        print(df.to_string())
        #txtQueryResults = df.to_string()
        txtQueryResults = str(cursorMySQL.fetchall())
        window.resultsTextEdit.setPlainText(txtQueryResults)
        model = PandasModel(df)
        window.tableView.setModel(model)

    def executeOracleUserQuery(self):
        userQuery = window.queryTextEdit.toPlainText()
        cursorOracle = myOracleConn.cursor()
        cursorOracle.execute(userQuery)
        print(cursorOracle.fetchall())
        df = pd.read_sql(userQuery, con = myOracleConn)
        print(df.to_string())
        #txtQueryResults = df.to_string()
        txtQueryResults = str(cursorOracle.fetchall())
        window.resultsTextEdit.setText(txtQueryResults)
        model = PandasModel(df)
        window.tableView.setModel(model)

    def clearWork(self): #Functie de stergere 
        window.queryTextEdit.setText("")
        window.resultsTextEdit.setText("")
        window.tableView.clearSpans()


#    def migrateMySQLToOracle(self):

    def exitProgram(self): #Functie de iesire
        window.deleteLater()
        window.close()
        window.destroy()


uf = usefulFunctions


class Ui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui, self).__init__() # Call the inherited classes __init__ method
        uic.loadUi('Proiectv3.ui', self) # Load the .ui file

        self.connectMySQLButton.clicked.connect(uf.connectToMySQL)

        self.disconnectMySQLButton.clicked.connect(uf.disconnectMySQL)

        self.connectOracleButton.clicked.connect(uf.connectToOracle)

        self.disconnectOracleButton.clicked.connect(uf.disconnectOracle)

        self.executeMySQLButton.clicked.connect(uf.executeMySQLUserQuery)

        self.executeOracleButton.clicked.connect(uf.executeOracleUserQuery)

        #self.transferButton.clicked.connect(uf.migrateMySQLToOracle)

        self.clearButton.clicked.connect(uf.clearWork)

        self.exitButton.clicked.connect(uf.exitProgram)

        self.show() # Show the GUI


#app = QtWidgets.QApplication(sys.argv) # Create an instance of QtWidgets.QApplication
app = QCoreApplication.instance()
#app.setStyle('Fusion')
if app is None:
    app = QApplication(sys.argv)
window = Ui() # Create an instance of our class
app.exec_() # Start the application

Редактировать 1

Это решения, которые я пытался.

def migrateMySQLToOracle(self): #<-- Easieste solution and works.
    dst = create_engine('oracle+cx_oracle://user:pass@localhost:1521/xe')
    sql = 'SELECT * FROM actor'
    df = pd.read_sql(sql, mySQLConn)
    df.to_sql('actor', dst,if_exists = 'replace')


def migrateMySQLToOracle(self):
    # create engine, reflect existing columns, and create table object for oldTable
    #print('Test1')
    srcEngine = create_engine('mysql+mysqldb://user:pass@localhost/classicmodels') # change this for your source database
    srcEngine._metadata = MetaData(bind=srcEngine)
    srcEngine._metadata.reflect(srcEngine) # get columns from existing table
    srcTable = Table('offices', srcEngine._metadata)

    # create engine and table object for newTable
    #print('Test2')
    destEngine = create_engine('oracle+cx_oracle://user:pass@localhost:1521/xe') # change this for your destination database
    destEngine._metadata = MetaData(bind=destEngine)
    destTable = Table('office', destEngine._metadata)
    #print('Test3') 
    # copy schema and create newTable from oldTable
    for column in srcTable.columns:
        #print('Test4')
        destTable.append_column(column.copy())
        destTable.create()


def migrateMySQLToOracle(self):
    src = create_engine('mysql+mysqldb://user:pass@localhost/classicmodels')
    dst = create_engine('oracle+cx_oracle://user:pass@localhost:1521/xe')
    meta = MetaData()
    meta.reflect(bind=src)
    tables = meta.tables

    for tbl in tables:
        data = src.execute(tables[tbl].select()).fetchmany()
        if data:
            dst.execute(tables[tbl].insert(), data)


def migrateMySQLToOracle(self):
    print('Test1')
    src = create_engine('mysql+mysqldb://user:pass@localhost/classicmodels')
    dst = create_engine('oracle+cx_oracle://user:pass@localhost:1521/xe')
    meta = MetaData()
    tables = meta.tables;
    print('Test2')
    for tbl in tables:
        print ('##################################')
        print (tbl)
        print ( tables[tbl].select())
        data = src.execute(tables[tbl].select()).fetchall()
        for a in data: 
            print(a)
        if data:
            print (tables[tbl].insert())
            dst.execute( tables[tbl].insert(), data)

def migrateMySQLToOracle(self):
    src = create_engine('mysql+mysqldb://user:pass@localhost/classicmodels')
    dst = create_engine('oracle+cx_oracle://user:pass@localhost:1521/xe')
    meta = MetaData()
    meta.reflect(bind=src)
    tables = meta.tables
    for tbl in tables:
        data = src.execute(tables[tbl].select()).fetchall()
        if data:
            dst.execute(tables[tbl].insert(), data)        

def migrateMySQLToOracle(self):
    old_base = automap_base()
    old_engine = create_engine("mysql+mysqldb://user:pass@localhost/classicmodels", echo=True)
    old_base.prepare(old_engine, reflect=True)
    TableOld = old_base.classes.table_old
    old_session = Session(old_engine)

    new_base = automap_base()
    new_engine = create_engine("oracle+cx_oracle://user:pass@localhost:1521/xe", echo=True)
    new_base.prepare(new_engine, reflect=True)
    TableNew = old_base.classes.table_new
    new_session = Session(new_engine)

    # here you can write your queries
    old_table_results = old_session.query(TableOld).all()
    new_data = []
    for result in old_table_results:
        new = TableNew()
        new.id = result.id
        new.name = result.name
        new_data.append(new)
    new_session.bulk_save_objects(new_data)
    new_session.commit()

1 Ответ

0 голосов
/ 03 февраля 2020

Хорошо, поэтому я рассмотрел некоторые решения, которые я изначально пробовал. Я пришел к выводу, что существует 2 способа скопировать таблицу MySQL в Oracle.

Первое решение

def migrateMySQLToOracle(self):
        src = create_engine('mysql+mysqldb://<user>:<pass>@localhost/<database>')
        dst = create_engine('oracle+cx_oracle://<user>:<pass>@localhost:port/<service>')
        sql = 'SELECT * FROM <table>'
        df = pd.read_sql(sql, src)
        print(df)
        df.to_sql('<Table name that will appear in Oracle>', dst,if_exists = 'replace')

Первое решение требует импорта pandas и использования pandas

Второе решение

С технической точки зрения это более удовлетворительно, единственная проблема, которую я заметил, заключается в том, что если вы хотите применить это решение при копировании таблицы с Oracle на MySQL у него будут проблемы с типом данных NUMBER из Oracle, и консоль python выдаст ошибку. В противном случае это работает, просто убедитесь, что в таблице нет столбца типа данных NUMBER.

https://www.slideshare.net/Stiivi/python-business-intelligence-pydata-2012-talk

Используйте эту ссылку и начните со слайда 35. Требуется использование sqlalchemy

...