условные операторы вставки python psycopg2 - PullRequest
2 голосов
/ 27 марта 2012

Мне нужно написать оператор INSERT, который сначала проверяет, существуют ли данные. Текущий код внутри python, использующий psycopg2 для подключения к postgresql db:

    sql = """IF NOT EXISTS (SELECT * FROM table \  
         WHERE col_1 = (%s) AND col_2 = (%s) ) \
         INSERT INTO table (col1, col2)      \
         VALUES (%s, %s);"""
    data = ( col1_data, col2_data, col1_data, col2_data)
    try:
        CURSOR.execute(sql, data)
        DB.commit()
    except:
        print "Cursor failed INSERT INTO table.\n"

, который не работает (и я не сделал качественную обработку ошибок, поэтому я не получаю никакой хорошей информации). Итак, я вошел в PSQL и попробовал просто:

    IF NOT EXISTS (SELECT * FROM t WHERE c1=d1 AND c2=d2)
        INSERT INTO t (c1, c2) VALUES (d1,d2);

и я получил следующую ошибку:

    ERROR:  syntax error at or near "IF" 
    LINE 1: IF NOT EXISTS (SELECT * FROM table WHERE c1 = d1...
            ^

Так что я верю, что моя ошибка в sql, а не в python (хотя я могу ошибаться), так как это работает:

    sql = """INSERT INTO t2 (col_0, col_1, col_2) \
             VALUES (%s, %s, %s);"""
    data = (d1, d2, time.time())
    try:
        CURSOR.execute(sql, data)
        DB.commit()
    except:
        print "Cursor failed to INSERT INTO t2.\n"

Для таблицы 1 мой CREATE был:

    db=> CREATE TABLE table (
    col_0 SERIAL PRIMARY KEY,
    col_1 varchar(16),
    col_2 smallint
    );
    NOTICE:  CREATE TABLE will create implicit sequence "pm_table_ip_id_seq" for serial column "pm_table.ip_id"
    NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "pm_table_pkey" for table "pm_table"
    CREATE TABLE

Я благодарен за любую помощь и руководство.

Ответы [ 2 ]

1 голос
/ 27 марта 2012

Я использовал plpgsql для такого требования в моем проекте

insert_function = """
CREATE LANGUAGE plpgsql;
CREATE FUNCTION insert_if_unique (sql_insert TEXT)
    RETURNS VOID
    LANGUAGE plpgsql
AS $$
BEGIN
    EXECUTE sql_insert;
    RETURN;
    EXCEPTION WHEN unique_violation THEN
    RETURN;
        -- do nothing
END;
$$;
"""

cursor.execute(insert_function);

Вы можете использовать что-то вроде ниже, чтобы использовать это:

cursor.execute("insert_if_unique("+sql+")"%data)

Вышеуказанный запрос не параметризован. Поэтому будьте осторожны с SQL-инъекцией, если вы получаете входные данные из внешнего источника.

Примечание : вы можете использовать cursor.mogrify(), чтобы избежать атак с использованием SQL-инъекций.

sql = cursor.mogrify(sql,data)
cursor.execute("insert_if_unique("+sql+")")
0 голосов
/ 15 октября 2015

Попробуйте поменять их. НЕ СУЩЕСТВУЕТ условие с подзапросом:

INSERT INTO t (c1, c2) VALUES (d1,d2)
WHERE NOT EXISTS (SELECT * FROM t WHERE c1=d1 AND c2=d2)
...