Python / pypyODBC: Insertar fila usando cadenas y NULLs

Soy bastante nuevo en Python y realmente no he interactuado con SQL Server y XML Parsing hasta este proyecto actual (puede que ni siquiera sea el mejor enfoque posible). En pocas palabras, mi equipo de TI está muy atrasado y necesito obtener datos en una tabla de sandbox (analizado desde un XML).

Hay un segmento del XML que contiene atributos [xx] 001 a [xx] 025. No se incluyen todos estos atributos para cada XML que analizaré. Por lo tanto, recorro un bucle de todos los atributos posibles y adjunto los resultados a una lista. Dado que no todos los atributos están en cada XML, no puedo incurrir en ningún tipo de letra intentando representar cada uno. No es un problema hasta que llego a crear mi statement de inserción SQL donde necesito que se conviertan a NULL. Probablemente haya alguna forma muy sencilla de manejar esto, pero mi estado de novato está impidiendo mi progreso. Las piezas relevantes del código siguen …

Tal vez hay una mejor manera de hacerlo en general? Me preocupa que sqlList solo pueda ser tan grande antes de que yo también scope un límite.

#this list contains Nones sqlList = (", ".join(map(repr,appendedList))) #the Nones are an issue when I get to here curs.execute("USE Sandbox INSERT INTO myTable VALUES (%s)" % (sqlList)) curs.commit() 

Aquí hay un ejemplo de cómo se ve sqlList:

 '20_2014', '20_2014_3/25/2015 2:01 PM', 'FBR', 'A', '0', '0', '3', '1', '134', None, None, '0', None, '0', '0', '0', '0', '0', None, None, '2', None, None, None, None 

Recibo el siguiente mensaje de error:

 pypyodbc.ProgrammingError: ('42S22', "[42S22] [Microsoft][ODBC SQL Server Driver][SQL Server]Invalid column name 'None'.") 

En general, todavía me gustaría saber si esta es la forma “correcta” de hacerlo.

Su solución sigue siendo SQL dynamic , que siempre sufre de

  • Problemas de inyección de SQL (por ejemplo, ¿Qué sucede si una de las cadenas contiene una comilla simple?)
  • escriba malabares (por ejemplo, Ninguno -> NULL como en su pregunta),
  • tener que usar los delimitadores correctos para sus valores literales (cadenas, fechas, etc.)

Todos estos problemas desaparecen si utiliza una consulta parametrizada . Este ejemplo utiliza solo 2 atributos para mayor claridad (en lugar de los 25 en su pregunta), pero el principio es exactamente el mismo. Tenga en cuenta que no tengo que hacer nada especial para manejar los valores None para que puedan insertarse como valores nulos.

 import pypyodbc myData = [ (1, 'foo'), (2, None), (3, 'bar'), ] connStr = """ DSN=myDb_SQLEXPRESS; """ cnxn = pypyodbc.connect(connStr) crsr = cnxn.cursor() sql = """ INSERT INTO myTable VALUES (?, ?) """ for dataRow in myData: print(dataRow) crsr.execute(sql, dataRow) cnxn.commit() crsr.close() cnxn.close() 

La salida de la consola es …

 (1, 'foo') (2, None) (3, 'bar') 

… y las tres filas se insertan en la tabla correctamente, incluido el valor NULL (Ninguno) en la segunda fila.

No importa. Vea abajo:

 #this string contains Nones sqlList = (", ".join(map(repr,appendedList))) #this converts Nones to NULLs sqlList = sqlList.replace("None", "NULL") #all good now curs.execute("USE Sandbox INSERT INTO myTable VALUES (%s)" % (sqlList)) curs.commit() 

En general, todavía me gustaría saber si esta es la forma “correcta” de hacerlo.