Вставьте следующее значение последовательности, используя cx_ Oracle Cursor.executemany () - PullRequest
0 голосов
/ 07 февраля 2020

Я пытаюсь использовать библиотеку cx_ oracle в python для вставки строк, где одно из значений столбца является следующим значением в последовательности, называемой an_aj_s.

Я создал функцию для сделать это с именем insert_into_columns, и вызов этой функции выглядит следующим образом:

self.insert_into_columns('AN_JOB',
                         ('AJ_ID','AJ_JOBNAME', 'AJ_DESCRIPTION', 'AJ_CD_JOB_TYPE', 'AJ_CD_DATABASE','AJ_CD_JOB_STATUS', 'AJ_USR_ID', 'AJ_CREATE_DATE', 'AJ_EQUIP_COMPS_FLAG'),
                         [ ('an_aj_s.nextval', 'QlikManual_3', 'First Manually entered Test Job', 2, 0, 1  ,6 , dt.today().date(),  1)])

где аргументы: insert_into_columns({Table Name}, {Columns to insert}, {row of values to insert})

Когда я вызываю функцию, я получаю неверный номер ошибки: cx_ Oracle .DatabaseError: ORA-01722: неверный номер

Я уверен, что проблема заключается в последовательности, потому что если я заменю последовательность на номер, вставка будет успешной. Может кто-нибудь сказать мне, как я могу вызвать мою последовательность при вставке строк в таблицу?

Я попытался установить размеры ввода с помощью cur.setinputsizes (), но, похоже, это не сработало.

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ:

Оператор SQL, который генерирует моя функция, выглядит следующим образом:

INSERT INTO AN_JOB (AJ_ID,AJ_JOBNAME,AJ_DESCRIPTION,AJ_CD_JOB_TYPE,AJ_CD_DATABASE,AJ_CD_JOB_STATUS,AJ_USR_ID,AJ_CREATE_DATE,AJ_EQUIP_COMPS_FLAG) VALUES ( :1, :2, :3, :4, :5, :6, :7, :8, :9 )

А фактическая функция python для генерации оператора выглядит следующим образом:

 def insert_into_columns(self, table_name, columns, rows):
    sql = "INSERT INTO {table_name} ({column_names}) VALUES ({column_args} )"
    args_str = ''
    col_str  = ''
    for col_id in range(1, len(columns) + 1):
        args_str += ' :' + str(col_id)
        col_str += columns[col_id - 1]
        if col_id < len(columns):
            args_str += ','
            col_str += ','

    sql = sql.format(table_name=table_name, column_names =col_str,  column_args=args_str)
    print('Inserting rows into specified columns...')
    print(sql)

    with self.conn.cursor() as cur:
        cur.executemany(sql, rows)
        self.conn.commit()

1 Ответ

1 голос
/ 07 февраля 2020

В вашем выражении SQL вы передаете все значения как переменные связывания. Что обычно здорово! Но переменные связывания не интерпретируются механизмом SQL. Таким образом, для столбца AJ_ID вы не вызываете псевдостолбец последовательности an_aj_s.nextval, как вы хотите, вы передаете строку varchar2 'an_aj_s.nextval'. Oracle ожидает число, а не строку, поэтому вы получаете ошибку ORA-01722.

Вам нужно изменить свою функцию так, чтобы вместо этого:

INSERT INTO AN_JOB (AJ_ID,AJ_JOBNAME,AJ_DESCRIPTION,AJ_CD_JOB_TYPE,AJ_CD_DATABASE,AJ_CD_JOB_STATUS,AJ_USR_ID,AJ_CREATE_DATE,AJ_EQUIP_COMPS_FLAG) 
VALUES ( :1, :2, :3, :4, :5, :6, :7, :8, :9 )

you ' повторяю это:

INSERT INTO AN_JOB (AJ_ID,AJ_JOBNAME,AJ_DESCRIPTION,AJ_CD_JOB_TYPE,AJ_CD_DATABASE,AJ_CD_JOB_STATUS,AJ_USR_ID,AJ_CREATE_DATE,AJ_EQUIP_COMPS_FLAG) 
VALUES ( an_aj_s.nextval, :2, :3, :4, :5, :6, :7, :8, :9 )

Имеет ли это смысл? Существует множество способов изменить свою функцию для этого, но вы не объяснили другие варианты использования, поэтому я не хочу предлагать какой-либо конкретный вариант.

С другой стороны, вы, вероятно, найдете это легче сделать на стороне Oracle, создав триггер последовательности . Есть много примеров SO (, например, )

CREATE OR REPLACE TRIGGER an_job_id_trigger
BEFORE INSERT ON an_job
FOR EACH ROW
  WHEN (new.ID IS NULL)
BEGIN
  :new.ID := an_aj_s.nextval;
END;
/

Таким образом, вы можете просто пропустить столбец ID из ваших вставок, и триггер с этим справится :

INSERT INTO AN_JOB (AJ_JOBNAME,AJ_DESCRIPTION,AJ_CD_JOB_TYPE,AJ_CD_DATABASE,AJ_CD_JOB_STATUS,AJ_USR_ID,AJ_CREATE_DATE,AJ_EQUIP_COMPS_FLAG) 
VALUES (:1, :2, :3, :4, :5, :6, :7, :8 )
...