Consulta SQL sin saber el número de columnas

Caotico

Hola, os describo un poco por encima lo que tengo, es un proyecto en php + mysql y estoy utilizando pdo para lanzar consultas.

Ocurre lo siguiente, tengo una tabla en la cual el usuario via web puede añadir columnas ( sin phpmyadmin) y en la web principal tengo un bucle el cual recorre toda la tabla y muestra todos los datos. Para esto no tengo ningún problema, porque aunque no sepa cuantas columnas hay en la tabla las puedo sacar de information_schema.columns.

La cuestión es la siguiente, cómo debo programar para que cuando el usuario quiera introducir una tupla en la tabla pueda hacerlo ? Yo no sé cuántas columnas hay, por lo tanto a la hora de hacer el insert into se me complica bastante la cosa.

Se me ha ocurrido hacer un insert into y sólo añadir la clave primaria, y después recoger todos los datos e ir recorriéndolos en un bucle mientras hago un update sobre esa tabla. Pero claro, si la tabla tiene 50 campos, para añadir una sola tupla voy a hacer 50 consultas y lo veo poco eficiente.

Alguna recomendación? De la misma forma, el usuario debe poder lanzar consultas, y creo que el problema con las consultas va más o menos de la mano a lo que estoy diciendo anteriormente.

Si me podéis ayudar con la lógica de esto os lo agradezco xD un saludo.

Meleagant

Utiliza DESCRIBE, te devuelve la estructura de la tabla y desde ahí puedes extraer cualquier información que necesites.

1 respuesta
Caotico

#2 Es que no necesito extraer información de la tabla, accedo a ella sin problemas. Lo que necesito es algún algoritmo para añadir los datos o lanzar consultas que me permita hacerlo de una forma dinámica, que funcione igual con 1 campo o con 100.

EDIT: Lo matizo más, la cuestión es que cuando haga el INSERT INTO tabla VALUES (?, ?, ?);
Ahí he puesto para que añada 3 valores, la cusetión es cómo modificar eso para que añada 3 o 100

2 respuestas
Merkury

#3 Hombre lo que puedes hacer es generar un Form dinámico en base a los campos de la tabla, y hacer que todos sean nullables, y que el usuario meta la info que le salga del pene y con php haces un insert normal y corriente del tipo INSERT INTO tabla (columna1, columna2, ..., columnaN) VALUES ($valores, $del, $form);

1 respuesta
JuAn4k4

Consultas dinamicas, la creas con cuidado en un string.

Con cuidado de SQL Injection

1 2 respuestas
Caotico

#4 Vale, Pero lo que tú me dices es estático, cómo sé cuántos values voy a añadir? Eso está escrito ya y programado para X values, no? Igual el usuario ahora me ha enviado 4 values y la próxima vez me envía 15.

#5 Con eso te refieres a que haga un while que recorra el array de valores recibidos y los voy añadiendo en una variable string y luego la lanzo?

#7 Pero es que la tabla no tendrá siempre los mismos values. Igual hoy tiene 25, mañana crea una columna nueva y cuando genere un registro nuevo ya no se añadirá.

1 respuesta
Merkury

#6 No he dicho nada XD

#6 Pues haz con PHP una extracción dinámica de todas columnas a un array y luego haz la consulta pintando cada columna en orden en la consulta XD.

#8 Si, pero no se eh yo veo altas posibilidades de petada o que te peten XDDD

1 2 respuestas
Caotico

#7 Algo así como dice #5 ?

Me quedará añadirlo todo a un string y ya está, no?

#7 Inicialmente es para algo interior sin salida a internet, pero si el día de mañana les da por ponerlo semi público la liamos....
Y aún así me parece un método muy guarro no sé si habrá otra cosa xD he estado mirando con los prepared statement pero no encuentro nada que se ajuste.

1 respuesta
Merkury

Yo lo digo porque dejar a usuarios agregar columnas a una BBDD es una locura, como casi cualquier cosa que le dejes hacer a un usuario delante de un ordenador.

1
Caotico

Ya, pero me lo piden así. Le limito bastante cómo agregar la columna y sólo le dejo elegir nombre y tipo. El único problemilla que me surgía era este, el de agregar nuevos datos.

1 respuesta
Meleagant

#3 No sé si te estoy entendiendo, pero si es lo que yo creo, tan sencillo como poner un bucle en PHP para generar la consulta en String.

query= "INSERT INTO tabla VALUES("
for(int i=0; i< num_valores-1; i++){
  valor = extraerValorFormulario(i)
  query+= valor + ", "
}
valor = extraerValorFormulario(num_valores-1)
query+= valor + ") RESTO DE CONSULTA"

Es más pseudocódigo que PHP, pero creo que se entiende lo que quiero decir.

1 2 respuestas
Lecherito

#10 Como ya te han dicho por ahí arriba, consultas dinámicas, no hace falta saber los nombres de las columnas ni nada, insert into tabla (a,b,c) y como ya te han dicho por ahí también ten cuidado con las Inyecciones:

mysql_real_escape_string($value); es la función que necesitas, de ahí si sabes crear una tabla con las columnas, también sabes meter un textBox por cada columna abajo del todo y cuando rellene todas (las que requieran not null) pues hacer el insert into.

1 respuesta
Caotico

#11 Sí, eso me servirá.

#12 No acabo de entender lo del textbox para comprobar los nulos.

Caotico

#11 Me estoy dando cuenta de que como pongan algún value en blanco, me generará la siguiente consulta

Insert into tabla values (,,11,texto,00,,);
Y por las comillas me petará, alguna idea de como solucionarlo? xD

#15 Gracias, eso va dentro del for, verdad?
EDIT: OK perfecto, muchas gracias

2 respuestas
Merkury

#14

if(strlen($var) > 0)
{
     <haz lo que sea>
}else
{
      $var = null;
}
1 1 respuesta
Caotico

Uf, peta por el entrecomillado de los datos. Los tipo text tienen que ir entre ' ' y los número sin nada. Pensé que con PDO esto daba igual xD. Pasaría algo si añado todos como ' ' incluidos los números (int,float,etc)?

#17 Creo que no es eso a lo que yo me refiero. Yo quiero decir que cuando hago un insert into tabla values ('texto',numero,' date ' );
Si el tipo de campo es texto en el insert debe ir entre comillas, no? el número no. Qué pasa si meto todos entre comillas y fuera?

#17 Bueno y lo que dices tú, esa es otra, como quieran añadir signos en plan = " ' ; en una descripción, qué hacemos? xDD Alguna sugerencia?

#17 Hago una función, recorro todo el campo texto antes de guardarlo en la base de datos y elimino los carácteres especiales que puedan darme problemas. Pero y si quiero guardarlos? xD Ando perdido en strings. Tengo un campo que es descripción y ahí deben poder escribir parrafadas de 1000 carácteres y quiero guardar todo.

Poniendo una barra invertida delante de todos los carácteres especiales los almacenaría?

1 respuesta
Merkury

#16 Escapalos

http://pastebin.com/v4gwQf6u

Te lo dejo en pastebin para que se vean todos caracteres que en MV en las tags code no se puede usar la contrabarra XD

He puesto un delete, que es la primera que he pillado de uno de mis proyectos XD

#16 Sanea el nombre hazte una función que coja el nombre de la columna y con una expresión regular elimine todos simbolos excepto el _ y fiesta :D

#17 Para guardar los textos, yo lo que haría sería un campo text, teniendo la base de datos codificada en utf8 y simplemente escapando el texto y prau.

Lo de limpiar el texto me referia al texto que vayas a usar como nombre de columna, porque no te metan cosas raras en plan column!a-35135-lele%$$%, en la descripción lo que te digo. sin pasar la función de limpieza XD.

2 respuestas
Caotico

#17 Vale, pero cómo almaceno el texto. Aunque esté en utf8 ese campo no me dejará almacenarlo porque al generar la consulta la generará con toda la parrafada de texto y como pille unas comillas dobles o unas comillas simples va creer que se trata de código php y ya no ejecutará el resto de la consulta.

$texto = ' Contenido: " 2 sets ", ' 3 packs ' ; 1 Equipo: -- ';

Si eso estuviese dentro de la variable $texto como leches podría almacenarlo? XD Las comillas de inicio y fin son la que está al lado de la letra C de contenido y la que está al lado del ; final. Todo lo de dentro sería texto a guardar.

Merkury

A ver pega el código tal como lo tienes

Lecherito

mysql_real_escape_string($value), te lo puse en #12

1 respuesta
Caotico
		$query = 'insert into equipo values(';
		//Aquí recorro el array para VALUES
		for ($c = 1; $c < $col; $c++) {
			if(strlen($AnadirDato[$c-1]) == 0) {
			$query = $query.$AnadirDato[$c-1].'NULL,';
			}
			else{
			$query = $query."'".$AnadirDato[$c-1]."',";
			}
		}
		$query = $query."'".$AnadirDato[$col-1]."');";// Con $col-1 Obtengo el último resultado 

La cosa es que uno de estos campos es un varchar(1000) y quiero que se almacene todo lo que se escriba en ese campo.
#20 He probado como dices y tampoco me funciona.

1 respuesta
Merkury

#21 Pon un campo text y no un varchar que para guardar textos tipo descripción va mejor.

1 respuesta
Caotico

#22 Lo he hecho y sigue sin poder dejarme añadir ese tipo de carácteres, el problema está en como lo estoy planteando en php.

Pregunta tonta, cómo guarda los datos un foro? En un post puedes escribir los carácteres que te de la gana y lo guarda bien. Cómo ejecuta la variable donde está el texto que permite guardar comillas y cualquier carácter?

#24 Yo he metido comillas para ver si se hacía un lío y me sale el siguiente mensaje de error ( Te pego la consulta y el mensaje de error, ambos. )

insert into equipo values('Camara15','12',NULL,NULL,NULL,NULL,'" " ' ' ; TEXTO ;: " ? ');

Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: no parameters were bound in C:\xampp\htdocs\index1.php on line 68

El texto que yo he metido en el input es este: " " ' ' ; TEXTO ;: " ?

La línea 68 es : $stmt->execute();

Y funcionar funciona bien, a menos que le meta comillas

He probado lo de mysql_real_escape_string pero parece que le da igual, da el mismo mensaje.

1 respuesta
Merkury

#23 En teoria con las comillas tal como te digo deberías poder, yo asi en mi PFC guardaba fragmentos enteros de código HTML

Y mira la consulta

$insertPseudo = mysql_query("INSERT INTO savedpseudo (userid, pseudo, fechaCreacion) VALUES('".$row['id']."', '".$textPseudo."', '".$fecha."')");

#23 Es que esa conusulta las comillas estan mal cerradas y sin escapar poner

 '""''; 

hay una comilla de mas

2 respuestas
Caotico

#24 Pero es que es lo que te digo xD se genera al recoger la variable, no es que esté mal en el código ( o eso creo porque ya tengo un lío encima )

Te pego una consulta poniendo datos normales para que veas el query que envía:

insert into equipo values('Camara16',NULL,NULL,NULL,NULL,NULL,'TEXTO');
2 respuestas
Lecherito

#25 Si eso no te funciona tienes las prepared statementes: http://stackoverflow.com/questions/60174/how-to-prevent-sql-injection-in-php

#27 también algo del tipo pg_escape_literal() o pg_escape_string()

1 1 respuesta
Caotico

Edit: #26 Vale ! una parte ya está solucionada, con los prepared statements por mucho que metan comillas y demás el código lo ejecuta y lo guarda. La cuestión es que guarda sólo una parte no todo.

Cuando detecta que intentan hacer una inyección lo corta, pero a mi me interesa que se guarden todos los carácteres sin que inyecte mierda en el código php xD no sé si eso será posible

Edit #26 No me van esas funciones, son para postgre?

Yo lo que digo, debe de haber alguna forma en la que los foros guardan los mensajes, no? Pues algo así quiero, lo que vendría siendo la consulta que guarda el post de un usuario. Yo en este post puedo poner comillas o lo que quiera, como si quiero meter código sql, que en la base de datos lo guardará, algo así necesito.

1 respuesta
JuAn4k4

No sería más sencillo NO dejar que crearan columnas, sino tener tu tu modelo de base de datos, que te permita tener objetos con propiedades ?

Lo digo mas que nada porque ¿ Que es lo que te estan pidiendo ? porque segurament no te pediran "Quiero añadir y quitar columnas de la base de datos", sino "Quiero poder añadirle atributos/propiedades a este objeto".

Vease: Quiero que una noticia ahora solo tenga titulo y descripicón, pero en un futuro le pondre Fecha, autor y demás.

¿ Es algo así ?

Y tu tus consultas seran :

Obten objeto X de la tabla entidades.
Obten propiedades del objeto X de la tabla propiedades

o como quieras hacerlo, pero no el lio que estas montando.

2 respuestas
Soltrac

Venía a preguntar algo parecido a lo de #28....

Te han pedido exactamente eso o tú has asumido que es la mejor solución para tu problema?

1 respuesta
Caotico

#28 #29 Me han pedido que deben poder añadir y quitar columnas cuando quieran, no ocultar o mostrar datos.

Eso no es un problema actualmente, el problema es por ejemplo que si esto lo enfoco a publicar noticias y quiero redactar una noticia no podrá tener según qué carácteres porque no inyectará el código en la base de datos.

1 respuesta