¿Por qué alguien usaría DONDE 1 = 1 Y < condiciones > en una cláusula de SQL?

StackOverflow https://stackoverflow.com/questions/242822

  •  04-07-2019
  •  | 
  •  

Pregunta

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

He visto en algún lugar que esto se usaría para protegerse contra la inyección de SQL, pero parece muy extraño.

Si hay inyección DONDE 1 = 1 Y inyectado O 1 = 1 tendría el mismo resultado que inyectado O 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
¿Fue útil?

Solución

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

and <condition>

y concatenarlos todos juntos. Con el 1 = 1 al comienzo, el inicial y tiene algo con qué asociarse.

Nunca he visto esto usado para ningún tipo de protección contra inyecciones, ya que dices que no parece que ayude mucho. He visto haberlo utilizado como una conveniencia de implementación El motor de consultas SQL terminará ignorando el 1 = 1 por lo que no debería tener ningún impacto en el rendimiento.

Otros consejos

Simplemente agregando 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

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

Puede concatenar condiciones utilizando un " Y " cuerda. Luego, en lugar de contar el número de condiciones que está pasando, coloque un " DONDE 1 = 1 " al final de su declaración de SQL de acciones y lance las condiciones concatenadas.

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

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.

Relevante indirectamente: 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 comparaciones)

1 = 1 expresión 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 sentencias condicionales.

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

En realidad, he visto este tipo de cosas utilizadas en los informes BIRT. La consulta pasada al tiempo de ejecución de BIRT es de la siguiente 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 en 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 obtengas todos los valores posibles más " * " ;. Si el usuario selecciona " * " en el cuadro desplegable (lo que significa que se deben seleccionar todos los valores de a), la consulta debe modificarse (con 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))

Eso básicamente elimina el efecto de la cláusula where y al mismo tiempo deja el parámetro posicional en su lugar.

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

Supongamos que debe crear dinámicamente una consulta que comience con select * from t y verifique:

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

algunas personas agregarían la primera con un DÓNDE y las siguientes con una AND así:

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

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

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

Encontré útil este patrón cuando estoy probando o revisando las cosas en la base de datos, por lo que puedo comentar 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

Aunque 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 o final. Obviamente, esto solo es útil si sabes que vas a tener al menos una cláusula.

Este es un ejemplo estrechamente relacionado: usar una declaración MERGE de 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;
  

¿Por qué alguien usaría DONDE 1 = 1 Y < condiciones adecuadas >

He visto los marcos de uso doméstico hacen cosas como esta ( blush ), ya que permite aplicar prácticas de análisis lento a las palabras clave WHERE y AND Sql.

Por ejemplo (estoy usando C # como ejemplo aquí), considere el análisis condicional de los siguientes predicados en un generador de cadenas de consultas Sql:

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 DONDE 1 = 1 significa que no se necesita ningún código especial:

  • Para AND : si es cero, se deben aplicar uno o ambos predicados (Bars y Baz's), lo que determinaría si se requiere el primer AND . Como ya tenemos al menos un predicado con 1 = 1 , significa que AND siempre está bien.
  • Para ningún predicado: en el caso de que haya predicados CERO, se debe eliminar el DONDE . Pero, de nuevo, podemos ser perezosos, porque de nuevo somos garantía de al menos un predicado.

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

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

Esto es útil en el caso de que tenga que usar la consulta dinámica en la que en donde Cláusula tienes que añadir algunas opciones de filtro. Al igual que si incluyes las opciones 0 para el estado está inactivo, 1 para activo. Basado en las opciones, solo hay dos opciones disponibles (0 y 1), pero si desea mostrar Todos los registros, es conveniente incluir en donde cerca 1 = 1. Vea la siguiente 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);

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 Habiendo realizado todas las comprobaciones, la consulta ejecutar ciudad es la misma. incluso sin la cláusula where. No soy un fan de la sintaxis

Usar un predicado como 1 = 1 es una sugerencia 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 anidada 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. Esta es solo una de las muchas sugerencias utilizadas 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.

Normalmente hago esto cuando estoy creando SQL dinámico para un informe que tiene muchos valores desplegables que un usuario puede seleccionar. Como el usuario puede o no seleccionar los valores de cada menú desplegable, terminamos teniendo dificultades para determinar qué condición fue la primera cláusula donde. Así que rellenamos la consulta con un donde 1 = 1 al 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 de esta manera 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 el tiempo de ejecución, esto nos ayuda mucho a encontrar si incluir un 'AND' o 'WHERE'.

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

Seleccione * del nombre de tabla

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

Donde 1 = 1

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top