Ver la Versión Completa : [TUTORIAL] Mini-tutorial sqlite
danko9696
28/05/16, 20:38:28
Como veo que hay gente que busca info sobre SQLITE y no llega a acceder a la info posteada en el hilo sobre la consulta excel (http://www.htcmania.com/showthread.php?t=1152543) (que también sería recomendable echarle un vistazo) he pensado que no sería mala idea crear un hilo aparte específico para ello reciclando el mini tutorial y añadiendo un par de cosillas.
Para un uso básico sin conocimientos previos en un principio lo más complicado/lioso creo no es el lenguaje en sí sino preparar los archivos/base de datos:
- Podemos coger una base de datos que ya esté creada (de alguna app instalada) y hacer una copia en una carpeta personal o crear una base de datos nueva. Por ejemplo usando SQLite Editor -> New Database -> seleccionamos ruta donde la queremos crear y nombre de la base de datos (por ejemplo tasker_pruebas).
- A continuación, en TABLES, damos a settings y NEW TABLE. Escribimos el nombre de la tabla, por ejemplo POBLACIONES y ahora hay que añadir los campos que queremos que tenga.
- De los datos que hay que rellenar, para empezar los importante son nombre del campo (obviamente), como NOM_POBLACION, y sobre todo el tipo de dato: número entero, real -número con decimales-, texto, blob (para almacenar datos binarios, como fotos, por ej), fecha, timestamp y time. Para poblaciones podríamos tener nom_poblacion text, c_p text, habitantes, int. Los otros parámetros no son fundamentales para un comienzo.
para ejecutar la consulta desde tasker usar el comando shell con;
sqlite3 <ruta de la base de datos>/nombre_base_datos.db "<consulta>"
por ej, asumiendo que usamos tres variables en tasker:
sqlite3 /storage/emulated/0/Download/test_base_de_datos.db "insert into poblaciones (nom_poblacion,c_p,habitantes) VALUES ('%var_nom_pob','%var_c_p',%var_numhab);"
Luego para leer datos lo mismo que antes pero ahora añadiendo una variable para recoger el resultado de la consulta.
y usando SELECT <campos separados por comas> FROM <tablas separadas por comas> WHERE <condiciónes> ORDER BY <orden> LIMIT <máximo número filas que queremos> Para construir las consultas mejor usa el SQLite Debugger, mejor interface que el otro para ello.
NOTAS:
- si pones SELECT * ...., el asterisco indica que coja todos los campos
- si el select incluye varios campos, en el texto devuelto a la variable indicada estos vendrán separados por tuberías |
- IMPORTANTE para el uso con tasker, si la consulta devuelve más de una fila muy recomendable añadir lo siguiente después de la última comilla: |awk '{printf("%s%v_char_separacion",$0)}'
por ej, sqlite3 ...ruta bd y archivo... "SELECT .... FROM ... WHERE ... " |awk '{printf("%s%v_charsplit",$0)}'
Esto hace que cada fila esté separada por el caracter que queramos (%v_charsplit). Yo normalmente uso alguno raro, como el símbolo del yen o del estilo, algo que creas que no va a aparecer en el texto ni de casualidad.
- Muy útil cuando hay muchos datos. Podemos usar la cláusula LIMIT al final (antes del awk, dado que este no forma parte de la consulta sql sql). Un ...WHERE habitantes>100 AND habitantes<1000 ORDER BY nom_población DESC LIMIT 10 nos dará los 10 primeros resultados con esa condición.
- Como condiciónes están las típicas, >=, =, etc..., pero también LIKE, para comparar texto. La utilidad es que permite ignorar mayúsculas, minúsculas y usar comodines. Un ... WHERE nom_poblacion LIKE 'b%' devuelve los nombres de poblaciones que empiecen por b.
- También muy útil y usando LIMIT: podemos hacer que nos muestre los 100 primeros resultados a partir del resultado número 500. ¿Para que sirve esto?, pués para usar paginación de modo que la consulta sea más rápida y sin variar las condiciones de búsqueda, ya que solo cambiamos que filas son devueltas. Podemos usar un LIMIT %v_offset,20, asumiendo que entran 20 resultados en pantalla.
Por ej, en tasker:
- Pongamos %num_pagina vale 3
- Pulsas botón de siguiente página -> asignas %num_pagina a %num_pagina+1
- Asignas %v_offset a %num_pagina*20
- ... LIMIT %v_offset,20 (te mostraría 20 filas a partir del 80º resultado)
, y de este modo ir cambiando de página en página cambiendo el número de página.
Otra cosa importante si queremos acceder a datos que procedan de más de una tabla, como puede ser el caso de extraer info de una app externa. Pongamos que hay dos tablas:
tabla POBLACION. Campos: ID, NOMPOB
1,Población A
2,Población B
3,Población C
tabla USUARIOS. Campos: ID, NOMBRE, IDPOB
1,Nombre A,2
2,Nombre B,3
3,Nombre C,1
Para la consulta que permita extraer los nombres junto con su población sería:
SELECT usuarios.nombre, poblacion.nompob
FROM poblacion, usuarios
WHERE poblacion.id=usuarios.idpob
o bien
SELECT usuarios.nombre, poblacion.nompob
FROM poblacion INNER JOIN usuarios ON poblacion.id=usuarios.idpob
Nota: las mayúsculas no son importantes pero puede hacer más legible el texto al permitir diferenciar más rapidamente instrucciones SQLITE de nombres de campos y tablas.
Lo de usar IDs es algo muy típico. Cuando busquemos algún dato en una tabla y no lo encontremos de primeras es muy probable que lo que tenga sea algún ID y haya que enlazar la tabla con otra para ello.
Para una tabla simple se reduce a la configuración inicial y la interacción con Tasker. Realmente la complicación se encuentra sobre todo cuando se trata de optimizar rendimiento en bases de datos muy pesadas y con muchas tablas y/o consultas muy complejas pero para archivos pequeños con tablas sueltas no relacionadas directamente entre sí no hace falta mirar practicamente nada. Salvo alguna duda puntual, más allá que lo que he puesto ya sería mirarse algún tutorial de SQLITE.
Actualizar uno o más campos de una tabla:
UPDATE tabla SET campo1=5, campo2=(campo2*campo3)+5
WHERE campo_id=133
Eliminar una fila de la tabla (o más si cambiamos la condición):
DELETE FROM tabla WHERE _id=5
Borrar todas las filas:
DELETE FROM tabla WHERE 1=1
DELETE FROM tabla
Caravantes
29/05/16, 23:02:06
Mini-tutorial sqlite
Excelente explicación. Muchísimas gracias.
Creo que con este post y el de Cace, e asunto ya queda muy bien orientado para todo el mundo, y además es un buen sitio para responde con otras consultas y dudas sobre SQLite.
Reitero el enlace al post de Cace:
[Tutorial] CONSULTA DE UNA TABLA DE DATOS DE EXCEL EN TASKER (nivel básico) (http://www.htcmania.com/showthread.php?t=1152543)
http://www.htcmania.com/showthread.php?t=1152543
cace0353
05/06/16, 21:51:47
Problema:
Tengo una BD y quiero editar los campos de un registro.
En una escena y mediante "Consulta de variable" cambio los valores que me interesan…
¿Cual seria el comando para substituir los campos originales por los editados al finalizar la edición?
¿Podria hacerlo con "INSERT INTO Tabla_1 (NOM, CODI, ARTICLE,…) VALUES (‘%campo1','%campo2','%campo3'…) " o esto me crearia un nuevo registro?
danko9696
05/06/16, 23:20:13
Problema:
Tengo una BD y quiero editar los campos de un registro.
En una escena y mediante "Consulta de variable" cambio los valores que me interesan…
¿Cual seria el comando para substituir los campos originales por los editados al finalizar la edición?
¿Podria hacerlo con "INSERT INTO Tabla_1 (NOM, CODI, ARTICLE,…) VALUES (‘%campo1','%campo2','%campo3'…) " o esto me crearia un nuevo registro?
El INSERT añade registros, para modificar habría que usar UPDATE. He modificado el post original para indicar la sintaxis.
cace0353
05/06/16, 23:32:10
Gracias por tu respuesta.
¿Y con que comando puedo obtener el "numero de campo_id" o "row_id" del Registro abierto para editarlo?
¿Podrias escribir la sintaxis?
Enviat des del meu SM-T550 usant Tapatalk
danko9696
05/06/16, 23:47:35
Gracias por tu respuesta.
¿Y con que comando puedo obtener el "numero de campo_id" o "row_id" del Registro abierto para editarlo?
¿Podrias escribir la sintaxis?
Enviat des del meu SM-T550 usant Tapatalk
Eso es sólo un ejemplo, depende de la tabla y es necesario examinarla para averiguar cual de los campos es el identificador. De hecho no es imprescindible que exista tal identificador (aunque sea bastante frecuente), y que de haberlo este sea numérico o que sólo haya un identificador único (puede haber varios). Además puede estar formado por la combinación de varios campos.
Aparte, la condición puede afectar a cualquier número de filas cambiando la condición o todas si la quitas. Por ej. puedes usar un UPDATE tabla SET campo3 = campo3 * 100, por ejemplo, para multiplicar el campo3 de todas las filas por 100.
cace0353
09/06/16, 17:33:58
Eso es sólo un ejemplo, depende de la tabla y es necesario examinarla para averiguar cual de los campos es el identificador. De hecho no es imprescindible que exista tal identificador (aunque sea bastante frecuente), y que de haberlo este sea numérico o que sólo haya un identificador único (puede haber varios). Además puede estar formado por la combinación de varios campos.
Bueno, tema resuelto.
Explico el proceso seguido para ayudar a solventar problemas a otros taskeros que estén como yo...:
En el ordenador uso para crear la base de datos Sqlite Manager (complemento del Firefox) y me aparece, al principio de la tabla, una columna que se genera automáticamente y que tiene el nombre "rowid"
Para extraer el valor de "rowid" del registro que estoy editando utilizo, en la misma tarea asociada al boton de la escena para editar la tabla y siendo %var3 el valor del dato en la columna 3 (COL_3), el sigüiente código:
sqlite3 nombre y path de la base de datos "SELECT ROWID FROM nombre_tabla WHERE COL_3 LIKE '%var3'"
Guardar resultado en: %posicion
Una vez obtenido en %posicion el número de línea edito el registro con la sigüiente acción:
sqlite3 nombre y path de la base de datos "UPDATE nombre_tabla SET COL_1 = '%var1',COL_2 = '%var2',COL_3 = '%var3', COL_4 = '%var4 WHERE ROWID LIKE '%posicion' "
Esto funciona si no edito el campo que está en la columna COL_3. Si lo hago ocurre que %posicion entonces no toma valor (simplemente porque aún no existe el registro en la BD) y me devuelve %posicion y, por tanto, no se cambian los valores de este registro...
Interpreto que al cambiar el valor %var3 que utilizo para obtener %posicion entonces Sqlite3 no encuentra este valor en la tabla y la variable %posicion queda sin asignar.
Solución: Al abrir la escena de consulta de la ficha obtengo el valor de %posicio mediante el primer comando que he escrito, tanto si pienso editar el registro como si no... En este caso, como %posicio ya está asignada, el comando UPDATE me funciona correctamente.
Saludos a todos!
Buenas, sabe alguien si hay alguna forma de establecer un ancho de columna en las tablas de SQL? El caso es que muestro el resultado en un elemento menú de una escena, y por estética me gustaría que quedase alineado.
Un saludo
Caravantes
27/01/17, 19:44:16
hay alguna forma de establecer un ancho de columna en las tablas de SQL?
Creo que no. Me parece que, por definición, una tabla SQL contiene información sin formato de ningún tipo. O sea que tiene columnas "conceptuales" pero no puede tener una anchura establecida, ni un tipo/tamaño de letra, ni otras cuestiones de formato. Dicho de otra forma: en cada fila, el tercer dato es el que queda asignado a la "tercera columna", pero los datos pueden tener una anchura variable y por ese motivo podría ocurrir que el tercer dato de una fila quedase visualmente debajo del quinto dato de la fila precedente, como en el ejemplo siguiente.
uno; dos; tres; cuatro; cinco; seis
111111111;222222222;33333;4444444;555555;666666
Si quieres que los datos queden alineados tendrás que gestionarlo desde la escena, ya sea mediante las propiedades de la casilla o bien estableciendo un tipo de letra de ancho fijo, o bien añadiendo caracteres de relleno al principio, etc.
Gracias Caravantes, ese ejemplo que has puesto, es exactamente lo que me ocurre.
El problema es que desde la escena no encuentro la manera, ya que relleno las etiquetas del elemento menú con un array, por lo tanto me es imposible. Porque todo lo que intente, se aplica para todas las arrays... no se si se me escapa alguna forma de hacerlo.
danko9696
27/01/17, 20:13:13
Buenas, sabe alguien si hay alguna forma de establecer un ancho de columna en las tablas de SQL? El caso es que muestro el resultado en un elemento menú de una escena, y por estética me gustaría que quedase alineado.
Un saludo
No son columnas sino campos, que sirven para almacenar datos que pueden ser usados de multitud de maneras. No hay que confundir algo como sqlite con, por ejemplo, excel o access, que además de base de datos incluyen un interface gráfico para manejarlas donde los campos suelen mostrarse como columnas y hay opciones para ajustar alineamiento, tamaño de fuente, etc...
Gracias @Caravantes, ese ejemplo que has puesto, es exactamente lo que me ocurre.
El problema es que desde la escena no encuentro la manera, ya que relleno las etiquetas del elemento menú con un array, por lo tanto me es imposible. Porque todo lo que intente, se aplica para todas las arrays... no se si se me escapa alguna forma de hacerlo.
¿Cuantas columnas son a mostrar?
Muestro 3 columnas, tal que así;
GOLES PLAYER USUARIO
15 MESSI RAUL
13 LUIS SUAREZ KIKO
Donde pongo, goles player etc, son elementos de texto. Y gracias por la aclaración.
danko9696
27/01/17, 22:17:58
Muestro 3 columnas, tal que así;
GOLES PLAYER USUARIO
15 MESSI RAUL
13 LUIS SUAREZ KIKO
Donde pongo, goles player etc, son elementos de texto. Y gracias por la aclaración.
Lo decía porque podrías formatear los campos para simular columnas usando después una fuente monospace y rellenando con espacios. Todo en la propia consulta, aunque construirla sería algo engorroso.
Algo como
SELECT SUBSTR(player,1,15) || substr("@@@@@@@@@@@@@@@",1,15-LEN(SUBSTR(player,1,15))) || "@@@" ||
SUBSTR("@@@",1,3-LEN(SUBSTR(goles,1,3))) || SUBSTR(goles,1,3) || "@@@" ||
SUBSTR(usuario,1,10) || substr("@@@@@@@@@@",1,10-LEN(SUBSTR(usuario,1,10)))
AS fila_formateada
FROM tabla
Puede que haya algún error pero esa sería la idea básica: jugar con las instrucciones de manejo de cadenas de sqlite para formatear el texto de modo que al final tengamos un solo campo de salida ya formateado (también se podría hacer con varios pero ya puestos mejor así).
Una cosa: he visto que los espacios no se suben correctamente, así que los he cambiado por una @, o sea, debes cambiar las @ por espacios en el código que uses. Lo bueno de este sistema es que lo puedes probar directamente en el editor, sin usar Tasker para nada hasta que la consulta funcione correctamente.
Esto me va a dar horas de entreteniendo, cuando lo consiga hacer, compartiré el resultado, pero tengo dudas de si podré hacerlo desde mi nuevo teléfono sin acceso root, parece que por lo pronto solo me deja usar SQL, desde la nueva acción SQL Query , y supongo que este código es para introducirlo en ejecutar consola.
danko9696
27/01/17, 23:24:24
Esto me va a dar horas de entreteniendo, cuando lo consiga hacer, compartiré el resultado, pero tengo dudas de si podré hacerlo desde mi nuevo teléfono sin acceso root, parece que por lo pronto solo me deja usar SQL, desde la nueva acción SQL Query , y supongo que este código es para introducirlo en ejecutar consola.
Este código es sqlite, ahí tienes el SELECT, el FROM, puedes añadir el WHERE y si quieres, más campos. Si te funcionan consultas "normales" esta también debería hacerlo. Realmente no tiene nada de especial. Aunque no sé bien como va en la última versión con sqlite integrado (que no tengo instalada) ni sus limitaciones, si permite consultas RAW (sqlite puro), como creo recordar que alguién indicó en el otro hilo, carecer de root no debería influir. Y puede que también funcione incluso sin utilizar el modo RAW, simplemente indicando todo el tocho con SUBSTRs (o sea, desde justo después del SELECT hasta justo antes del AS) como campo.
Por cierto, que antes el LEN creo que es un LENGTH. Deberías probarla con sqlitedebugger antes de nada.
Por lo pronto no consigo hacer consultas, pero si desde el modo RAW puedo insertar datos, supongo que también debería de poder hacer consultas, seguiré probando a ver si lo consigo.
danko9696 he conseguido hacer funcionar el código que indicaste, y es justo lo que quería. El problema es que se ve, que los espacios no ocupan igual que las letras y no se termina de quedar bien cuadrado.
Aún así, no comprendo la sintaxis del código, prácticamente llevo esta semana mirando un poco más SQLite y si me sacas de lo más básico... Espero que si logro comprenderlo, pueda hacer modificaciones para terminar de cuadrarlo.
Un saludo
danko9696
31/01/17, 23:38:15
@danko9696 he conseguido hacer funcionar el código que indicaste, y es justo lo que quería. El problema es que se ve, que los espacios no ocupan igual que las letras y no se termina de quedar bien cuadrado.
Aún así, prácticamente no comprendo la sintaxis del código, prácticamente llevo esta ssemana mirando un poco más SQLite y si me sacas de lo más básico... Espero que si logro comprenderlo, pueda hacer modificaciones para terminar de cuadrarlo.
Un saludo
Si usas una fuente monospace todos los caracteres deben de ocupar lo mismo, incluidos espacios, y también lo mismo una ´i´ que una ´m´, que en otros casos tendrían un ancho muy distinto. Esa es la razón de usar este tipo de fuentes. Si la fuente que usas es efectivamente monospace entonces hace como esta web y el problema es distinto: cuando hay más de un espacio seguido quita todos menos uno.
Luego, el codigo es un poco engorroso visto todo junto pero si vas por partes es bastante sencillo teniendo a mano lo que hace cada instrucción (fácil de encontrar con google):
Pon que player = "Maradona". Su longitud es 8, así que SUBSTR(player,1,15) = "Maradona". No basta usar player a secas porque hay que prever que la cadena podría ocupar más de 15 caracteres, así que usar SUBSTR te asegura que coges 15 como máximo, pudiendo ser menos.
Para "Maradona" faltan 7 espacios a la derecha para una columa de 15, o concatenarle otra cadena con 15 espacios menos lo que ocupe "Maradona" (15-8), o sea SUBSTR("@@@@@@@@@@@@@@@",1,15-8), pero ese 8 no lo puedes poner directamente, porque depende del player concreto, así lo sacas del resultado de la cadena anterior: LENGTH(SUBSTR(player,1,15)). Con esto ya tienes la primera columna, metes tres espacios después para separar con la siguiente columna y listo. Luego el resto de columnas igual.
Repito de nuevo que debes de tener una web de referencia a mano con las instrucciones. Yo tampoco lo hago de memoria. Puede que me suene que debe de haber alguna instrucción para lo que yo quiero pero si no la he utilizado recientemente tampoco me voy a acordar de su sintaxis. También lo mejor es que lo hagas en PC con un editor de texto, donde puedes usar ratón y sobre todo teclado, y luego lo pases al móvil.
Gracias de nuevo, con esta nueva explicación ya me queda más claro como funciona el código.
Si usas una fuente monospace todos los caracteres deben de ocupar lo mismo
Cuando lo mencionaste en el otro mensaje, pensaba que "fuente menospace" era algún término relacionado con el código SQL, en vez de un tipo de letra. Supongo que eso si que solucionará el problema. No obstante, no me suena que se pueda añadir un tipo de fuente a un app creada con Tasker, por lo que entiendo que cuando los demás se la instalen en sus respectivos teléfonos se seguiría viendo descuadrado. Buscaré la manera y si encuentro la forma de hacerlo lo compartiré por aquí.
Solo una cosa más; cuando trato de buscar información sobre sqlite para implementarlo en Tasker, me cuesta extrapolar el código a Tasker, hay alguna página que recomiendes en la que creas que me puede ser más fácil buscar información? Un saludo.
danko9696
01/02/17, 16:28:19
Cuando lo mencionaste en el otro mensaje, pensaba que "fuente menospace" era algún término relacionado con el código SQL, en vez de un tipo de letra. Supongo que eso si que solucionará el problema. No obstante, no me suena que se pueda añadir un tipo de fuente a un app creada con Tasker, por lo que entiendo que cuando los demás se la instalen en sus respectivos teléfonos se seguiría viendo descuadrado. Buscaré la manera y si encuentro la forma de hacerlo lo compartiré por aquí.
Las fuentes monospace son un tipo de tipos de letra (o un tipo de fuentes). No sé que usas exactamente para mostrar los resultados pero las veces que he utilizado escenas (más bien poco) nunca he tenido problemas para elegir una. En el peor de los casos necesitarías copiar el mismo archivo de fuente a todos los móviles que vayan a usar la app, no es necesario "instalar" nada.
Solo una cosa más; cuando trato de buscar información sobre sqlite para implementarlo en Tasker, me cuesta extrapolar el código a Tasker, hay alguna página que recomiendes en la que creas que me puede ser más fácil buscar información? Un saludo.
Realmente no tengo una página de referencia a la que siempre recurra. Simplemente cuando voy a hacer algo con sqlite tiro del buscador, por ejemplo http://lmgtfy.com/?q=sqlite+substr.
WillyWeb
01/02/17, 17:28:07
http://lmgtfy.com/?q=sqlite+substr
:aplausos: ... precioso.
Con tu permiso me lo apunto. :ok:
Tal y como comentaste, con una fuente monospace y con el código que indicaste, se ajusta perfectamente a la escena. Y también tenías razón en lo de como utilizar la fuente, no hay que instalar nada, únicamente tener el archivo e indicar la ruta en el apartado de fuente del elemento de la escena. De nuevo gracias, y aquí dejo una captura del resultado. Un saludo
https://dl.dropboxusercontent.com/u/49277586/Screenshot_2017-02-01-18-22-54-196_net.dinglisch.android.taskerm.png
cace0353
16/03/17, 12:51:33
Hola,
Pues el tema es el del enunciado: cuando tengo una variable con texto con apóstrofos (uso datos en catalán y aparecen a menudo...) al editar los campos de un registro de la DB con UPDATE se detiene la acción.
Por ejemplo: quiero actualizar el campo COMENTARIS de una tabla, y establezco %comentaris = Planta de l'Amèrica del Sud.
Acción SQLquery: UPDATE nombre_de_la_tabla SET COMENTARIS = '%comentaris'
Al encontrar el apóstrofo, el literal de la variable queda en Planta de l y lo que queda de la frase no puede ser interpretado por SQL abortando la acción.
Tuve un problema parecido cuando importaba tablas de Excel pero se resolvió codificando el texto en UTF-8. Ahora este texto ya está en este formato y no encuentro la solución: ninguna ficha que contenga apóstrofes puede ser editada...
Alguien sabe cual sería la solución manteniendo el formato de texto con apóstrofes?.
Gracias de antemano por el desgaste neuronal...;-)
Hola,
Pues el tema es el del enunciado: cuando tengo una variable con texto con apóstrofos (uso datos en catalán y aparecen a menudo...) al editar los campos de un registro de la DB con UPDATE se detiene la acción.
Por ejemplo: quiero actualizar el campo COMENTARIS de una tabla, y establezco %comentaris = Planta de l'Amèrica del Sud.
Acción SQLquery: UPDATE nombre_de_la_tabla SET COMENTARIS = '%comentaris'
Al encontrar el apóstrofo, el literal de la variable queda en Planta de l y lo que queda de la frase no puede ser interpretado por SQL abortando la acción.
Tuve un problema parecido cuando importaba tablas de Excel pero se resolvió codificando el texto en UTF-8. Ahora este texto ya está en este formato y no encuentro la solución: ninguna ficha que contenga apóstrofes puede ser editada...
Alguien sabe cual sería la solución manteniendo el formato de texto con apóstrofes?.
Gracias de antemano por el desgaste neuronal...;-)
Creo que tienes que escapar el caracter, si mal no recuerdo en sql se hace escribiendolo dos veces '' (son dos apostrofes seguidos)
cace0353
16/03/17, 15:42:27
Gracias fus, tema resuelto!
Antes de la acción SQLquery pongo un Buscar y Reemplazar sobre la variable %comentaris, buscando ' (apóstrofe) y reemplazando con '' (dos apóstrofes seguidos) y funciona…
Enviat des del meu Nexus 5 usant Tapatalk
Buenas danko9696, te cito a ti directamente porque viendo los aportes que has hecho a este hilo, creo que eres el que puede resolver mi duda.
Estoy intentando insertar imágenes en mis tablas de sqlite, pero no lo consigo. He leído que tiene que ser insertada en un campo tipo "blob", pero me resulta imposible extrapolar el código que veo en los foros de sqlite a Tasker.
Ahí te dejo la consulta, por si sabes cómo es, y tienes un hueco para explicármelo. Un saludo.
danko9696
08/06/17, 12:32:25
Buenas @danko9696 (http://www.htcmania.com/member.php?u=868681), te cito a ti directamente porque viendo los aportes que has hecho a este hilo, creo que eres el que puede resolver mi duda.
Estoy intentando insertar imágenes en mis tablas de sqlite, pero no lo consigo. He leído que tiene que ser insertada en un campo tipo "blob", pero me resulta imposible extrapolar el código que veo en los foros de sqlite a Tasker.
Ahí te dejo la consulta, por si sabes cómo es, y tienes un hueco para explicármelo. Un saludo.
Con acciones de Tasker no es posible que yo sepa, pero se pueden guardar en campos de texto si usamos Read Binary y Write binary. Y de todos modos usar campos Blob solo es útil si podemos acceder directamente a ese tipo de datos, por ejemplo visualizar imágenes directamente de una base de datos, pero Tasker no cuenta con esa funcionalidad, así que toca usar Read/Write Binary (disponibles en Tasker) con campos de texto normales o bien mantener las imágenes fuera de la base de datos.
No sé para lo que lo vas a usar pero si se trata de imágenes relativamente grandes yo consideraría mantenerlas fuera de la base de datos. Desde luego yo no lo usaría para guardar las fotos de vacaciones, por ejemplo, pero puede que sí para pequeñas fotos asociadas a artículos, si el rendimiento no es un factor muy importante.
El uso que le quiero dar es meramente estético. Como ya comenté hice una aplicación para llevar el control de los goles y las tarjetas en una liga de fútbol de un juego de la Play que juego con unos amigos.
La escena principal tiene entre otros elementos, un elemento menú que muestra el contenido de una tabla sqlite, que gracias a este hilo he sabido construir y la tengo completamente alineada utilizando una fuente monospace.
La tabla actualmente tiene tres campos y está compuesta así:
GOLES PLAYER USUARIO
Lo que quiero es añadir otro campo, que contenga una imagen png con la cara de los jugadores. Las imágenes que me he descargado hasta el momento ocupan muy poco espacio.
Como comprenderás por lo que he explicado, descarto incluir las imágenes fuera de la base de datos, porque quedarían fuera del elemento menú.
así que toca usar Read/Write Binary (disponibles en Tasker) con campos de texto normales
Es la primera vez que escucho hablar de esto, así que intentaré buscar algo de información a ver si lo logro comprender, aunque se agradecen pistas.
Muchas gracias de nuevo por las aclaraciones, un saludo.
danko9696
08/06/17, 16:06:41
No entiendo eso de descartar las imágenes fuera de la base de datos por quedar fuera del elemento menu, no veo que tiene que ver.
Las imágenes van a tener que ser leídas desde archivos sí o sí, porque Tasker no permite (que yo sepa) cargarlas directamente desde una base de datos (en cuyo caso sí estaría muy bien tenerlas en ella). La cuestión es si cargarlas directamente o almacenando en la base de datos solamente el nombre de archivo y su ruta.
O sea, tal como lo quieres hacer, antes de mostrar X jugadores, tendrías que buscar sus registros en sqlite, mediante Write Binary convertirlos de texto a varios archivos de imagen que puedan ser mostrados por Tasker, esperar a que dichos archivos existan, y entonces permitir (o refrescar) que puedan ser accedidos por Tasker. Y antes de todo eso, para almacenar las imágenes tendrías que usar Read Binary, porque Tasker no tiene instrucciones para manejar directamente variables con datos binarios.
Basicamente lo que consigues con ello es ganar consistencia, porque todo queda en la base de datos, pero también ganas latencia, que pienso que sería suficiente para no merecer la pena.
No entiendo eso de descartar las imágenes fuera de la base de datos por quedar fuera del elemento menu, no veo que tiene que ver.
Lo que quiero decir es que necesito que cada fila contenga su correspondiente imagen, tal y como quedaría las etiquetas de un contacto de WhatsApp por ejemplo.
IMAGEN/GOLES/PLAYER/USUARIO
Porque si inserto las imágenes en la escena como "elemento imagen", no correrán junto al resto de datos de cada jugador, cuando haga swipe sobre el elemento menú.
Las imágenes van a tener que ser leídas desde archivos sí o sí
Esto no sería problema, ya que cargo los archivos necesarios en una carpeta de dropbox que tenemos compartida, y que voy sincronizando mediante acciones de Tasker.
O sea, tal como lo quieres hacer, antes de mostrar X jugadores, tendrías que buscar sus registros en sqlite, mediante Write Binary convertirlos de texto a varios archivos de imagen que puedan ser mostrados por Tasker, esperar a que dichos archivos existan, y entonces permitir (o refrescar) que puedan ser accedidos por Tasker. Y antes de todo eso, para almacenar las imágenes tendrías que usar Read Binary, porque Tasker no tiene instrucciones para manejar directamente variables con datos binarios.
Supongo que entre otras cosas, lo que quieres decir con esto es que un elemento menú de una escena de Tasker, nunca podrá mostrar una imagen, verdad? No obstante como te he comentado antes, tengo que empaparme un poco de lo que supone escribir y leer binarios, porque no tengo ni idea, pensaba que eran acciones de Tasker que estaban de adorno. :)
En cuanto vaya probando lo que me has dicho, pondré el resultado por aquí. Gracias de nuevo.
danko9696
08/06/17, 17:01:16
Lo que quiero decir es que necesito que cada fila contenga su correspondiente imagen, tal y como quedaría las etiquetas de un contacto de WhatsApp por ejemplo.
Pero lo que guardes en la BD no tiene por qué ser una imagen propiamente dicha sino la ruta y nombre de archivo de una imagen. En ese caso el proceso será mucho más rápido, porque no hay conversión de datos, escritura y esperar a que el archivo sea visible.
Esto no sería problema, ya que cargo los archivos necesarios en una carpeta de dropbox que tenemos compartida, y que voy sincronizando mediante acciones de Tasker.
A lo que me refiero es que no tiene mucho sentido guardar los archivos de imagen en la base de datos, que encima no van a ser propiamente archivos de imagen sino archivos de imagen convertidos a formato de texto (porque Tasker no permite de otra manera), si no las puedes utilizar directamente. Bueno, sentido supongo que podría tener en algún caso pero no para lo que quieres.
Supongo que entre otras cosas, lo que quieres decir con esto es que un elemento menú de una escena de Tasker, nunca podrá mostrar una imagen, verdad? No obstante como te he comentado antes, tengo que empaparme un poco de lo que supone escribir y leer binarios, porque no tengo ni idea, pensaba que eran acciones de Tasker que estaban de adorno. :)
Yo no diría nunca. Es posible que en el futuro se añada para las imágenes soporte para bases de datos como origen en lugar de archivos, pero ahora mismo no sirve. Aún así podría funcionar usando conversiones intermedias pero el resultado no creo que sea bueno.
Aún así podría funcionar usando conversiones intermedias pero el resultado no creo que sea bueno.
Con esto te refieres a lo que has comentado antes de escribir y leer binarios?
La opción que acabo de intentar, que no había caído hasta ahora, ha sido incluir la ruta del archivo png, en el campo que quiero que figure la imagen, y en poner el texto en formato html, de esta manera;
<IMG SRC="imagen.png">
El caso es que así tampoco funciona, y en vez de la imagen, se ve un cuadro pequeño de color celeste, independientemente de la imagen que ponga.
No entiendo porque no funciona, ya que si utilizo el texto en formato html para poner el texto en negrita, o en cualquier otro color, si que funciona.
danko9696
08/06/17, 19:16:00
Eso que has puesto es para generar páginas web o código del estilo. Para tu caso sería más bien:
Jugador: Hardcore
Equipo: Villabajo
Imagen: 01.png
Jugador: Henry
Equipo: Villabajo
Imagen: 02.png
Jugador: Connor
Equipo: Villarriba
Imagen: 01.png
Jugador: McGregor
Equipo: Villarriba
Imagen: 02.png
Donde cargues las imágenes algo como:
//download/app_liga/imagenes_jugadores/%v_equipo/%v_imagen_jugador(1)
//download/app_liga/imagenes_jugadores/%v_equipo/%v_imagen_jugador(2)
...
//download/app_liga/imagenes_jugadores/%v_equipo/%v_imagen_jugador(11)
Entre medias tendrías que crear el array %v_imagen_jugador y rellenarlo con los datos correspondientes de la BD.
Donde cargues las imágenes algo como:
//download/app_liga/imagenes_jugadores/%v_equipo/%v_imagen_jugador(1)
//download/app_liga/imagenes_jugadores/%v_equipo/%v_imagen_jugador(2)
Quieres decir que escribiendo en un cuadro de texto, la ruta del archivo, como has puesto aquí, debería verse la imagen en vez del texto?
Porque no lo consigo. He probado a poner "//ruta del archivo" con formato de texto html y con formato de texto plano, y no se ve la imagen. También he probado escribiendo "//download/ruta del archivo" porque no tenía claro si download había que ponerlo para llamar a la imagen, o lo habías puesto como si se tratase de una carpeta.
Lo estoy intentado hacer más fácil, sin utilizar base de datos por lo pronto, si no, un simple elemento de texto, hasta que consiga que se vea la imagen.
danko9696
08/06/17, 20:35:48
Logicamente deberías preparar la estructura de carpetas, imágenes cada una en su carpeta correspondiente y con los nombres adecuados. Lo de "download" es solo un ejemplo, podría estar en cualquier otro sitio. De lo que se trata es que debería ser una ruta android válida, y luego añades una estructura con una carpeta con cada equipo e imágenes en cada una de las carpetas.
Lo estoy intentado hacer más fácil, sin utilizar base de datos por lo pronto, si no, un simple elemento de texto, hasta que consiga que se vea la imagen.
¿Estas usando un elemento de texto en lugar de uno de imagen para mostrar imágenes?
¿Estas usando un elemento de texto en lugar de uno de imagen para mostrar imágenes?
Dicho así parece una locura X-D, pero se trata de eso, el fin es que se muestre en un elemento menú, y cómo debe de ser un campo de una base de datos, es necesario que sea texto.
Por lo tanto para agilizar las pruebas, utilizo un elemento de texto.
Tenía esperanzas que con formato de texto html permitiera cargar imágenes, y pensaba que la forma que habías indicado al final, era para eso mismo.
Las etiquetas de las escenas de un elemento menú, permiten poner elementos de imágenes, pero, se repetiría la misma imagen en todas las filas del menú.
danko9696
08/06/17, 22:58:04
Dicho así parece una locura , pero se trata de eso, el fin es que se muestre en un elemento menú
Si quieres que funcione en un elemento menu debes hacer las pruebas en un elemento menu.
y cómo debe de ser un campo de una base de datos, es necesario que sea texto.
Pero si es texto entonces no podrás ver imágenes.
Tenía esperanzas que con formato de texto html permitiera cargar imágenes, y pensaba que la forma que habías indicado al final, era para eso mismo.
Incluso si lo permitiera, que podría haber sido el caso, de algún modo tendrías que indicar la ruta completa a algún archivo y no un "imagen.png" genérico sin apuntar a donde está ese imagen.png. Y aunque funcionase no tiene nada que ver el elemento texto con el elemento menu, que funcione en un sitio no significa que funcione en otro.
Por un lado debes distinguir entre almacenar imagenes en la base de datos, para lo cual hay que usar o bien Blob para almacenarlas tal cual (y que en principio no se puede hacer en Tasker) o bien convertirlas a formato texto y almacenarlas en la base de datos como texto. Y otra cosa MUY distinta a las anteriores es almacenar las rutas de archivos de imagen externos en la base de datos.
He estado mirando el elemento menu, del que daba por hecho que se podrían especificar los iconos con una variable pero no es posible, y he encontrado un sitio donde Pent lo corrobora. Para que haya iconos estos deben de ser fijos, no pueden ser dinámicos. Debes tener cada icono con su etiqueta especifica.
Pero he visto una forma (mala, pero mejor que nada) para hacerlo de forma pseudo-dinámica, que requeriría asumir un máximo de jugadores por equipo, por ejemplo 30 (no sé de cuantos es la plantilla máxima).
//download/app_liga/imagenes_jugadores/%v_equipo/%v_imagen_jugador(1)
Pongamos que tienes:
//download/app_liga/imagenes_jugadores/sevilla/01.png
.
.
//download/app_liga/imagenes_jugadores/sevilla/30.png
..
//download/app_liga/imagenes_jugadores/zaragoza/01.png
.
//download/app_liga/imagenes_jugadores/zaragoza/30.png
.
.
En la base de datos tienes todo bien identificado, ya que con nombre de equipo y nombre de imagen sabes cual coger para cada caso. Si el Zaragoza tiene por ejemplo 25 jugadores, del 26.png al 30.png deberían existir pero sería específica para estos casos (una imagen en blanco, por ejemplo).
Creas una carpeta especifica para archivos temporales y copias en ella 30 imagenes, da igual cuales (porque los vas a sobreescribir después) pero tienen que ser imágenes válidas, por ejemplo los de uno de los equipos:
//download/app_liga/imagenes_temp_menu/01.png
.
.
.
//download/app_liga/imagenes_temp_menu/30.png
En el objeto menu de la escena coges para el primer elemento la imagen de esa ruta especial, con 01.png para el primero, para el segundo 02.png, ..., hasta el 30.png. Como nombre de momento usaremos una variable global (luego ya se vería a ver si se puede evitar), por ejemplo %JUGADOR1 para el primer elemento, %JUGADOR2 para el segundo, etc...
El proceso sería:
- Crear el array %JUGADOR1...%JUGADOR30. Si un equipo tiene solo 22, contando reservas, en los últimos 8 pones un guión, un espacio o lo que quieras y asignarle los nombres de jugadores que correspondan.
- Para los iconos, si por ejemplo se trata del zaragoza, copiariamos todos los archivos sobreescribiendo de ..../imagenes_jugadores/zaragoza a .../imagenes_temp_menu, de modo que aunque para el primer jugador siempre carga el 01.png de esa ruta, este 01.png en realidad va a ser distinto según el equipo que sea.
- Ahora cargas la escena.
- Al cerrar la escena te cargas el array %JUGADOR.
Es diferente a mi planteamiento inicial, y es posible que tenga que cambiar muchas cosas en el proyecto, puesto que hasta ahora, lo que venía haciendo era rellenar las etiquetas del elemento menú, con el contenido de la base de datos, por lo tanto se rellenaba automáticamente. Supongo que te has fijado que hay tres formas de rellenar las etiquetas (variables, arrays o manual).
Además, la tabla no estaba dividida por equipos. Se trataba de una lista de jugadores de diferentes equipos, que subían o bajaban posiciones en el orden de la tabla (mejor dicho, en el orden en el que se mostraba la tabla), en base al número de goles que llevaban.
Pero he visto una forma (mala, pero mejor que nada)
Por lo pronto lo he probado como has dicho, con una carpeta temporal y una de un equipo y funciona perfectamente. No obstante tengo dudas de si finalmente podré utilizar este método para este proyecto en concreto, pero de lo que no tengo ninguna duda es que la solución es ingeniosa y puede que la única para modificar las imágenes de las etiquetas, por lo tanto abre muchas puertas para trabajar con escenas de Tasker. Por lo pronto ya has conseguido que esta noche pierda unas cuantas horas de sueño.
Iré poniendo por aquí el resultado de como va quedando para el que le pueda interesar. Muchas gracias de nuevo, si no hubiera notado por tus comentarios, que te gusta poco el fútbol, te invitaría a jugar la liga :D. Un saludo!
danko9696
09/06/17, 12:53:10
Supongo que te has fijado que hay tres formas de rellenar las etiquetas (variables, arrays o manual).
Puedes rellenar el menu con un array pero entonces no puedes asignar los iconos, solo se puede en modo manual. Ese es el problema y que yo daba por hecho, que se podría ambas cosas, que si se puede asignar el texto del label dinámicamente lo lógico es que pase lo mismo con los iconos. Me extraño y busqué hasta que vi que alguien preguntaba lo mismo y respondía Pent que no. Pero vamos, es el tipo de cosas que probablemente está en la lista de mejoras a realizar, aunque seguramente no con mucha prioridad.
Es diferente a mi planteamiento inicial, y es posible que tenga que cambiar muchas cosas en el proyecto, puesto que hasta ahora, lo que venía haciendo era rellenar las etiquetas del elemento menú, con el contenido de la base de datos, por lo tanto se rellenaba automáticamente.
El planteamiento inicial es exactamente el mismo y no hay que cambiar apenas nada, porque creo que tal como tenías planteado obtenías un array con nombres de jugadores y sus imágenes. Tan solo es modificar el elemento menu de la escena y añadir un poco de código. Si ya tienes imágenes asociadas a cada jugador con su nombre de archivo en la BD no es más que recorrer el array antes pasabas en un bucle (ahora con la info adicional de la imagen) y realizar este proceso para cada elemento, junto con gestionar el array global para solo los nombres. Por ejemplo si el primero de la lista es pepito.png copiar y renombrarlo como 01.png en la carpeta temporal, el segundo como 02.png, etc...
Además, la tabla no estaba dividida por equipos. Se trataba de una lista de jugadores de diferentes equipos, que subían o bajaban posiciones en el orden de la tabla (mejor dicho, en el orden en el que se mostraba la tabla), en base al número de goles que llevaban.
Entonces es bastante mejor, porque si (asumo) hay un número fijo de jugadores no habrá huecos vacíos.
Muchas gracias de nuevo, si no hubiera notado por tus comentarios, que te gusta poco el fútbol, te invitaría a jugar la liga . Un saludo! La verdad que no, no soy muy aficionado al deporte nacional XDD. De hecho podría decir que lo soy más del de Tailandia.
El planteamiento inicial es exactamente el mismo y no hay que cambiar apenas nada
Si que me está costando un poco hacer las modificaciones. Es un poco complejo de entender sin utilizar el proyecto, pero para que te hagas una idea...
La escena principal, como ya he comentado, esta compuesta por un elemento menú, en la cual tras una consulta SQL Query, se actualizan todos los jugadores, y además tengo un icono, que utilizo para añadir jugadores a la tabla, mediante INSERT INTO.
De esta forma, cada vez que haya que agregar un jugador (cada vez que un jugador que no esté en la tabla, marque un gol) se añade sin necesidad de modificar la escena, y lo puede hacer cualquiera de mis amigos que tienen la aplicación.
Pero al utilizar el elemento menú, en modo "manual", cada vez que haya que agregar un jugador, tengo que hacer modificaciones en la escena, porque no hay ninguna acción de Tasker, que permita añadir un ITEMS, al elemento menú.
De hecho podría decir que lo soy más del de Tailandia.
Buen deporte también, habrá que construir un proyecto sobre Muay thai
danko9696
11/06/17, 12:53:47
Si que me está costando un poco hacer las modificaciones. Es un poco complejo de entender sin utilizar el proyecto, pero para que te hagas una idea...
La escena principal, como ya he comentado, esta compuesta por un elemento menú, en la cual tras una consulta SQL Query, se actualizan todos los jugadores, y además tengo un icono, que utilizo para añadir jugadores a la tabla, mediante INSERT INTO.
De esta forma, cada vez que haya que agregar un jugador (cada vez que un jugador que no esté en la tabla, marque un gol) se añade sin necesidad de modificar la escena, y lo puede hacer cualquiera de mis amigos que tienen la aplicación.
Pero al utilizar el elemento menú, en modo "manual", cada vez que haya que agregar un jugador, tengo que hacer modificaciones en la escena, porque no hay ninguna acción de Tasker, que permita añadir un ITEMS, al elemento menú.
Yo estaba pensando en meter todos los jugadores, así no tienes que cambiar el menu salvo que haya fichajes, y si los hay tendrías que añadir las nuevas fotos de todos modos. Asume 25 jugadores por equipo y luego en la consulta puedes ordenar primero por goles descendente y después por nombre ascendente, así los que no tienen goles te aparecen al final alfabéticamente y no molestan. Solo tendrías que modificar el menu una vez o dos al año (para contar con traspasos). Y esos cambios que no pueden ser hechos meramente con consultas serían necesarios de todos modos si pensabas contar con fotos de jugadores.
Lo único, que el proceso de escritura de archivos cada vez que se modifican los goles puede llevar algún tiempo, sobreescribir unos 500 archivos pequeños (mucho mejor en la memoria interna antes que la SD externa). Si merece la pena dependerá de cómo de rápido se produzca, aunque si tarda mucho se podría investigar la posibilidad de usar un ramdrive para acelerar el proceso (si se cuenta con root).
Contarías con la ventaja de que ya que tienes todos los jugadores metidos podrías meter más campos para no solamente ver la lista de goles sino también plantillas y alineaciones, con una escena adicional con menu de 25 elementos y otra de 11.
Buen deporte también, habrá que construir un proyecto sobre Muay thai
Soy más de MMA pero el Muay Thai no está mal, aunque a veces es aburrido si están todo el rato con clinching. Y aún así lo prefiero al fútbol XDD
Caravantes
24/10/18, 10:19:21
La noticia que voy a añadir no pretende mancillar ni distraer la vertiente técnica de este hilo, sino añadir una noticia jocosa y humorística. Espero no molestar a nadie.
El creador de SQLite crucificado tras adoptar como código de conducta amar a Dios, no matar, cometer adulterio o robar. El proyecto de la base de datos de código abierto SQLite ha dicho a sus desarrolladores que esperan que sigan a Cristo, amen la castidad, vistan a los desnudos y no asesinen, roben ni duerman con los cónyuges de sus colegas. Ese es el resultado de un código de conducta algo atípico que el proyecto ampliamente utilizado ha publicado en línea. SQLite ha optado por reglas elaboradas por San Benito hace más de 1.500 años. El código de conducta ha atraído una atención significativa y la inevitable ola de rabia y condena de Twitter.
Vía Menéame: https://www.meneame.net/m/tecnolog%C3%ADa/creador-sqlite-crucificado-tras-adoptar-como-codigo-conducta-no
Noticia original en inglés: https://www.theregister.co.uk/2018/10/22/sqlite_code_of_conduct/
vBulletin® v3.8.1, Copyright ©2000-2026, Jelsoft Enterprises Ltd.