2008-10-28 22 views
203

¿Por qué alguien usar WHERE 1=1 AND <conditions> en una cláusula SQL (SQL obtiene a través de cadenas concatenadas, ya sea vista definición)¿Por qué alguien debería usar WHERE 1 = 1 AND <conditions> en una cláusula de SQL?

que he visto en alguna parte que esto podría ser utilizado para proteger contra la inyección de SQL, pero me parece muy raro.

Si hay inyección WHERE 1 = 1 AND injected OR 1=1 tendría el mismo resultado que injected OR 1=1.

Edición posterior: ¿Qué pasa con el uso en una definición de vista?


Gracias por su respuesta.

Aún así, No entiendo por qué alguien usaría esta construcción para definir una vista, o la usaría dentro de un procedimiento almacenado.

dar esto por ejemplo:

CREATE VIEW vTest AS 
SELECT FROM Table WHERE 1=1 AND table.Field=Value 
+2

* "¿Por qué alguien utilizar esta construcción para la definición de una visión" * Probablemente por costumbre. No ofrece ninguna ventaja funcional en consultas estáticas. – ADTC

Respuesta

285

Si la lista de condiciones no se conoce en tiempo de compilación y en su lugar se construyó en tiempo de ejecución, usted no tiene que preocuparse de si usted tiene uno o más de Una condición. Puede generarlos todos como:

and <condition> 

y concatenarlos todos juntos. Con el 1=1 al inicio, el and inicial tiene algo con lo que asociarse.

Nunca lo he visto usado para ningún tipo de protección de inyección, como dices, parece que no ayudaría mucho. I tengo lo he visto como una conveniencia de implementación. El motor de consulta SQL terminará ignorando el 1=1 por lo que no debería tener ningún impacto en el rendimiento.

+12

Ha habido casos en el pasado de SQL Server generar planes deficientes cuando se utiliza esta técnica. Por esa razón, ya no lo uso, a menos que la consulta esté dirigida a recuperar la definición del esquema. –

+2

De acuerdo. Vote por responder la pregunta, pero recomiendo codificar la consulta correctamente para empezar, en lugar de ser flojo. – Ady

+24

A veces no se trata de ser flojo, sino de tener un código más limpio. –

20

Parece una manera perezosa de saber siempre que su cláusula WHERE ya está definida y le permite seguir agregando condiciones sin tener que comprobar si es la primera.

+5

* "Lazy" * Me gusta pensar que es inteligente, no floja. Está evitando el código repetitivo y las verificaciones de condición innecesarias. Sin poder agregar 'where 1 = 1' (Oracle) o' where true' (Postgres), tendré que verificar para cada condición si es la primera. No tiene sentido hacerlo, y solo agrega más código repetitivo. – ADTC

+1

@ADTC El código de escritura es a menudo, si no principalmente, sobre el manejo de diferentes condiciones. Esta es solo otra condición que debe ser manejada, lo que personalmente creo que es perezoso para contaminar el SQL generado. Si construye su código para agregar 'Donde 1 = 1' en UN lugar, podría, con un pequeño esfuerzo adicional, manejar la diferencia entre cero y muchas condiciones en ese UN lugar en su código. Sin embargo, mi conjetura es que aboga por 'Donde 1 = 1' lo salpique a lo largo de su código base, lo que me lleva a la conclusión de que la pereza engendra pereza. –

+0

@JasonS La pereza es el padre de Invention. – ADTC

12

1 = 1 expresión se utiliza comúnmente en código sql generado. Esta expresión puede simplificar el código de generación sql reduciendo el número de enunciados condicionales.

31

Lo he visto usado cuando el número de condiciones puede ser variable.

Puede concatenar condiciones utilizando una cadena "Y". Luego, en lugar de contar la cantidad de condiciones que está ingresando, coloca un "DÓNDE 1 = 1" al final de su instrucción stock SQL y arroje las condiciones concatenadas.

Básicamente, le ahorra tener que hacer una prueba de condiciones y luego agregar una cadena "DONDE" antes de ellas.

+0

Eso es exactamente lo que hago, no podría haberlo dicho mejor. – Eli

99

Simplemente añadiendo un código de ejemplo para la respuesta de Greg:

dim sqlstmt as new StringBuilder 
sqlstmt.add("SELECT * FROM Products") 
sqlstmt.add(" WHERE 1=1") 

''// From now on you don't have to worry if you must 
''// append AND or WHERE because you know the WHERE is there 
If ProductCategoryID <> 0 then 
    sqlstmt.AppendFormat(" AND ProductCategoryID = {0}", trim(ProductCategoryID)) 
end if 
If MinimunPrice > 0 then 
    sqlstmt.AppendFormat(" AND Price >= {0}", trim(MinimunPrice)) 
end if 
+3

bit hacky, pero parece ser un uso válido. – Mike

+5

Esta debería ser la respuesta aceptada. La práctica realmente es piratear para no tener que determinar cuántos condicionales tienes. – aglassman

10

En realidad, he visto este tipo de cosas se utiliza en BIRT informes. La consulta pasada al tiempo de ejecución BIRT es de la siguiente forma:

select a,b,c from t where a = ? 

y el '?' se reemplaza en el tiempo de ejecución por un valor de parámetro real seleccionado de un cuadro desplegable.Las opciones en el menú desplegable se dan por:

select distinct a from t 
union all 
select '*' from sysibm.sysdummy1 

para que obtenga todos los valores posibles plus "*". Si el usuario selecciona "*" en el cuadro desplegable (lo que significa que deben seleccionarse todos los valores de a), la consulta debe ser modificada (por Javascript) antes de ejecutarse.

Dado que el "?" es un parámetro de posición y debe permanecer allí por otras cosas para trabajar, el Javascript modifica la consulta sea:

select a,b,c from t where ((a = ?) or (1==1)) 

Que básicamente elimina el efecto de la cláusula where al mismo tiempo dejando el parámetro de posición en su lugar.

También he visto el caso AND utilizado por los codificadores perezosos mientras se crea dinámicamente una consulta SQL.

Digamos que tienes para crear dinámicamente una consulta que se inicia con select * from t y cheques:

  • el nombre es Bob; y
  • el salario es> $ 20.000

algunas personas se sumaría el primero con un WHERE y las posteriores con una Y de este modo:

select * from t where name = 'Bob' and salary > 20000 

Los programadores perezosos (y eso no es necesariamente una mal rasgo) no distinguiría entre las condiciones agregadas, comenzarían con select * from t where 1=1 y simplemente agregarían cláusulas AND después de eso.

select * from t where 1=1 and name = 'Bob' and salary > 20000 
+1

* "Lazy" * Me gusta pensar que es inteligente, no floja. Está evitando el código repetitivo y las verificaciones de condición innecesarias. Sin poder agregar 'where 1 = 1' (Oracle) o' where true' (Postgres), tendré que verificar para cada condición si es la primera. No tiene sentido hacerlo, y solo agrega más código repetitivo. – ADTC

+1

@ADTC, no quise decir vago de una mala manera. De hecho, "perezoso" es un "buen" rasgo en la programación :-) Lo aclararé. – paxdiablo

0

llegué por primera vez a través de esta de vuelta con ADO y ASP clásico, la respuesta que obtuve fue: rendimiento. si lo hace una recta

Select * from tablename

y pasar de que en como un comando/texto sql obtendrá un aumento notable en el rendimiento con el

Where 1=1

añade, era visible diferencia. algo que hacer con los encabezados de tabla que se devuelve tan pronto como se cumple la primera condición, o alguna otra locura, de todos modos, aceleró las cosas.

+6

Eso suena completamente idiota para mí, pero completamente creíble ... – flussence

+2

Si eso es cierto, ¿por qué el DBMS no siempre agrega eso? – Carcamano

+4

¿Se puede presentar evidencia? –

9

donde 1 = 0, Esto se hace para verificar si la tabla existe. No sé por qué se usa 1 = 1.

+0

Visto esto solía devolver un conjunto de resultados vacío de la base de datos para ser utilizado como titular de nuevos registros. –

5

Mientras puedo ver que 1 = 1 sería útil para SQL generado, una técnica que utilizo en PHP es crear una matriz de cláusulas y luego hacer

implode (" AND ", $clauses); 

evitando así el problema de tener un líder o al final AND. ¡Obviamente esto solo es útil si sabes que vas a tener al menos una cláusula!

+0

Ahí es donde entra el 1 = 1. Te da esa "al menos una cláusula" para que no tengas que preocuparte solo de presionar un "AND abc" – Carl

+0

¡Me gusta esta idea! Consulte aquí para obtener un ejemplo más completo http://stackoverflow.com/questions/35326160/how-to-write-php-ternary-operator-with-array-value – drooh

4

Aquí hay un ejemplo muy relacionado: usar una declaración SQL MERGE para actualizar el destino presentado utilizando todos los valores de la tabla fuente donde no hay un atributo común para unirse, p.

MERGE INTO Circles 
    USING 
     (
     SELECT pi 
     FROM Constants 
    ) AS SourceTable 
    ON 1 = 1 
WHEN MATCHED THEN 
    UPDATE 
    SET circumference = 2 * SourceTable.pi * radius; 
0

El uso de un predicado como 1=1 es una pista normal, a veces se utiliza para forzar el plan de acceso para usar o no usar un recorrido de índice. La razón por la que esto se usa es cuando está utilizando una consulta combinada de múltiples anidados con muchos predicados en la cláusula where donde a veces incluso el uso de todos los índices hace que el plan de acceso lea cada tabla, una exploración de tabla completa. Esta es solo una de las muchas sugerencias utilizadas por los administradores de bases de datos para engañar a los administradores de bases de datos con una ruta más eficiente. Simplemente no arroje uno; necesita un dba para analizar la consulta, ya que no siempre funciona.

+2

¿Tiene alguna cita que documente este comportamiento para algunas bases de datos? – Joe

9

indirectamente relevantes: cuando 1 = 2 se utiliza:

CREATE TABLE New_table_name como SELECT * FROM Old_table_name donde 1 = 2;

Esto creará una nueva tabla con el mismo esquema que la tabla anterior. (Muy práctico si desea cargar algunos datos para comparar)

+0

Se olvidó de agregar, aunque creará una nueva tabla con los mismos datos que la anterior, la nueva tabla no tendrá otras restricciones, como la clave externa de la tabla anterior – milso

0

Lo hago generalmente cuando estoy creando SQL dinámico para un informe que tiene muchos valores desplegables que un usuario puede seleccionar. Dado que el usuario puede o no puede seleccionar los valores de cada menú desplegable, terminaremos teniendo dificultades para determinar qué condición era la primera cláusula where. Por lo tanto, completamos la consulta con un where 1=1 al final y agregamos todas las cláusulas posteriores a eso.

Algo así como

select column1, column2 from my table where 1=1 {name} {age}; 

Entonces construiríamos la cláusula where como esto y pasarlo como un valor de parámetro

string name_whereClause= ddlName.SelectedIndex > 0 ? "AND name ='"+ ddlName.SelectedValue+ "'" : ""; 

Como el que la selección cláusula son desconocidas para nosotros en tiempo de ejecución, por lo que este nos ayuda mucho a la hora de encontrar si se incluye un 'AND' or 'WHERE'.

4

¿Por qué alguien debería usar DONDE? 1 = 1 y <proper conditions>

he seen marcos de andar por casa hacen cosas como esta ( rubor), ya que esto permite que las prácticas de análisis perezosos que han de aplicarse tanto a las palabras clave de SQL WHERE y AND.

Por ejemplo (estoy usando C# como un ejemplo aquí), consideran que el análisis condicional de los siguientes predicados en una consulta SQL string builder:

var sqlQuery = "SELECT * FROM FOOS WHERE 1 = 1" 
if (shouldFilterForBars) 
{ 
    sqlQuery = sqlQuery + " AND Bars > 3"; 
} 
if (shouldFilterForBaz) 
{ 
    sqlQuery = sqlQuery + " AND Baz < 12"; 
} 

El "beneficio" de WHERE 1 = 1 significa que ningún código especial se necesita:

  • Para y - ya sea cero, uno o ambos predicados (bares y Baz de) se debe aplicar, lo que determinar si se requiere la primera AND. Como ya tenemos al menos un predicado con el 1 = 1, significa que AND siempre está bien.
  • Para ningún predicado en absoluto: en el caso en que hay predicados CERO, debe soltarse el WHERE. Pero nuevamente, podemos ser flojos, porque nuevamente estamos garantizados de al menos un predicado.

Esto obviamente es una mala idea y recomendaría usar un marco de acceso de datos establecido o ORM para analizar los predicados opcionales y condicionales de esta manera.

+0

O, si lo hace, el constructor cláusula where debería estar en un lugar en su código . Entonces puede manejar predicados cero o más de cero predicados en una sola ubicación en su código. Mi sospecha es que la existencia de 'WHERE 1 = 1' es un indicador justo de que NO es el caso, que la base de código está llena de bits' WHERE 1 = 1', lo que me indicaría un problema de arquitectura de la aplicación ¡Y yo diría que no es el único! –

2

Si ha venido aquí buscando WHERE 1, tenga en cuenta que WHERE 1 y WHERE 1=1 son idénticos. WHERE 1 se usa raramente porque algunos sistemas de bases de datos lo rechazan teniendo en cuenta que WHERE 1 no es realmente booleano.

6

He encontrado útil este patrón cuando estoy probando cosas o de doble control en la base de datos, por lo que puedo comentar muy rápidamente otras condiciones:

CREATE VIEW vTest AS 
SELECT FROM Table WHERE 1=1 
AND Table.Field=Value 
AND Table.IsValid=true 

se convierte en:

CREATE VIEW vTest AS 
SELECT FROM Table WHERE 1=1 
--AND Table.Field=Value 
--AND Table.IsValid=true 
0

Esto es útil en un caso en el que tiene que usar una consulta dinámica en la que en la cláusula debe agregar algunas opciones de filtro. Al igual que si incluye las opciones 0 para el estado está inactivo, 1 para activo. Según las opciones, solo hay dos opciones disponibles (0 y 1), pero si desea visualizar Todos los registros, es útil incluir en donde cerca de 1 = 1. Véase a continuación la muestra:

Declare @SearchValue varchar(8) 
Declare @SQLQuery varchar(max) = ' 
Select [FirstName] 
    ,[LastName] 
    ,[MiddleName] 
    ,[BirthDate] 
,Case 
    when [Status] = 0 then ''Inactive'' 
    when [Status] = 1 then ''Active'' 
end as [Status]' 

Declare @SearchOption nvarchar(100) 
If (@SearchValue = 'Active') 
Begin 
    Set @SearchOption = ' Where a.[Status] = 1' 
End 

If (@SearchValue = 'Inactive') 
Begin 
    Set @SearchOption = ' Where a.[Status] = 0' 
End 

If (@SearchValue = 'All') 
Begin 
    Set @SearchOption = ' Where 1=1' 
End 

Set @SQLQuery = @SQLQuery + @SearchOption 

Exec(@SQLQuery); 
Cuestiones relacionadas