Как правильно вставить массив типа INET в Postgresql с использованием Python (библиотека psycopg2)

Я постоянно получал эту ошибку при попытке вставить в массив типа INET.

psycopg2.DataError: invalid input syntax for type inet: "Inet('8.8.8.8')"

Также для некоторых вариантов я пробовал:

TypeError: not all arguments converted during string formatting

Таблица испытаний:

cursor.execute( "CREATE TABLE test( ip_list inet[] );" )

Некоторые варианты, которые я пытался заставить работать:

cursor.execute( "INSERT INTO test( ip_list ) VALUES ( %s );", ( str( { "8.8.8.8" } ) ) )
cursor.execute( "INSERT INTO test( ip_list ) VALUES ( %s );", ( str( { psycopg2.extras.Inet( "8.8.8.8" ) } ) ) )
cursor.execute( "INSERT INTO test( ip_list ) VALUES ( %s );", ( psycopg2.extras.Inet( [ "8.8.8.8", "8.8.4.4" ] ) ) )

Команда psycopg2.extras.Inet( [ "8.8.8.8", "8.8.4.4" ] ) генерирует правильный объект Inet Inet(['8.8.8.8', '8.8.4.4']).

Однако при попытке вставить это с помощью

cursor.execute( "INSERT INTO test( ip_list ) VALUES ( %s );", ( psycopg2.extras.Inet( [ "8.8.8.8", "8.8.4.4" ] ) ) )

Это дает мне ошибку: TypeError: 'Inet' object does not support indexing

Когда я попытался преобразовать его в строку перед вставкой через:

ursor.execute( "INSERT INTO test( ip_list ) VALUES ( %s );", ( str( psycopg2.extras.Inet( [ "8.8.8.8", "8.8.4.4" ] ) ) ) )

У меня ошибка TypeError: not all arguments converted during string formatting.

Если вы вставляете в поле массива, не должно ли значение вставки быть чем-то вроде array['8.8.8.8']::inet[]?

Scratch'N'Purr 16.07.2018 14:11

Согласно документы, похоже, что psycopg будет преобразовывать массив inet в список строк. Однако я не совсем уверен, как это работает наоборот. Может быть, вы можете попробовать cursor.execute( "INSERT INTO test( ip_list ) VALUES ( %s );", (['8.8.8.8'],)) для параметризованной вставки.

Scratch'N'Purr 16.07.2018 14:22

@ Scratch'N'Purr эта строка дает ошибку DETAIL: Array value must start with "{" or dimension information.

Meghdeep Ray 16.07.2018 14:26

@MeghdeepRay: Используя sqlfiddle, это сработало. INSERT INTO test( ip_list ) VALUES ('{ 8.8.8.8, 8.8.4.4}');. Вам нужны фигурные скобки для обозначения массива. Заключите его в кавычки, чтобы получилась одна строка. Здесь - это документ, в котором объясняется, как использовать массивы.

shahkalpeshp 16.07.2018 14:46

@shahkalpesh Это определенно работает, но мне нужно, чтобы он работал с параметризованными входами.

Meghdeep Ray 16.07.2018 15:58

@MeghdeepRay: cursor.execute( "INSERT INTO test( ip_list ) VALUES ('{ 8.8.8.8, 8.8.4.4}')"); - это помогает?

shahkalpeshp 19.07.2018 11:41
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
6
715
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, проблема в том, как вы форматируете строку и синтаксис вашего запроса.

Вы можете просто вставить запись, если запустите свой запрос следующим образом:

INSERT INTO itest( ip_list ) VALUES ( '{ 8.8.8.8 }' );

Или несколько значений:

INSERT INTO itest( ip_list ) VALUES ('{ 192.168.2.1, 120.12.25.26, 10.20.30.40, 156.223.122.252 }');

.

Чтобы отформатировать такой запрос в python, вы можете сделать что-то вроде этого:

cur.execute( "INSERT INTO itest( ip_list ) VALUES ( %s );" % ("'{ 200.8.8.200 }'"))

.

================================================== =============

Редактировать:

Ответ на комментарий:

Я только что посмотрел на класс Inet(), и, похоже, он не возвращает правильное приведение для массивов (я не уверен, что мне здесь что-то не хватает, поправьте меня, если я ошибаюсь). Однако в качестве обходного пути я придумал это.

cur = conn.cursor()
cur.execute( "INSERT INTO itest( ip_list ) VALUES ( %s[] );", (Inet([ "8.8.8.8", "8.8.4.4" ]),))
conn.commit()

Как видите, я вручную добавил преобразование массива [] в тип inet.

Надеюсь, это поможет :) Не стесняйтесь спрашивать, есть ли у вас сомнения !!

Как это достигается с помощью параметризованного ввода через библиотеку psycopg2? Если мне нужно каждый раз вводить переменное количество IP-адресов?

Meghdeep Ray 20.07.2018 09:25

@MeghdeepRay, пожалуйста, прочтите редактируемую часть моего ответа. Я его обновил.

Nimeshka Srimal 20.07.2018 13:53

Другие вопросы по теме