¿Por qué alguien usaría DONDE 1 = 1 Y < condiciones > en una cláusula de SQL?
-
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
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 con1 = 1
, significa queAND
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.