Python, Oracle_cx, использование результата запроса в качестве списка параметров в циклическом операторе вставки - PullRequest
0 голосов
/ 28 апреля 2020

В прошлом я писал сценарий pl / sql, который принимает имя таблицы и имя столбца (который указывает источник) в качестве аргументов, а затем профилирует все столбцы в таблице, давая полезные значения.

В настоящее время я учу себя python и переписываю этот сценарий pl / sql таким образом, чтобы его можно было выполнять для других баз данных sql, а не только для oracle. Так что я новичок в Python. Я иду через Автоматизировать скучный материал на Удеми. На данный момент я не занимаюсь инъекцией sql, потому что я только изучаю язык Python. Я пропустил операторы создания таблицы, чтобы уменьшить объем кода, который я вставляю.

Сценарий вставляет правильные записи при первом проходе l oop, но не запускает второй l oop. Вот вывод IDLE, а затем код.

================================================ RESTART: C:\Users\nathan\Documents\_work\_data_profiling_script\profiling_python_tester.py ================================================
('ETL_INS_DTM',)
insert into PROFILING_NWS6_PRT
            select 'PROFILING_NWS6', 'ETL_INS_DTM', SRCRECNO, count(*), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null
            from PROFILING_NWS6
            group by SRCRECNO
            order by 1,2,3
executed
committed
**Traceback (most recent call last):
  File "C:\Users\nathan\Documents\_work\_data_profiling_script\profiling_python_tester.py", line 39, in <module>
    for row in cursor:
cx_Oracle.InterfaceError: not a query**

import cx_Oracle
conn = cx_Oracle.connect("system", "XXXX", "localhost/xe")
cursor = conn.cursor()

## parameter declaration
##########################################################################

# These 2 parameters populated by user
v_st = 'PROFILING_NWS6' # Source Table - table in which we are profiling the data
v_srcno = 'SRCRECNO' # Source Number - numeric column in v_st that identifies the source system

# These 3 parameters automatically populated
v_prt = v_st + '_PRT' # Profile Report Table - table name we want our report created as
v_log = v_st + '_LOG' # Log Table - script logging goes here, used for monitoring and debugging
v_top = v_st + '_TOP' # Top Table - temporary table to hold top 5 counts


# write script that populates Profile Report Table with rows for each source/column combination from source table
# these are required to join to when updating analysis fields
##########################################################################

sql = "Select column_name from user_tab_columns where table_name = '"+ v_st + "' and column_name <> '" + v_srcno + "'"
cursor.execute(sql)
for row in cursor:
    print(row)
    sql =   """insert into {x_prt}
            select '{x_st}', '{x_row}', {x_srcno}, count(*), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null
            from {x_st}
            group by {x_srcno}
            order by 1,2,3""".format(x_prt = v_prt, x_srcno = v_srcno, x_st = v_st, x_row = row[0])
    print(sql)
    cursor.execute(sql)
    print('executed')
    cursor.execute('commit')
    print('committed')


#close connections
##########################################################################
cursor.close()
conn.close()

Ответы [ 2 ]

0 голосов
/ 28 апреля 2020

Эта архитектура кодирования будет выполнять множество «обходов» между Python и БД, поэтому она будет далека от оптимальной. Небольшие улучшения включают использование connection.autocommit вместо полной SQL фиксации (или connection.commit () call). Тогда вы можете посмотреть на использование executemany() вместо нескольких execute() вызовов. В целом, для Oracle просто используйте вызов PL / SQL, поскольку это займет всего одну поездку в оба конца.

0 голосов
/ 28 апреля 2020

Курсор в for row in cursor: все еще используется, пока l oop не завершится. Когда вы делаете cursor.execute(sql) внутри l oop, он меняет объект cursor. Таким образом, на 2-м l oop итерируемый элемент cursor является курсором от commit внутри l oop. Решение состоит в том, чтобы создать или использовать другой объект курсора внутри l oop.

cursor = conn.cursor()         # original cursor, as above
insert_cursor = conn.cursor()  # new one for insert
sql = "Select column_name from user_tab_columns where table_name "  # etc

for row in cursor.execute(sql):
    print(row)
    sql =   """second sql""".format(...)
    print(sql)
    insert_cursor.execute(sql)
    print('executed')
    insert_cursor.execute('commit')
    print('committed')

cursor.close()
insert_cursor.close()
conn.close()

Кроме того, for row in cursor: должно быть for row in cursor.fetchall():. Или просто for row in cur.execute(sql):.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...