Psycopg execute_values без идентификатора

#python #postgresql #psycopg2 #execute

#python #postgresql #psycopg2 #выполнить

Вопрос:

Я пытаюсь вставить список строк / кортежей в мою базу данных postgresql. Итак, я нашел функцию execute_values() … Но это не работает, чтобы строки автоматически получали идентификатор.

Мой код:

 query = "INSERT INTO "  self.table   " VALUES %s"
execute_values(self.cursor,query, row)
self.con.commit()
  

Первый столбец в моей базе данных — это идентификатор, а первый столбец моего кортежа строк — ТЕКСТ (второй столбец в базе данных также является ТЕКСТОМ)

Итак, я получаю сообщение об ошибке:

 psycopg2.errors.InvalidTextRepresentation: invalid input syntax for type integer: "blub"
LINE 1: INSERT INTO whales VALUES ('blub...

  

Так что я думаю, это из-за идентификатора.

Также я пробовал template , но результат не лучше:

 database.py", line 204, in insert_row
execute_values(self.cursor,query, row, "(%(name)s,%(is_member)s)")
File "C:JustaPathenvlibsite-packagespsycopg2extras.py", line 1289, in execute_values
parts.append(cur.mogrify(template, args))
TypeError: tuple indices must be integers or slices, not str
  

Возможно, я неправильно прочитал документацию или не понимаю шаблоны…

Теперь вопрос: как я могу с этим справиться? При «обычных» исполнениях мне не нужно добавлять идентификатор. Есть ли способ сделать это с помощью execute_values()? Или это единственный способ сначала получить идентификаторы с помощью select и также присвоить неиспользуемые идентификаторы execute_values?

Комментарии:

1. Вы должны указать столбцы, к которым принадлежат данные: INSERT INTO foo (text_col_1, text_col_2) VALUES ... , предполагая id , что столбец автоматически увеличивается.

Ответ №1:

В Postgresql для допустимого SQL список значений в INSERT инструкции должен соответствовать указанному списку имен столбцов. Если список имен столбцов не указан, то указанный список N значений должен соответствовать первым N столбцам в таблице с возможностью указания DEFAULT для вставки значения по умолчанию для этих столбцов. В отношении столбца Postgresql SERIAL , такого как тот, который объявлен в следующей таблице примера:

     CREATE TABLE test_insert_with_serial_column (
        id SERIAL PRIMARY KEY,
        col1 VARCHAR,
        col2 VARCHAR
    );
  

Допустимы следующие инструкции SQL:

     -- Specifying only the col1 and col2 columns, SERIAL id column will "auto-increment"
    INSERT INTO test_insert_with_serial_column(col1, col2) VALUES ('one_text', 'other_text');

    
    -- Specifying values for all columns with DEFAULT for the SERIAL id column
    INSERT INTO test_insert_with_serial_column VALUES (DEFAULT, 'one_text', 'other_text');
  

Однако следующий SQL недопустим:

     -- Failed to specify an integer value for the first SERIAL id column
    INSERT INTO test_insert_with_serial_column VALUES ('one_text', 'other_text');
  

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

psycopg2.extras.execute_values это вспомогательная функция, которую можно использовать для более эффективной вставки нескольких строк значений (т.Е. Списка списка значений). Входной SQL-запрос должен содержать один %s заполнитель, который будет заменен template заполнителями of . Значение по умолчанию template (т.Е. Если None Указано) представляет собой простую позиционную последовательность заполнителей (т.Е. (%s, %s, ...) ) с количеством заполнителей, равным количеству значений, которые нужно вставить для каждой строки. Поэтому вызов execute_values с:

 execute_values(cur, "INSERT INTO test_insert_with_serial_column VALUES %s",
               [('one_text', 'other_text')])
  

приводит к тому же недопустимому SQL, что и выше. Обратите внимание, что приведенное выше использование execute_values для вставки только
одной строки вместо нескольких строк не имеет значения для ошибки.

Существует несколько решений этой проблемы:

  1. Укажите имена столбцов, соответствующие значениям во входном запросе
 execute_values(cur, "INSERT INTO test_insert_with_serial_column (col1, col2) VALUES %s",
               [('one_text', 'other_text')])
  
  1. Укажите a template , который указывает a DEFAULT для id столбца
 execute_values(cur, "INSERT INTO test_insert_with_serial_column VALUES %s",
               [('one_text', 'other_text')], template="(DEFAULT, %s, %s)")
  
  1. Объявите SERIAL столбец как последний столбец в таблице
     CREATE TABLE test_insert_with_serial_column (
        col1 VARCHAR,
        col2 VARCHAR,
        id SERIAL PRIMARY KEY
    );
  

Затем, вызывая:

 execute_values(cur, "INSERT INTO test_insert_with_serial_column VALUES %s",
               [('one_text', 'other_text')])
  

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

Комментарии:

1. Проблема, которая мешает мне использовать первые два решения, заключается в том, что столбцы могут быть переменной величиной. Мой подготовленный оператор insert предназначен для использования для нескольких таблиц с различным количеством столбцов. Единственный способ, которым я могу избежать этой проблемы, — использовать ваше третье решение.