2012-03-27 5 views
2

Je dois écrire une instruction INSERT qui vérifie d'abord si les données existent déjà. Le code actuel est à l'intérieur en utilisant python psycopg2 pour se connecter à un postgresql db:python instructions d'insertion conditionnelles psycopg2

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" 

qui ne fonctionne pas (et je n'ai pas fait erreur qualité manipulation, donc je ne reçois pas de bonnes informations). Alors, je suis allé dans psql et essayé simplement:

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

et moi avons eu l'erreur suivante:

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

Je crois que mon erreur est dans le sql pas le python (bien que je peux me tromper) puisque cela fonctionne:

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" 

Pour le tableau 1, mon CREATE était:

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 

Je suis reconnaissant pour toute aide et conseils.

+1

Etes-vous sûr que ces deux colonnes ne peuvent pas composer la clé primaire? –

Répondre

1

J'utilisé plpgsql pour une telle exigence dans mon projet

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); 

Vous pouvez utiliser quelque chose comme ci-dessous pour l'utiliser:

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

La requête ci-dessus ne sont pas paramétrées. Alors s'il vous plaît méfiez-vous de l'injection SQL si vous obtenez l'entrée d'une source externe.

Remarque: Vous pouvez utiliser cursor.mogrify() pour éviter les attaques par injection SQL.

sql = cursor.mogrify(sql,data) 
cursor.execute("insert_if_unique("+sql+")") 
0

Essayez de les inverser. Condition NON EXISTE avec sous-requête:

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