Pourquoi quelqu'un utiliserait-il WHERE 1=1 AND <conditions>
dans une clause SQL (Soit le SQL obtenu par des chaînes concaténées, soit la définition de la vue)
J'ai vu quelque part que cela serait utilisé pour se protéger contre l'injection SQL, mais cela semble très étrange.
S'il y a injection, WHERE 1 = 1 AND injected OR 1=1
aura le même résultat que injected OR 1=1
.
Édition ultérieure: qu’en est-il de l’utilisation dans une définition de vue?
Merci pour vos réponses.
Cependant, je ne comprends pas pourquoi quelqu'un utiliserait cette construction pour définir une vue ou l'utiliserait dans une procédure stockée.
Prenons ceci par exemple:
CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value
Si la liste de conditions n'est pas connue au moment de la compilation et est construite à l'exécution, vous n'avez pas à vous demander si vous avez une ou plusieurs conditions. Vous pouvez tous les générer comme:
and <condition>
et les concaténer tous ensemble. Avec le 1=1
au début, le and
initial a quelque chose à associer.
Je n'ai jamais vu cela utilisé pour un type quelconque de protection contre les injections, car vous dites qu'il ne semble pas que cela aiderait beaucoup. Je ai le voyons utilisé comme une commodité d'implémentation. Le moteur de requête SQL finira par ignorer le 1=1
et n'aura donc aucun impact sur les performances.
Il suffit d'ajouter un exemple de code à la réponse 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
Je l'ai vu utilisé lorsque le nombre de conditions peut être variable.
Vous pouvez concaténer des conditions à l'aide d'une chaîne "AND". Ensuite, au lieu de compter le nombre de conditions que vous spécifiez, placez un "WHERE 1 = 1" à la fin de votre instruction SQL stock et ajoutez les conditions concaténées.
En gros, cela vous évite de faire un test de conditions et d'ajouter ensuite une chaîne "WHERE" devant elles.
Cela semble être un moyen paresseux de toujours savoir que votre clause WHERE est déjà définie et vous permet de continuer à ajouter des conditions sans avoir à vérifier s'il s'agit de la première.
Indirectement pertinent: lorsque 1 = 2 est utilisé:
CREATE TABLE New_table_name
as
select *
FROM Old_table_name
WHERE 1 = 2;
cela créera une nouvelle table avec le même schéma que l'ancienne table. (Très pratique si vous voulez charger des données pour les comparaisons)
1 = 1 expression est couramment utilisée dans le code SQL généré. Cette expression peut simplifier la génération de code SQL en réduisant le nombre d'instructions conditionnelles.
où 1 = 0, ceci est fait pour vérifier si la table existe. Je ne sais pas pourquoi 1 = 1 est utilisé.
En fait, j'ai vu ce genre de chose dans les rapports BIRT. La requête transmise au runtime BIRT est de la forme:
select a,b,c from t where a = ?
et le '?' est remplacé au moment de l'exécution par une valeur de paramètre réelle sélectionnée dans une liste déroulante. Les choix dans la liste déroulante sont donnés par:
select distinct a from t
union all
select '*' from sysibm.sysdummy1
afin que vous obteniez toutes les valeurs possibles plus "*
". Si l'utilisateur sélectionne "*
" dans la liste déroulante (ce qui signifie que toutes les valeurs de a doivent être sélectionnées), la requête doit être modifiée (par Javascript) avant d'être exécutée.
Depuis le "?" est un paramètre de position et DOIT y rester pour que d’autres choses fonctionnent, le Javascript modifie la requête pour être:
select a,b,c from t where ((a = ?) or (1==1))
Cela supprime fondamentalement l'effet de la clause where tout en laissant le paramètre de position en place.
J'ai également vu le cas AND utilisé par des codeurs lazy en créant dynamiquement une requête SQL.
Supposons que vous deviez créer dynamiquement une requête commençant par select * from t
et vérifiant:
certaines personnes ajouteraient le premier avec un WHERE et les suivants avec un AND, ainsi:
select * from t where name = 'Bob' and salary > 20000
Les programmeurs paresseux (et ce n'est pas nécessairement un trait mauvais ) ne feraient pas la distinction entre les conditions ajoutées, ils commenceraient par select * from t where 1=1
et seulement ajouter des clauses AND après cela.
select * from t where 1=1 and name = 'Bob' and salary > 20000
J'ai trouvé utile ce modèle lorsque je teste ou vérifie plusieurs choses dans la base de données, donc je peux commenter très rapidement d'autres conditions:
CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1
AND Table.Field=Value
AND Table.IsValid=true
se transforme en:
CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1
--AND Table.Field=Value
--AND Table.IsValid=true
Bien que je sache que 1 = 1 serait utile pour le SQL généré, une technique que j’utilise dans PHP consiste à créer un tableau de clauses, puis à
implode (" AND ", $clauses);
évitant ainsi le problème d'avoir un ET en tête ou en fuite. Évidemment, cela n’est utile que si vous savez que vous allez avoir au moins un article!
Voici un exemple étroitement lié: utilisation d'une instruction SQL MERGE
pour mettre à jour la cible tabled à l'aide de toutes les valeurs de la table source où il n'y a pas d'attribut commun auquel se joindre, par exemple.
MERGE INTO Circles
USING
(
SELECT pi
FROM Constants
) AS SourceTable
ON 1 = 1
WHEN MATCHED THEN
UPDATE
SET circumference = 2 * SourceTable.pi * radius;
Pourquoi quelqu'un utiliserait-il WHERE 1 = 1 AND
<proper conditions>
J'ai v les frameworks homespun font des choses comme ceci ( blush ), car cela permet d'appliquer des méthodes d'analyse syntaxique paresseuses à la WHERE
et AND
mots-clés Sql.
Par exemple (j'utilise C # comme exemple ici), considérons l'analyse conditionnelle des prédicats suivants dans une requête 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";
}
Le "bénéfice" de WHERE 1 = 1
signifie qu'aucun code spécial n'est nécessaire:
AND
est requis. Comme nous avons déjà au moins un prédicat avec le 1 = 1
, cela signifie que AND
est toujours correct.WHERE
doit être supprimée. Mais encore une fois, nous pouvons être paresseux, car nous sommes à nouveau garantis par au moins un prédicat.Ceci est évidemment une mauvaise idée et recommande d'utiliser un cadre d'accès aux données établi ou ORM pour analyser les prédicats facultatifs et conditionnels de cette manière.
Si vous êtes venu chercher WHERE 1
, notez que WHERE 1
et WHERE 1=1
sont identiques. WHERE 1
est rarement utilisé car certains systèmes de base de données le rejettent car WHERE 1
n'est pas vraiment booléen.
Après avoir passé en revue toutes les réponses, j'ai décidé de faire une expérience comme
SELECT
*
FROM MyTable
WHERE 1=1
Puis j'ai vérifié avec d'autres numéros
WHERE 2=2
WHERE 10=10
WHERE 99=99
ect Après avoir effectué toutes les vérifications, la ville d'exécution de la requête est la même. même sans la clause where. Je ne suis pas fan de la syntaxe
Ceci est utile dans le cas où vous devez utiliser une requête dynamique dans laquelle dans la clause where, vous devez ajouter des options de filtrage. Comme si vous incluez les options 0 pour le statut est inactif, 1 pour actif. En fonction des options, il n'y a que deux options disponibles (0 et 1), mais si vous souhaitez afficher Tous les enregistrements, il est pratique d'inclure dans où fermer 1 = 1. Voir ci-dessous échantillon:
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);
L'utilisation d'un prédicat tel que 1=1
est un indice normal parfois utilisé pour forcer le plan d'accès à utiliser ou non une analyse d'index. Cette raison est utilisée lorsque vous utilisez une requête jointe à plusieurs imbrications avec de nombreux prédicats dans la clause where où parfois même l'utilisation de tous les index force le plan d'accès à lire chaque table - une analyse complète de la table. Il ne s'agit que de l'un des nombreux conseils utilisés par les administrateurs de base de données pour amener un système de gestion de base à utiliser un chemin plus efficace. Juste n'en jetez pas un; vous avez besoin d'un dba pour analyser la requête car cela ne fonctionne pas toujours.
Je le fais généralement lorsque je crée du SQL dynamique pour un rapport comportant de nombreuses valeurs de liste déroulante qu'un utilisateur peut sélectionner. Étant donné que l'utilisateur peut ou non sélectionner les valeurs de chaque liste déroulante, nous finissons par avoir du mal à déterminer quelle condition était la première clause where. Nous complétons donc la requête avec un where 1=1
à la fin et ajoutons ensuite toutes les clauses where.
Quelque chose comme
select column1, column2 from my table where 1=1 {name} {age};
Ensuite, nous construirions la clause where comme celle-ci et la passerions en tant que valeur de paramètre
string name_whereClause= ddlName.SelectedIndex > 0 ? "AND name ='"+ ddlName.SelectedValue+ "'" : "";
Comme la sélection de la clause where nous est inconnue au moment de l'exécution, cela nous aide beaucoup à déterminer s'il faut inclure un 'AND' or 'WHERE'.