Модуль Python cx_Oracle: невозможно отформатировать запрос в коде

Я использую модуль cx_Oracle для подключения к базе данных оракула. В сценарии я использую две переменные schema_name и table_name. Следующий запрос работает нормально

cur1.execute("select owner,table_name from dba_tables where owner ='schema_name'")

Но мне нужно запросить количество строк таблицы, где мне нужно указать table_name с помощью schema_name, поэтому запрос должен быть

SELECT count(*) FROM "schema_name"."table_name"

Это не работает при использовании в коде, я пытался поместить его в тройные кавычки, одинарные кавычки и другие параметры, но он не форматирует запрос, как ожидалось, и, следовательно, ошибок в таблице не существует.

Любое руководство приветствуется.


person Ajit    schedule 18.02.2021    source источник


Ответы (2)


Можно использовать подготовленный оператор, содержащий заполнители с переменными формы ...{}.{}".format(sc,tb).

sc='myschema'
tb='mytable'

cur1.execute("SELECT COUNT(*) FROM {}.{}".format(sc,tb))
print(cur1.fetchone()[0])
person Barbaros Özhan    schedule 18.02.2021
comment
Хорошее решение. Но я сомневаюсь в терминологии в этом контексте: использование «переменных привязки» не является определением переменных привязки в Oracle. Переменные связывания Oracle — это способ отделить данные от кода. С этим фрагментом по-прежнему важно проверять значения sc и tb по известным «безопасным» спискам. - person Christopher Jones; 19.02.2021
comment
спасибо @ChristopherJones, вы правы, исправил объяснение. - person Barbaros Özhan; 19.02.2021
comment
Вы также можете использовать f-строки, как в cur1.execute(f"select count(*) from {sc}.{tb}"), но, как уже отмечалось, вам необходимо убедиться, что значения sc и tb известны или проверены. - person Anthony Tuininga; 19.02.2021

В этом конкретном случае вы также можете попробовать установить Connection.current_schema, см. документ cx_Oracle API

Например, если вы создаете таблицу в своей собственной схеме:

SQL> show user
USER is "CJ"
SQL> create table ffff (mycol number);

Table created.

SQL> insert into ffff values (1);

1 row created.

SQL> commit;

Commit complete.

Затем запустите код Python, который подключается от имени другого пользователя:

import cx_Oracle
import os

import sys, os
if sys.platform.startswith("darwin"):
    cx_Oracle.init_oracle_client(lib_dir=os.environ.get("HOME")+"/Downloads/instantclient_19_8")

username = "system"
password = "oracle"
connect_string = "localhost/orclpdb1"

connection = cx_Oracle.connect(username, password, connect_string)

connection.current_schema = 'CJ';

with connection.cursor() as cursor:
    sql = """select * from ffff"""
    for r in cursor.execute(sql):
        print(r)

    sql = """select sys_context('USERENV','CURRENT_USER') from dual"""
    for r in cursor.execute(sql):
        print(r)

вывод будет:

(1,)
('SYSTEM',)

Последний запрос показывает, что меняется не пользователь, а просто первый запрос автоматически меняется с 'ffff' на 'CJ.ffff'.

person Christopher Jones    schedule 18.02.2021
comment
Спасибо, Кристофер, я пытался использовать его в своем коде, но обнаружил, что даже после настройки схемы на то, что я хочу, когда я пытаюсь запросить таблицу, которая существует в схеме, она говорит, что таблица не существует, а также когда я пытаюсь запросить текущий пользователь показывает admin, который является пользователем, с которым было установлено соединение с базой данных, а не пользователем, который устанавливается с помощью Connection.current_schema. - person Ajit; 22.02.2021
comment
``` schema_name='myschemaname' table_name='mypassword' dsn_tns1 = cx_Oracle.makedsn(db_host,db_port,db_name) conn1 = cx_Oracle.connect(user=username, password=password, dsn=dsn_tns1) cur1 = conn1.cursor() conn1.current_schema = имя_схемы cur1.execute(SELECT COUNT(*) FROM {}.format(table_name)) print(cur1.fetchall()) cur1.execute(выберите sys_context('USERENV','CURRENT_USER') из двойного) ` `` - person Ajit; 22.02.2021
comment
Я обновил ответ примером. - person Christopher Jones; 22.02.2021
comment
Спасибо, Кристофер. В целях тестирования я создал тест таблицы в тесте схемы, и он отлично работает. Но когда я запрашиваю свою фактическую таблицу, в имени которой есть подчеркивание, код терпит неудачу. Я предполагаю, что это должно что-то делать с именем таблицы, которое должно быть в двойных кавычках. Даже в sqlplus, когда я запрашиваю таблицу select * из test.test, она работает нормально, но пока я запрашиваю select * из Scheme.table_name, это не удается, я должен указать table_name в двойных кавычках - person Ajit; 09.03.2021