¿Por qué alguien usaría WHERE 1 = 1 AND <conditions> en una cláusula SQL?

258

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

He visto en alguna parte que esto se usaría para proteger contra la inyección de SQL, pero parece muy extraño.

Si hay inyección WHERE 1 = 1 AND injected OR 1=1tendrí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 sus respuestas.

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.

Toma esto por ejemplo:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value
Bogdan Maxim
fuente
3
"¿Por qué alguien usaría esta construcción para definir una vista?" Probablemente por costumbre. No ofrece ninguna ventaja funcional en consultas estáticas.
ADTC

Respuestas:

346

Si la lista de condiciones no se conoce en el momento de la compilación y, en cambio, se crea en el tiempo de ejecución, no tiene que preocuparse por si tiene una o más de una condición. Puedes generarlos a todos como:

and <condition>

y concatenarlos a todos juntos. Con el 1=1al principio, la inicial andtiene algo con qué asociarse.

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

Greg Hewgill
fuente
34
A veces no se trata de ser flojo, sino de tener un código más limpio.
Eduardo Molteni
39
lidiar con los AND o COMMA finales no está sucio ... nada está más limpio al tener 1 = 1 en todo su SQL.
21
DBA? ¿Para qué son? :)
Eduardo Molteni
38
Los DBA están allí para limpiar después de que los programadores creen que saben cómo usar las bases de datos de manera efectiva.
Adrian Pronk
23
"Perezoso" Me gusta pensar que es inteligente, no perezoso. Estás evitando códigos repetitivos y 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
113

Simplemente agregue un código de ejemplo a 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
Eduardo Molteni
fuente
66
poco hacky, pero parece un uso válido.
Mike
55
Esta debería ser la respuesta aceptada. La práctica es realmente solo piratear para no tener que determinar cuántos condicionales tiene.
aglassman el
38

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

Puede concatenar condiciones utilizando una cadena "AND". Luego, en lugar de contar el número de condiciones que está pasando, coloca un "WHERE 1 = 1" al final de su declaración SQL de valores y aplica las condiciones concatenadas.

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

Carl
fuente
28

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

John Lemp
fuente
12
"Perezoso" Me gusta pensar que es inteligente, no perezoso. Estás evitando códigos repetitivos y 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
2
@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 manejarse, y personalmente creo que es flojo contaminar el SQL generado. Si diseña 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 UNO lugar en su código. Sin embargo, supongo que los defensores de 'Where 1 = 1' lo espolvorean en toda su base de código, lo que me lleva a la conclusión de que la pereza engendra pereza.
Jason S
@JasonS Laziness es el padre de la invención.
ADTC
@ADTC Soy perezoso porque no me gusta actualizar el código en cientos de lugares, por lo que la invención se coloca en un solo lugar. Para mí, WHERE 1=1genera el trabajo adicional de mantener el mismo código en varios lugares y leerlo en todo el SQL generado. ¡Soy más vago que tú, creo!
Jason S
19

Indirectamente relevante: cuando se usa 1 = 2:

CREATE TABLE New_table_name 
as 
select * 
FROM Old_table_name 
WHERE 1 = 2;

esto creará una nueva tabla con el mismo esquema que la tabla anterior. (Muy útil si desea cargar algunos datos para comparar)

milso
fuente
3
Se olvidó de agregar, mientras que 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
16

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

aku
fuente
11

En realidad, he visto este tipo de cosas usadas en los informes de BIRT. La consulta pasada al tiempo de ejecución BIRT tiene la forma:

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

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

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

para que obtenga todos los valores posibles más " *". Si el usuario selecciona " *" en el cuadro desplegable (lo que significa que todos los valores de a deben seleccionarse), la consulta debe modificarse (mediante Javascript) antes de ejecutarse.

Desde el "?" es un parámetro posicional y DEBE permanecer allí para que otras cosas funcionen, el Javascript modifica la consulta para que sea:

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

Básicamente, eso elimina el efecto de la cláusula where y deja el parámetro posicional en su lugar.

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

Supongamos que tiene que crear dinámicamente una consulta que comienza con select * from ty comprueba:

  • el nombre es Bob; y
  • el salario es> $ 20,000

algunas personas agregarían el primero con un DÓNDE y los siguientes con un Y así:

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

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

select * from t where 1=1 and name = 'Bob' and salary > 20000
paxdiablo
fuente
1
"Perezoso" Me gusta pensar que es inteligente, no perezoso. Estás evitando códigos repetitivos y 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 me refería a vago de mala manera. De hecho, perezoso es un buen rasgo en la programación :-) aclararé.
paxdiablo
La pereza es la raíz de todo mal
Ivanzinho
11

Encontré útil este patrón cuando estoy probando o haciendo doble comprobación 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
Carlos Toledo
fuente
10

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


fuente
1
Visto esto, se utiliza para devolver un conjunto de resultados vacío de la base de datos para ser utilizado como titular de nuevos registros.
Gary Kindel
6

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

implode (" AND ", $clauses);

evitando así el problema de tener un AND inicial o final. ¡Obviamente, esto solo es útil si sabe que tendrá al menos una cláusula!

sanbikinoraion
fuente
1
Ahí es donde entra en juego el 1 = 1. Te da esa "al menos una cláusula" para que no tengas que preocuparte por solo darle una bofetada a "AND abc"
Carl
¡Me gusta esta idea! Vea aquí un ejemplo más completo stackoverflow.com/questions/35326160/…
drooh
5

Aquí hay un ejemplo estrechamente relacionado: el uso de una MERGEinstrucción SQL para actualizar la tabla de destino utilizando todos los valores de la tabla de origen donde no hay un atributo común en el que unirse, por ejemplo

MERGE INTO Circles
   USING 
      (
        SELECT pi
         FROM Constants
      ) AS SourceTable
   ON 1 = 1
WHEN MATCHED THEN 
  UPDATE
     SET circumference = 2 * SourceTable.pi * radius;
un día cuando
fuente
5

¿Por qué alguien usaría DONDE 1 = 1 Y <proper conditions>

He visto los marcos de andar por casa hacen cosas como esta ( rubor ), ya que esto permite que las prácticas de análisis perezosos que se aplicarán tanto a los WHEREy ANDpalabras clave de SQL.

Por ejemplo (estoy usando C # como ejemplo aquí), considere 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 = 1significa que no se necesita un código especial:

  • Para AND : si se debe aplicar cero, uno o ambos predicados (Barras y Baz), lo que determinaría si ANDse requiere el primero . Como ya tenemos al menos un predicado con el 1 = 1, significa ANDque siempre está bien.
  • Para ningún predicado en absoluto: en el caso de que haya CERO predicados, se WHEREdebe descartar. Pero, de nuevo, podemos ser perezosos, porque de nuevo estamos garantizados de al menos un predicado.

Obviamente, esta es una mala idea y recomendaría usar un marco de acceso a datos establecido u ORM para analizar predicados opcionales y condicionales de esta manera.

StuartLC
fuente
O si usa el suyo, el generador de cláusulas where debería estar en un lugar en su código. Entonces puede manejar cero predicados o más de cero predicados en una sola ubicación en su código. Mi sospecha es que la existencia de WHERE 1=1es un indicador justo de que ese NO es el caso, que la base del código está llena de trozos de cadenas WHERE 1=1, lo que me indicaría un problema de arquitectura de la aplicación, ¡y supongo que no es el único!
Jason S
1
En realidad, no hay nada "malo" en la idea, mucho menos una falla "obvia". Tampoco es un ORM la forma correcta en todos los casos. Aprenda SQL y personas de álgebra relacional ...
Hejazzman
4

Si usted vino aquí en busca de WHERE 1, nota que WHERE 1y WHERE 1=1son idénticos. WHERE 1se usa raramente porque algunos sistemas de bases de datos lo rechazan considerando que WHERE 1realmente no es booleano.

Yogesh Umesh Vaity
fuente
2

Esto es útil en un caso en el que tiene que usar una consulta dinámica en la que en la cláusula where debe agregar algunas opciones de filtro. Como si incluye 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 mostrar Todos los registros, es útil incluir en donde cierre 1 = 1. Vea 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);
Eliseo Jr
fuente
2

Después de revisar todas las respuestas, decidí realizar un experimento como

SELECT
*
FROM MyTable

WHERE 1=1

Luego verifiqué con otros números

WHERE 2=2
WHERE 10=10
WHERE 99=99

ect Después de haber realizado todas las comprobaciones, la consulta ejecutar ciudad es la misma. incluso sin la cláusula where. No soy fanático de la sintaxis

JonWay
fuente
1

Por lo general, hago esto 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 seleccionar los valores de cada menú desplegable, terminamos teniendo dificultades para descubrir qué condición era la primera cláusula where. Así que rellenamos la consulta con un where 1=1al final y agregamos todas las cláusulas where después de eso.

Algo como

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

Luego construiríamos la cláusula where como esta y la pasaríamos como un valor de parámetro

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

Como la selección de la cláusula where es desconocida para nosotros en tiempo de ejecución, esto nos ayuda mucho a encontrar si se incluye un 'AND' or 'WHERE'.

Zo Has
fuente
0

El uso de un predicado como 1=1es una pista normal que a veces se usa para forzar al plan de acceso a usar o no un escaneo de índice. La razón por la que se usa esto es cuando está utilizando una consulta unida con múltiples anidamientos 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, un análisis completo de la tabla. Este es solo uno de los muchos consejos utilizados por los DBA para engañar a un dbms para que use una ruta más eficiente. Simplemente no tires uno; necesita un dba para analizar la consulta, ya que no siempre funciona.

Big Al
fuente
44
¿Tiene alguna cita que documente este comportamiento para algunas bases de datos?
Joe
0

Aquí hay un caso de uso ... sin embargo, no estoy demasiado preocupado por los tecnicismos de por qué debería usar o no 1 = 1. Estoy escribiendo una función, usando pyodbc para recuperar algunos datos de SQL Server. Estaba buscando una manera de forzar un relleno después de la wherepalabra clave en mi código. Esta fue una gran sugerencia de hecho:

if _where == '': _where = '1=1'
...
...
...
cur.execute(f'select {predicate} from {table_name} where {_where}')

La razón es porque no pude implementar la palabra clave 'where' juntos dentro de la variable de cláusula _where. Entonces, creo que usar cualquier condición ficticia que se evalúe como verdadera funcionaría como relleno.

SMS
fuente
-1

La primera vez que encontré esto fue con ADO y asp clásico, la respuesta que obtuve fue: rendimiento. si haces una escalera

Select * from tablename

y pásalo como un comando / texto sql obtendrás un notable aumento de rendimiento con el

Where 1=1

agregado, era una diferencia visible. algo relacionado con los encabezados de las tablas que se devuelven tan pronto como se cumple la primera condición, o alguna otra locura, de todos modos, aceleró las cosas.

Jackberry
fuente
3
Si eso es cierto, ¿por qué el DBMS no siempre agrega eso?
Carcamano
55
¿Puedes producir evidencia?
Peter G.