Как вставить «НУЛЕВЫЕ» значения в базу данных PostgreSQL с помощью Python?

#python #postgresql #null #psycopg2 #nonetype

Вопрос:

Существует ли хорошая практика ввода NULL значений ключей в базу данных PostgreSQL, когда переменная находится None в Python?

Выполнение этого запроса:

 mycursor.execute('INSERT INTO products (user_id, city_id, product_id, quantity, price) VALUES (%i, %i, %i, %i, %f)' %(user_id, city_id, product_id, quantity, price))
 

приводит к TypeError исключению, когда user_id есть None .

Как можно NULL вставить a в базу данных , если значение равно None , используя psycopg2 драйвер?

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

1. Какой адаптер DB-API вы используете?

2. под адаптером DB-API я полагаю, вы имеете в виду интерфейс бд psycopg2. Если нет, можете ли вы быть более конкретным?

Ответ №1:

Чтобы вставить нулевые значения в базу данных, у вас есть два варианта:

  1. опустите это поле в инструкции INSERT или
  2. использовать None

Также: Для защиты от SQL-инъекции вам не следует использовать обычную интерполяцию строк для ваших запросов.

Вы должны передать два (2) аргумента execute() , например:

 mycursor.execute("""INSERT INTO products 
                    (city_id, product_id, quantity, price) 
                    VALUES (%s, %s, %s, %s)""", 
                 (city_id, product_id, quantity, price))
 

Альтернатива № 2:

 user_id = None
mycursor.execute("""INSERT INTO products 
                    (user_id, city_id, product_id, quantity, price) 
                    VALUES (%s, %s, %s, %s, %s)""", 
                 (user_id, city_id, product_id, quantity, price))
 

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

1. Спасибо. Можете ли вы указать мне где-нибудь, чтобы я мог прочитать, почему интерполяция строк в python может привести к sql-инъекции. Это очень интересно, и я об этом не подумал.

2. Пожалуйста. Это хорошо описывает, что такое атаки с использованием SQL-инъекций: en.wikipedia.org/wiki/SQL_injection Как это связано с интерполяцией строк?: Допустим, вы получаете ненадежный ввод в свою программу. Этот ввод может содержать, например, DROP TABLE команду.

3. Я использую None для значения столбца, но получаю ошибку: Ошибка программирования: столбец «none» не существует СТРОКА 1: …01.00-ng20′, report_date=’2016-03-30′, ec_enabled=Нет, ec_s… Вот исходный запрос, который не удался: ОБНОВИТЕ kw_daily_data_mart, УСТАНОВИТЕ имя хоста=’ctrlkey.com’, users_licensed=7, licensed_users=10, sw_version=’kw2016.01.00-ng20′, дата отчета=’2016-03-30′, ec_enabled=Нет, ec_server_count=1, config_max_file_version=10, av_enabled=True, location_count=1, sso_enabled=False, ГДЕ идентификатор пользователя=127892, идентификатор установки=3585 И имя хоста=’ctrlkey.com» ВОЗВРАЩАЮ удостоверение личности

4. Я тоже не использую ни одного, и я получаю ту же ошибку, что и @Varun. Тот же пакет python psycopg2, v2.6.2. Posgresql v9.6

5. Решение также работает с запросом на обновление. Спасибо, что поделились!

Ответ №2:

В текущем psycopg вместо » Нет «используйте переменную, равную «NULL».

 variable = 'NULL'
insert_query = """insert into my_table values(date'{}',{},{})"""
format_query = insert_query.format('9999-12-31', variable, variable)
curr.execute(format_query)
conn.commit()

>> insert into my_table values(date'9999-12-31',NULL,NULL)
 

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

1. это работает для psycopg2 2.8.4, решение с вставкой None заканчивается значением «None» в бд, по крайней мере, для postgres

2. Если вставляемое поле является текстовым полем, используя «NULL», просто вставьте эти четыре символа. Приведенный выше ответ (использование None ) является правильным.

Ответ №3:

Вот мое решение:

 text = 'INSERT INTO products (user_id, city_id, product_id, quantity, price) VALUES (%i, %i, %i, %i, %f)' %(user_id, city_id, product_id, quantity, price))

text = text.replace("nan", "null")

mycursor.execute(text)
 

Ответ №4:

Более простой подход, который также практичен при большом количестве столбцов:

Пусть row будет список вставляемых значений, которые могут содержать None . Чтобы вставить его в PostgreSQL, мы делаем следующее

 values = ','.join(["'"   str(i)   "'" if i else 'NULL' for i in row])
cursor.execute('insert into myTable VALUES ({});'.format(values))
conn.commit()
 

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

1. Возможно, это не по теме, но я мог бы предложить не вставлять в таблицу без указания имен столбцов.