Django Raw SQL Query с использованием нескольких баз данных
Я пытаюсь получить информацию из двух разных баз данных в одном запросе.
Ниже приведен пример кода, который я пытаюсь использовать с идентификационной информацией, замененной на общие имена.
У меня мои базы данных настроены следующим образом:
DATABASES = {
'default': {},
'primary': {
'ENGINE': 'django.db.backends.oracle',
'NAME': 'oracle.test.com:5432/erp',
'USER':'test1',
'PASSWORD':'',
},
'secondary': {
'ENGINE': 'django.db.backends.oracle',
'NAME': 'oracle2.test.com:5432/wms',
'USER':'test2',
'PASSWORD':'',
},
}
Тогда в моих представлениях я имею следующее:
def index(request):
sql_query = ('select \n'
' primary.table1.organization_id "Org", \n'
' primary.table2.LOCATION "Loc", \n'
' primary.table3.inventory "Inv", \n'
' primary.table4.reorder_date "Reorder", \n'
' secondary.table3.COMMENTS "Comments", \n'
'from \n'
' primary.table2, primary.table1\n'
' LEFT OUTER JOIN primary.table3 On\n'
' (primary.table1.SCHEDULE_NUMBER = primary.table3.SCHEDULE_NUMBER) \n'
' LEFT OUTER JOIN primary.table4 On \n'
' (primary.table1.SCHEDULE_NUMBER = primary.table4.PARENT_SCHEDULE_NUMBER) \n'
' LEFT OUTER JOIN secondary.table1 On \n'
' (primary.table1.SCHEDULE_NUMBER = primary.table1.SCHEDULE_NUMBER) \n'
'where
'primary.table1.item_id = primary.table2.inventory_item and \n'
'primary.table1.organization_id = primary.table2.organization_id \n')
with connections['primary', 'secondary'].cursor() as cursor:
cursor.execute(sql_query)
field_names = [tuple(x[0] for x in cursor.description)]
row = cursor.fetchall()
result = field_names + row
df = pd.DataFrame(result)
df.rename(columns=df.iloc[0], inplace=True)
df.drop([0], inplace=True)
table = df.to_html(index=False, classes='mystyle', justify='left')
return render(request, 'template.html', {'table': table})
Я думал, что это сработает, потому что синтаксис, который я нашел в Интернете для SQL, говорит, что нужно добавлять имя базы данных к каждой таблице. К сожалению, я получаю ошибку базы данных, говорящую, что первичный или вторичный является недопустимым идентификатором.
Во-первых, connections
является диктой, поэтому вы должны выполнить итерацию по его ключам, чтобы получить оба соединения:
dbs_to_connect = ['primary','secondary']
for k in dbs:
with connections[k].cursor() as cursor:
# code here...
Во-вторых, я не уверен, как настроены ваши базы данных и схемы в Oracle, но помните, что запрос всегда должен быть select <colums> from <schema>.<table>
. Независимо от этого, строка запроса должна выполняться непосредственно в другом программном обеспечении БД, так что вы можете протестировать ее там, чтобы убедиться, что проблема не в самом запросе.
Основываясь на некоторых советах с других форумов. Я узнал, что невозможно объединить таблицы в разных базах данных. Поэтому вот мое решение. Запустите 2 базы данных как 2 разных запроса, а затем сохраните их результаты в отдельных фреймах данных. Затем используйте pandas merge для объединения этих двух баз данных вместе с помощью левого объединения.
Filepath = 'example filepath'
SQL_Query1 = 'example'
SQL_Query2 = 'example'
with connections['primary'].cursor() as cursor:
cursor.execute(SQL_Query1)
field_names = [tuple(x[0] for x in cursor.description)]
row = cursor.fetchall()
result = field_names + row
df = pd.DataFrame(result)
df.rename(columns=df.iloc[0], inplace=True)
df.drop([0], inplace=True)
df['SCHED_#'] = pd.to_numeric(df['SCHED_#'])
with connections['secondary'].cursor() as cursor2:
cursor2.execute(SQL_Query2)
wms_field_names = [tuple(x[0] for x in cursor2.description)]
wms_row = cursor2.fetchall()
wms_result = wms_field_names + wms_row
wms_df = pd.DataFrame(wms_result)
wms_df.rename(columns=wms_df.iloc[0], inplace=True)
wms_df.drop([0], inplace=True)
wms_df['SCHED_#'] = pd.to_numeric(wms_df['SCHED_#'])
merged_df = pd.merge(df, wms_df, on='SCHED_#', how='left', indicator=True)
merged_df.to_csv(filepath, index=False)
Спасибо всем за ваш вклад