2011-05-24 22 views
8

He golpeado un gran bache de velocidad al insertar datos en mi base de datos. Puede ver en el siguiente código que simplemente estoy construyendo la declaración SQL para pasar al comando de ejecución. Los valores son correctos y todo está bien allí, pero el intérprete de Python parece agregar y eliminar citas de los params en tiempo de ejecución.INSERT INTO y Concatenación de cadenas con Python

Esta es la forma correcta de insertar datos espaciales en la base de datos.

INSERT INTO my_table(
      name, url, id, point_geom, poly_geom) 
    VALUES ('test', 'http://myurl', '26971012', 
      ST_GeomFromText('POINT(52.147400 19.050780)',4326), 
      ST_GeomFromText('POLYGON((52.146542 19.050557, bleh, bleh, bleh))',4326)); 

Esto es verificable en el editor de Postgres consulta ... Ahora, cuando ejecuto el código Python a continuación Se añade comillas dobles alrededor de la función ST_GeomFromText y luego elimina las citas de la columna id.

INSERT INTO my_table(
      name, url, id, point_geom, poly_geom) 
    VALUES ('test', 'http://myurl', 26971012, 
    "ST_GeomFromText('POINT(52.147400 19.050780)',4326)", 
    "ST_GeomFromText('POLYGON((52.146542 19.050557, 52.148430 19.045527, 52.149525 19.045831, 52.147400 19.050780, 52.147400 19.050780, 52.146542 19.050557))',4326)"); 

Esto hace que la inserción fallar y PostGIS afirma que no es una geometría adecuada. Cuando imprimo cada uno de los params para ver en la pantalla, no hay nada divertido pasando con las comillas, así que estoy pensando que el problema debe estar en el comando de ejecución. Estoy usando Python 2.7 ... ¿Alguien puede ayudar a prevenir que esta locura continúe?

conn = psycopg2.connect('dbname=mydb user=postgres password=password') 
    cur = conn.cursor() 
    SQL = 'INSERT INTO my_table (name, url, id, point_geom, poly_geom) VALUES (%s,%s,%s,%s,%s);' 
    Data = name, url, id, point, polygon 
    #print Data 
    cur.execute(SQL, Data) 
    conn.commit() 
    cur.close() 
    conn.close() 
+0

Intenté cur.execute (SQL, (Data,)) pero eso saca el índice de tupla fuera de rango. ¿Nadie? – aeupinhere

Respuesta

13

está de paso la cadena ST_GeomFromText('POINT(..)') como parámetro, y se psycopg2 escapar de ella. Sin embargo, ST_GeomFromText(..) es una función PostGIS, no datos que está insertando.

Para resolver esto, necesita mover la función ST_GeomFromText al SQL estático. Por ejemplo:

sql = ''' 
    INSERT INTO foo (point_geom, poly_geom) 
    VALUES (ST_PointFromText(%s, 4326), ST_GeomFromText(%s, 4326))''' 
params = ['POINT(20 20)', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'] 
cur.execute(sql, params) 
+0

¡Esto lo arregló por completo! Muchas gracias ... – aeupinhere

+0

Funciona de hecho, y debe aceptarse como una respuesta. – Alex

+0

Esta respuesta es muy útil. Lo conseguí, sin embargo, cuando miro los datos en pgadmin después de insertarlos, ¿no veo el tipo de geometría o srid definidos para el campo? ¿Eso tiene que hacerse por separado? – kflaw

0

Es mejor (edit: que lo que está haciendo, no de primera respuesta) para hacer algo como esto:

select st_asgeojson(the_geom_ls) from atlas where the_geom_ls &&\ 
st_geomfromtext('POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))', 4326) 

y pasar eso a su adaptador con las coordenadas en una tupla, se analizarán correctamente. Esta es la forma menos dolorosa de hacerlo. Si realmente tiene que construir las cuerdas por separado, es posible limpiar el escape mirando una la salida de cur.mogrify:

cur.mogrify('INSERT INTO my_table (name, url, id, point_geom, poly_geom) VALUES (%s,%s,%s,%s,%s);', (1,2,3,4,5)) 
>>>'INSERT INTO my_table (name, url, id, point_geom, poly_geom) VALUES (1,2,3,4,5);' 

query = "ST_GeomFromText('POLYGON((52.146542 19.050557, 52.148430 19.045527, 52.149525 19.045831, 52.147400 19.050780, 52.147400 19.050780, 52.146542 19.050557))',4326)" 

cur.mogrify('INSERT INTO my_table (name, url, id, point_geom, poly_geom) VALUES (%s,%s,%s,%s,%s);', (1,2,3,4,query)) 
>>> "INSERT INTO my_table (name, url, id, point_geom, poly_geom) VALUES (1,2,3,4,E'ST_GeomFromText(''POLYGON((52.146542 19.050557, 52.148430 19.045527, 52.149525 19.045831, 52.147400 19.050780, 52.147400 19.050780, 52.146542 19.050557))'',4326)');" 

Resiste la tentación de utilizar un formato de cadenas método en una cadena de consulta SQL, a pesar de que estas cosas puede ser frustrante

+0

No tuve la oportunidad de probar este enfoque, pero definitivamente lo echaré un vistazo la próxima vez que me encuentre con algo como esto. Adam – aeupinhere

+0

@samplebias la respuesta es la mejor (parece increíblemente experto en general); Utilizo lo anterior para rectángulos simples y probablemente sea mejor tener un enfoque genérico de '' POLYGON ({0}) '' formato (some_geometry) 'para el caso general. Mire el método 'cur.mogrify' si alguna vez se confunde acerca de cómo psycopg2 está escapando cosas. – unmounted

+0

@bvmou Probé este método con cur.execute y un ejemplo similar, pero tengo un error de 'psycopg2.InternalError: ERREUR: error de análisis - geometría inválida': porque E'ST_GeomFromText no se reconoce ... por qué el E ' cuando reemplazo la variable? – reyman64

Cuestiones relacionadas