Вставка значения None в столбец Date из python в базу данных PostgreSQL с использованием PygreSQL v5.0.6 - PullRequest
0 голосов
/ 13 ноября 2018

Я пытаюсь вставить None значения в столбец даты базы данных PostgreSQL из python, используя PygreSQL v5.0.6.

Некоторый код:

def _update_traits_db(self, code, date_start, date_end, unit):
    sql = ("Insert into traits (code, date_start, date_end, unit) "
           "VALUES ('%s', '%s', '%s', '%s') "
           "ON CONFLICT (code) DO UPDATE "
           "SET date_start = excluded.date_start, date_end = excluded.date_end, unit = excluded.unit "
           % (code, date_start, date_end, unit))
    try:
        self._connect()
        self._cur.execute(sql)
        self._con.commit()
        self._close()
    except Exception as e:
        self._close()
        raise e

Есть параПроблемы, с которыми я сталкиваюсь, самая большая из которых - это возможность None значений для date_end и unit, первая из которых - дата, вызывающая ошибки SQL, такие как:

ОШИБКА: неверный синтаксис ввода длявведите дату: "Нет"
ЛИНИЯ 1: ... d, единица измерения) ЗНАЧЕНИЯ ('AWGHT', '2003-01-29T23: 00: 00Z', 'Нет', 'N ... ^ Если я заменюзначение none с жестко заданным значением NULL, тогда оно работает, но, прочитав, я решил, что его нужно обработать Py PyreSQL, автоматически преобразуя None в NULL, но я не могу заставить это работать.

секундупроблема со значениями None в столбце unit, предполагается, что это строка, но None теперь хранится в базе данных, где в идеале должно быть значение NULL. Я попытался удалить кавычки со всех сторон"% s" для единицы измерения в запросе, которая вызывает только ошибку SQL на Noне значение.

Я довольно плохо знаком с Python и PostgreSQL, поэтому есть много потенциальных мест, которые я мог испортить, поэтому все предложения приветствуются.

1 Ответ

0 голосов
/ 13 ноября 2018

Просто используйте параметризацию, отраслевой стандарт для отделения кода SQL от значений данных, а не интерполяцию строк, которая выглядит аналогично, поскольку в обоих случаях используется заполнитель %s. При таком подходе None должно разрешаться как NULL. Фактически, PygreSQL docs даже предупреждает пользователей на практике:

Предупреждение
Не забывайте никогда вставлять параметры непосредственно в ваши запросы используя оператор%. Всегда передавайте параметры отдельно.

Рассмотрим следующую корректировку с использованием %s заполнителей без кавычек (см. документы ) со значениями, позже связанными в cursor.execute() call:

def _update_traits_db(self, code, date_start, date_end, unit):
    # PREPARED STATEMENT (NO DATA VALUES INTERPOLATED)
    sql =  """INSERT INTO traits (code, date_start, date_end, unit)
              VALUES (%s, %s, %s, %s)
              ON CONFLICT (code) DO UPDATE
              SET date_start = excluded.date_start, 
                  date_end = excluded.date_end, 
                  unit = excluded.unit
           """
    try:
        self._connect()
        # BIND PARAMETERS WITH TUPLE OF VALUES
        self._cur.execute(sql, (code, date_start, date_end, unit))
        self._con.commit()

    except Exception as e:
        raise e

    finally:
        self._close()
...