2011-09-22 10 views
10

Hace poco - muy recientemente - comencé a aprender a programar para iOS, y he quedado perplejo por lo que parece (para mí) ser una descuidada supervisión en SQLite3. Permítanme calificarlo diciendo que antes de la semana pasada tenía cero experiencia (práctica) con Macs, Objective C, Xcode, iOS o SQLite, así que no tengo ilusiones sobre el vals en el campo de las herramientas probadas y la búsqueda de errores obvios en mi primer intento Supongo que hay una buena explicación.Enlace de Parámetros de SQLite directamente por Nombre

Sin embargo, después de pasar los últimos meses usando SQL Server, MySQL y PostgreSQL, me sorprendió descubrir que SQLite no tiene una mejor funcionalidad para agregar parámetros por nombre. Todo lo que pude encontrar en línea (documentación, foros [incluido SO]) dice que asigne parámetros usando su índice entero, que parece que sería difícil mantenerlo si alguna vez modifica sus consultas. A pesar de que puede nombre de los parámetros en sus estados de cuenta y hacer algo como

sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@my_param"), myInt); 

nadie parece hacer eso tampoco. De hecho, nadie parece tratar de automatizar esto en absoluto; el único alternate approach que pude encontrar usó una matriz de parámetros y un contador de ciclos, e inspeccionó cada parámetro para determinar qué tipo de objeto insertar. Originalmente consideré un enfoque similar, pero a) la postura de mi jefe es que los parámetros de la base de datos siempre deben ser revisados ​​(y estoy de acuerdo, aunque me doy cuenta de que los campos SQLite no están fuertemente tipados y técnicamente podría hacerlo de todos modos), b) se sentía como un truco poco elegante, yc) asumí que había una razón por la cual este enfoque no se usaba ampliamente. Entonces:

1) ¿Por qué no hay métodos de enlace en SQLite que acepten un nombre de parámetro (como, por ejemplo, un 'const char')? ¿O están allí y me falta algo?

2) ¿Por qué nadie parece utilizar un enfoque como el del ejemplo anterior?

Indagué un poco en el código fuente y pensé que podría modificar fácilmente la biblioteca o simplemente escribir mis propios métodos de clase (mecanografiados) que harían lo anterior para mí, pero supongo que hay una razón por la que nadie ha creado esto en SQLite todavía. Mi única conjetura es que la memoria adicional y los ciclos necesarios para encontrar el índice del parámetro son demasiado valiosos en un [insert iDevice aquí], y no vale la pena la conveniencia de poder usar nombres de parámetros. . . ?

Cualquier apreciación sería apreciada.

+0

SQLite no ofrecer este: http://www.sqlite.org/lang_expr.html – Tim

+0

Recurso útil - pero no sabe cómo se refiere a mi pregunta? – brichins

+0

Para mí, es menos exigente mentalmente con los parámetros con nombre y, como dijo Tim, es compatible con SQLite. Los lenguajes como .NET hacen que los parámetros con nombre sean mucho más accesibles. – Echilon

Respuesta

4
  1. Hay; es la función sqlite3_bind_parameter_index() que mencionó que usa para convertir un nombre de parámetro en un índice, que luego puede usar con las funciones sqlite3_bind_*(). Sin embargo, no existe la función sqlite3_bind_*_by_name() ni nada de eso. Esto es para ayudar a prevenir la hinchazón API. El popular Flying Meat Database sqlite wrapper tiene soporte para parámetros con nombre en una de sus ramas, si le interesa ver cómo se usa.

    Si se piensa en lo que se necesitaría para poner en práctica métodos de encuadernación de parámetro con nombre completo, considere la lista actual de bind funciones:

    int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); 
    int sqlite3_bind_double(sqlite3_stmt*, int, double); 
    int sqlite3_bind_int(sqlite3_stmt*, int, int); 
    int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); 
    int sqlite3_bind_null(sqlite3_stmt*, int); 
    int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); 
    int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); 
    int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); 
    int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); 
    

    Si quisiéramos añadir un apoyo explícito a los parámetros con nombre, esa lista se duplicaría en longitud para incluir:

    int sqlite3_bind_name_blob(sqlite3_stmt*, const char*, const void*, int n, void(*)(void*)); 
    int sqlite3_bind_name_double(sqlite3_stmt*, const char*, double); 
    int sqlite3_bind_name_int(sqlite3_stmt*, const char*, int); 
    int sqlite3_bind_name_int64(sqlite3_stmt*, const char*, sqlite3_int64); 
    int sqlite3_bind_name_null(sqlite3_stmt*, const char*); 
    int sqlite3_bind_name_text(sqlite3_stmt*, const char*, const char*, int n, void(*)(void*)); 
    int sqlite3_bind_name_text16(sqlite3_stmt*, const char*, const void*, int, void(*)(void*)); 
    int sqlite3_bind_name_value(sqlite3_stmt*, const char*, const sqlite3_value*); 
    int sqlite3_bind_name_zeroblob(sqlite3_stmt*, const char*, int n); 
    

    dos veces tantas funciones significa mucho más tiempo dedicado a mantener API, asegurando de compatibilidad hacia atrás, etc, etc. Sin embargo, por la simple introducción de la sqlite3_bind_parameter_index(), que fueron capaces de una dd soporte completo para los parámetros nombrados con solo una función simple.Esto significa que si alguna vez deciden admitir nuevos tipos de vinculación (¿quizás sqlite3_bind_int128?), Solo tienen que agregar una sola función, y no dos.

  2. En cuanto a por qué nadie parece usarlo ... No puedo dar ningún tipo de respuesta definitiva con la realización de una encuesta. Mi supongo sería que es un poco más natural referirse a los parámetros secuencialmente, en cuyo caso los parámetros nombrados no son tan útiles. Los parámetros con nombre solo parecen ser útiles si necesita consultar parámetros fuera de servicio.

+0

Tiene sentido desde el punto de vista del mantenimiento ... pero puedes usar métodos que toman 'nombre' como argumento y descartar aquellos que toman 'int' (aparte de la compatibilidad hacia atrás, pero debes hacer el salto en algún punto) . Todavía estoy sorprendido de que el estándar SQLite sea listarlos en secuencia cuando todos los demás sistemas de bases de datos SQL (al menos que yo sepa) usan parámetros con nombre, lo cual, para mí, es precisamente _so así que puedes_ trabajar con ellos sin Preocuparse por la secuencia. Gracias por el enlace, tendré que buscar envoltorios de SQLite al lado :) – brichins

+1

@brichins, puedes preparar una declaración y leer los índices de parámetros en una variable una vez y luego reutilizar esa declaración preparada y vincular diferentes parámetros muchas veces. Esto evita una búsqueda de diccionario por parámetro. Dejar caer la API basada en el índice obligaría * a las personas a ser menos eficientes, por lo que me sorprendería que eso ocurra ;-). – binki

Cuestiones relacionadas