Por que alguém usaria WHERE 1 = 1 AND <conditions> em uma cláusula SQL?

257

Por que alguém usaria WHERE 1=1 AND <conditions>em uma cláusula SQL (o SQL obtido por meio de cadeias concatenadas, ou a definição de exibição)

Eu já vi em algum lugar que isso seria usado para proteger contra a injeção de SQL, mas parece muito estranho.

Se houver injeção WHERE 1 = 1 AND injected OR 1=1teria o mesmo resultado que injected OR 1=1.

Edição posterior: e o uso em uma definição de exibição?


Obrigado por suas respostas.

Ainda assim, não entendo por que alguém usaria essa construção para definir uma exibição ou em um procedimento armazenado.

Veja isso por exemplo:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value
Bogdan Maxim
fonte
3
"por que alguém usaria essa construção para definir uma visão" Provavelmente por hábito. Não oferece vantagem funcional em consultas estáticas.
ADTC

Respostas:

346

Se a lista de condições não for conhecida no tempo de compilação e, em vez disso, criada no tempo de execução, você não precisa se preocupar se possui uma ou mais de uma condição. Você pode gerá-los todos como:

and <condition>

e concatená-los todos juntos. Com o 1=1início, a inicial andtem algo a ser associado.

Eu nunca vi isso usado para qualquer tipo de proteção contra injeção, como você diz, não parece que ajudaria muito. Eu vi isso usado como uma conveniência implementação. O mecanismo de consulta SQL acabará ignorando o, 1=1portanto, não deverá ter impacto no desempenho.

Greg Hewgill
fonte
34
Às vezes, não se trata de ser preguiçoso, mas de ter um código mais limpo.
Eduardo Molteni
39
lidar com ANDs ou COMMAs à direita não é sujo ... nada é mais limpo com 1 = 1 em todo o SQL.
21
DBAs? Para que servem? :)
Eduardo Molteni
38
Os DBAs estão lá para limpar os programadores que pensam que sabem como usar bancos de dados efetivamente.
Adrian Pronk
23
"Preguiçoso" Eu gosto de pensar que é inteligente, não preguiçoso. Você está evitando códigos repetitivos e verificações de condições desnecessárias. Sem poder adicionar where 1=1(Oracle) ou where true(Postgres), terei que verificar para cada condição se é a primeira. Não faz sentido fazê-lo e apenas adiciona mais código padrão.
ADTC 30/07
113

Apenas adicionando um código de exemplo à resposta 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
fonte
6
um pouco hacky, mas parece um uso válido.
1155 Mike
5
Essa deve ser a resposta aceita. A prática é realmente apenas um truque para não ter que determinar quantos condicionais você tem.
aglassman
38

Já o vi usado quando o número de condições pode ser variável.

Você pode concatenar condições usando uma string "AND". Então, em vez de contar o número de condições pelas quais você está passando, coloque um "WHERE 1 = 1" no final de sua instrução SQL de estoque e ative as condições concatenadas.

Basicamente, evita que você faça um teste de condições e adicione uma string "WHERE" antes delas.

Carl
fonte
28

Parece uma maneira lenta de saber sempre que sua cláusula WHERE já está definida e permitir que você continue adicionando condições sem precisar verificar se é a primeira.

John Lemp
fonte
12
"Preguiçoso" Eu gosto de pensar que é inteligente, não preguiçoso. Você está evitando códigos repetitivos e verificações de condições desnecessárias. Sem poder adicionar where 1=1(Oracle) ou where true(Postgres), terei que verificar para cada condição se é a primeira. Não faz sentido fazê-lo e apenas adiciona mais código padrão.
ADTC 30/07
2
O @ADTC Writing code é frequentemente - se não principalmente - o tratamento de diferentes condições. Essa é apenas outra condição que precisa ser tratada, que eu pessoalmente considero preguiçosa poluir o SQL gerado. Se você arquitetar seu código para adicionar 'Onde 1 = 1' em UM lugar, você poderia - com pouco esforço extra - lidar com a diferença entre zero e muitas condições naquele ONE lugar em seu código. Meu palpite é que os defensores de 'Where 1 = 1' espalham-na por toda a base de código, o que me leva à conclusão de que a preguiça gera preguiça.
Jason S
@JasonS Preguiça é o pai da Invenção.
ADTC 22/02
@ADTC Estou com preguiça porque não gosto de atualizar o código em centenas de lugares, então a invenção é colocá-lo em um só lugar. Para mim, WHERE 1=1gera o trabalho extra de manter o mesmo código em vários locais e lê-lo em todo o SQL gerado. Eu sou mais preguiçosa do que você!
Jason S
19

Indiretamente relevante: quando 1 = 2 é usado:

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

isso criará uma nova tabela com o mesmo esquema da tabela antiga. (Muito útil se você deseja carregar alguns dados para comparação)

milso
fonte
3
Esqueceu de acrescentar, enquanto ele vai criar uma nova tabela com os mesmos dados como idade, a nova tabela não terá outros constrangimentos como chave estrangeira da tabela mais velho
milso
16

A expressão 1 = 1 é comumente usada no código sql gerado. Essa expressão pode simplificar o código de geração de sql, reduzindo o número de instruções condicionais.

aku
fonte
11

Na verdade, eu já vi esse tipo de coisa usada nos relatórios do BIRT. A consulta passada para o tempo de execução do BIRT tem o formato:

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

e a '?' é substituído no tempo de execução por um valor real do parâmetro selecionado em uma caixa suspensa. As opções no menu suspenso são dadas por:

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

para que você obtenha todos os valores possíveis mais " *". Se o usuário selecionar " *" na caixa suspensa (o que significa que todos os valores de a devem ser selecionados), a consulta deverá ser modificada (por Javascript) antes de ser executada.

Desde o "?" é um parâmetro posicional e DEVE permanecer lá para que outras coisas funcionem, o Javascript modifica a consulta para:

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

Isso basicamente remove o efeito da cláusula where enquanto ainda mantém o parâmetro posicional no lugar.

Também vi o caso AND usado por codificadores preguiçosos ao criar dinamicamente uma consulta SQL.

Digamos que você precise criar dinamicamente uma consulta que comece com select * from te verifique:

  • o nome é Bob; e
  • o salário é> $ 20.000

algumas pessoas adicionariam o primeiro com um WHERE e os subsequentes com um AND assim:

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

Programadores preguiçosos (e isso não é necessariamente uma característica ruim ) não fazem distinção entre as condições adicionadas, eles começam com select * from t where 1=1e apenas adicionam cláusulas AND depois disso.

select * from t where 1=1 and name = 'Bob' and salary > 20000
paxdiablo
fonte
1
"Preguiçoso" Eu gosto de pensar que é inteligente, não preguiçoso. Você está evitando códigos repetitivos e verificações de condições desnecessárias. Sem poder adicionar where 1=1(Oracle) ou where true(Postgres), terei que verificar para cada condição se é a primeira. Não faz sentido fazê-lo e apenas adiciona mais código padrão.
ADTC
1
@ADTC, eu não quis dizer preguiçoso de uma maneira ruim. De fato, preguiçoso é uma boa característica na programação :-) vou esclarecer.
22414
A preguiça é a raiz de todos os males
Ivanzinho
11

Encontrei esse padrão útil ao testar ou checar duas vezes as coisas no banco de dados, para comentar rapidamente outras condições:

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

torna-se em:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 
--AND Table.Field=Value
--AND Table.IsValid=true
Carlos Toledo
fonte
10

onde 1 = 0, isso é feito para verificar se a tabela existe. Não sei por que 1 = 1 é usado.


fonte
1
Visto isso é usado para retornar um conjunto de resultados vazio do banco de dados para ser usado como titular de novos registros.
Gary Kindel
6

Embora eu possa ver que 1 = 1 seria útil para SQL gerado, uma técnica que eu uso no PHP é criar uma matriz de cláusulas e depois fazer

implode (" AND ", $clauses);

evitando assim o problema de ter um AND inicial ou final. Obviamente, isso só é útil se você souber que terá pelo menos uma cláusula!

sanbikinoraion
fonte
1
. É aí que o 1 = 1 vem em Dá-lhe que "pelo menos uma cláusula" para que você não precisa se preocupar com apenas tapa em um "E abc"
Carl
Eu gosto desta ideia! Veja aqui para obter um exemplo mais completo stackoverflow.com/questions/35326160/…
drooh
5

Aqui está um exemplo estreitamente relacionado: usando uma MERGEinstrução SQL para atualizar o destino apresentado usando todos os valores da tabela de origem em que não há nenhum atributo comum no qual participar, por exemplo

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

Por que alguém usaria WHERE 1 = 1 AND <proper conditions>

vi estruturas caseiras fazerem coisas assim ( blush ), pois isso permite que práticas de análise lenta sejam aplicadas às palavras-chave WHEREe ao ANDSql.

Por exemplo (estou usando C # como exemplo aqui), considere a análise condicional dos seguintes predicados em uma 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";
}

O "benefício" de WHERE 1 = 1significa que nenhum código especial é necessário:

  • Para AND - se zero, um ou ambos os predicados (Bars e Baz's) devem ser aplicados, o que determinaria se o primeiro ANDé necessário. Como já temos pelo menos um predicado com o 1 = 1, isso significa que ANDestá sempre OK.
  • Para nenhum predicado - no caso em que há predicados ZERO, ele WHEREdeve ser descartado. Mas, novamente, podemos ser preguiçosos, porque novamente garantimos pelo menos um predicado.

Obviamente, essa é uma péssima idéia e recomendaria o uso de uma estrutura de acesso a dados estabelecida ou ORM para analisar predicados opcionais e condicionais dessa maneira.

StuartLC
fonte
Ou, se você criar o seu próprio, o construtor de cláusulas where deve estar em um lugar no seu código. Em seguida, você pode manipular zero predicados ou mais de zero predicados em um único local no seu código. Minha suspeita é que a existência de WHERE 1=1é um indicador justo de que NÃO é esse o caso, que a base de código está repleta de bits de strings WHERE 1=1, o que indicaria para mim um problema de arquitetura de aplicativos e eu acho que não é o único!
Jason S
1
Na verdade, não há nada de "ruim" na idéia, muito menos uma falha "óbvia". Nem uma ORM é a maneira correta em todos os casos. Saiba SQL e Álgebra Relacional pessoas ...
Hejazzman
4

Se você veio procurar aqui WHERE 1, observe WHERE 1e WHERE 1=1é idêntico. WHERE 1é usado raramente porque alguns sistemas de banco de dados o rejeitam, considerando que WHERE 1não são realmente booleanos.

Yogesh Umesh Vaity
fonte
2

Isso é útil em um caso em que você deve usar a consulta dinâmica, na qual na cláusula where você deve anexar algumas opções de filtro. Por exemplo, se você incluir as opções 0 para o status está inativo, 1 para ativo. Com base nas opções, existem apenas duas opções disponíveis (0 e 1), mas se você deseja exibir Todos os registros, é útil incluir onde fechar 1 = 1. Veja abaixo a amostra:

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
fonte
2

Depois de revisar todas as respostas, decidi realizar um experimento como

SELECT
*
FROM MyTable

WHERE 1=1

Então eu verifiquei com outros números

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

ect Após todas as verificações, a consulta é executada da mesma forma. mesmo sem a cláusula where. Eu não sou fã da sintaxe

JonWay
fonte
1

Eu faço isso normalmente quando estou criando SQL dinâmico para um relatório que possui muitos valores suspensos que um usuário pode selecionar. Como o usuário pode ou não selecionar os valores de cada lista suspensa, acabamos tendo dificuldade em descobrir qual condição foi a primeira cláusula where. Então, preenchemos a consulta com a where 1=1no final e adicionamos todas as cláusulas where depois disso.

Algo como

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

Em seguida, construiríamos a cláusula where assim e a transmitiríamos como um valor de parâmetro

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

Como a seleção da cláusula where é desconhecida para nós no tempo de execução, isso nos ajuda bastante a descobrir se devemos incluir um 'AND' or 'WHERE'.

Zo Has
fonte
0

Usar um predicado como 1=1é uma dica normal às vezes usada para forçar o plano de acesso a usar ou não uma varredura de índice. A razão pela qual isso é usado é quando você está usando uma consulta combinada com vários aninhados com muitos predicados na cláusula where, onde às vezes até o uso de todos os índices faz com que o plano de acesso leia cada tabela - uma varredura completa da tabela. Esta é apenas uma das muitas dicas usadas pelos DBAs para induzir um dbms a usar um caminho mais eficiente. Apenas não jogue um; você precisa de um dba para analisar a consulta, pois ela nem sempre funciona.

Big Al
fonte
4
Você tem citações que documentam esse comportamento para alguns bancos de dados?
13133 Joe
0

Aqui está um caso de uso ... no entanto, não estou muito preocupado com os detalhes técnicos de por que devo ou não usar 1 = 1. Estou escrevendo uma função, usando pyodbc para recuperar alguns dados do SQL Server. Eu estava procurando uma maneira de forçar um preenchedor após a wherepalavra - chave no meu código. Essa foi uma ótima sugestão:

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

O motivo é que não foi possível implementar a palavra-chave 'where' juntas na variável de cláusula _where. Então, acho que usar qualquer condição fictícia avaliada como verdadeira faria como preenchedor.

SMS
fonte
-1

Eu me deparei com isso com o ADO e o asp clássico, a resposta que recebi foi: desempenho. se você fizer uma reta

Select * from tablename

e passar isso como um comando / texto sql, você obterá um aumento perceptível no desempenho com o

Where 1=1

adicionado, era uma diferença visível. algo a ver com os cabeçalhos de tabela sendo retornados assim que a primeira condição for atendida, ou alguma outra loucura, de qualquer maneira, isso acelerou as coisas.

Jackberry
fonte
3
Se isso é verdade, por que o DBMS não adiciona isso sempre?
Carcamano
5
Você pode produzir evidências?
Peter G.