2011-04-07 21 views
7

Tengo un objeto de filtro para consultar una tabla con muchas columnas, y en lugar de escribir una condición que cubre todas las columnas (que permite la filtración opcional) así:Cómo consultar los nombres de columna dinámicamente utilizando Postgres/Npgsql

WHERE ((:value0 IS NULL) OR (column_name0 = :value0)) AND ((:value1 IS NULL) OR (column_name1 = :value1)) AND... etc 

para cada columna. En su lugar, me gustaría idealmente me gustaría ser capaz de pasar en el nombre del campo como un parámetro:

WHERE :column_name0 = :value0 AND column_name1 = :value1 AND... etc 

que no es posible ya que se requieren las columnas en tiempo de análisis (similar a esta respuesta given here) .

¿Cómo superar esto? - Realmente no quiero tener que mantener el SQL cuando se agregan o eliminan nuevas columnas (como tendrías que hacer en mi primer ejemplo) y creo que sería peligroso para mí construir los nombres de las columnas en la cadena de comandos directamente ya que esto podría permitir la inyección de sql.

Tenga en cuenta que este código está detrás de un servicio web.

+0

¿Por qué a menudo es necesario añadir o eliminar columnas? ¿Qué buena razón hay para tal necesidad? –

+0

@ypercube, no necesito hacer esto a menudo. Simplemente no quería mantener el sql en mi objeto de filtro para cada cambio en mi base de datos y al mismo tiempo proporcionar un objeto flexible para filtrar datos. –

Respuesta

23

Solo asegúrese de que los usuarios finales no puedan proporcionar los nombres de las columnas directamente y debe estar seguro al construir la consulta manualmente. Si necesita averiguar qué nombres de columna son válidos en tiempo de ejecución puede utilizar la siguiente consulta:

SELECT column_name 
FROM information_schema.columns 
WHERE table_schema='public' AND table_name='yourtablename' 
+1

+1 para la idea de obtener nombres válidos de columnas. nota: como se trata de un servicio web, el software del cliente proporciona la información de filtrado, y aunque se implementa la seguridad/autenticación, aún podría ser posible llamar al servicio web con datos distintos a los del cliente. –

+0

Voy a utilizar su idea para almacenar el lado del servidor de nombres de columna (permitido) en un diccionario de nombres de columna (dentro de un diccionario de nombres de tabla) al inicio del servicio. El cliente puede referirse a la clave y no a los nombres reales de la tabla o columna (s) para usar en el objeto de filtro –

1

creo que la solución más fácil es construir la sentencia SQL sobre la marcha.

La inyección SQL no es posible si usa parámetros para los datos proporcionados por el usuario.

+0

Sí, sobre la marcha es una solución fácil, pero como se trata de un servicio web con el cliente pasando los criterios de filtrado, incluida la información de la columna, aún pueden estar abiertos al ataque. –

+1

Tiene razón, si los nombres de las columnas son proporcionados por el usuario, entonces es peligroso. Una solución (no perfecta) es solo permitir caracteres (A-Z, a-z) y el guión bajo (_). Y posiblemente dígitos (0-9), pero no al principio. –

+0

El cliente es la aplicación cliente. +1 para las respuestas correctas, aunque @Eelke ha proporcionado la mejor idea para responder mi pregunta. –

0

ejemplo:

NpgsqlCommand command = new NpgsqlCommand(SQL, Connection); 
     Npgsql.NpgsqlDataReader Resource = command.ExecuteReader(); 

     while (this.Resource.Read()) 
     { 
      for (int i = 0; i < this.Resource.FieldCount; i++) 
      { 
       string field = this.Resource.GetName(i).ToString(); 
      } 
     } 
Cuestiones relacionadas