20

For my SQL queries, I usually do the following for SELECT statements:

SELECT ...
FROM table t
WHERE 1=1
  AND t.[column1] = @param1
  AND t.[column2] = @param2

This will make it easy if I need to add / remove / comment any WHERE clauses, since I don't have to care about the first line.

Is there any performance hit when using this pattern?

Additional Info:

Example for sheepsimulator and all other who didn't get the usage.

Suppose the above query, I need to change @param1 to be not included into the query:

With 1=1:

...
WHERE 1=1 <-- no change
  --AND t.[column1] = @param1 <-- changed
  AND t.[column2] = @param2 <-- no change
...

Without 1=1:

...
WHERE <-- no change
  --t.[column1] = @param1 <-- changed
  {AND removed} t.[column2] = @param2 <-- changed
...
Adrian Godong
  • 8,802
  • 8
  • 40
  • 62
  • 1
    I'm sorry if this sounds kinda daff, but I'm really not sure how addding 1=1 to your WHERE clause gains you the above benefits; could you elaborate on this for those of us who would like to learn this possible best practice? – J. Polfer Jun 26 '09 at 14:44
  • @sheepsimulator: it's super easy to comment and uncomment any condition merely by prepending it with double dash (--) – Quassnoi Jun 26 '09 at 14:48
  • 2
    Hey Adrian, I always do the same thing, it's so comfortable to build dynamic queries... – tekBlues Jun 26 '09 at 14:52

8 Answers8

22

No, SQL Server is smart enough to omit this condition from the execution plan since it's always TRUE.

Same is true for Oracle, MySQL and PostgreSQL.

Steve Horn
  • 8,818
  • 11
  • 45
  • 60
Quassnoi
  • 413,100
  • 91
  • 616
  • 614
  • 1
    Do you have a source for this? I believe you, I'd just link something to reference. – Danny Beckett Jun 27 '13 at 01:28
  • 1
    @Danny: for MySQL, yes: http://dev.mysql.com/doc/refman/5.6/en/where-optimizations.html *Constant condition removal (needed because of constant folding)*, for others no but constant folding is core feature of any optimizer – Quassnoi Jun 29 '13 at 07:55
16

It is likely that if you use the profiler and look, you will end up seeing that the optimizer will end up ignoring that more often than not, so in the grand scheme of things, there probably won't be much in the way of performance gain or losses.

TheTXI
  • 37,429
  • 10
  • 86
  • 110
  • 1
    I agree. @Adrian- if write the two queries together and turn on the execution plan, you will probably see that both queries are 50% each. – RichardOD Jun 26 '09 at 14:45
4

This has no performance impact, but there the SQL text looks like it has been mangled by a SQL injection attack. The '1=1' trick appears in many sql injection based attacks. You just run the risk that some customer of yours someday deploys a 'black box' that monitors SQL traffic and you'll find your app flagged as 'hacked'. Also source code analyzers may flag this. Its a long long shot, of course, but something worth putting into the balance.

Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
  • A cool trick, but this is a valid point. I may start using this during development, but I'd want to take it out before releasing it to Production. – Philip Kelley Jun 26 '09 at 15:42
  • 5
    Not a valid point I'd say. SQL injection uses "OR 1=1" not "1=1 AND". Those two are distinctly different, if an app can't differentiate them, are you sure the other results are reliable? – Adrian Godong Jun 29 '09 at 21:51
  • If your doing this on a web app or SAAS system the customer likely isn't capable of installing their own monitoring tools. And of course if you install your own you know these queries are safe. – danielson317 Sep 30 '16 at 18:36
4

One potentially mildly negative impact of this is that the AND 1=1 will stop SQL Server's simple parameterisation facility from kicking in.

Demo script

DBCC FREEPROCCACHE;  /*<-- Don't run on production box!*/

CREATE TABLE [E7ED0174-9820-4B29-BCDF-C999CA319131]
(
X INT, 
Y INT,
PRIMARY KEY (X,Y)
);

GO
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  X = 1
       AND Y = 2;
GO
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  X = 2
       AND Y = 3;
GO   
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  1 = 1
       AND X = 1
       AND Y = 2 
GO   
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  1 = 1
       AND X = 2
       AND Y = 3    

SELECT usecounts,
       execution_count,
       size_in_bytes,
       cacheobjtype,
       objtype,
       text,
       creation_time,
       last_execution_time,
       execution_count
FROM   sys.dm_exec_cached_plans a
       INNER JOIN sys.dm_exec_query_stats b
         ON a.plan_handle = b.plan_handle
       CROSS apply sys.dm_exec_sql_text(b.sql_handle) AS sql_text
WHERE  text LIKE '%\[E7ED0174-9820-4B29-BCDF-C999CA319131\]%' ESCAPE '\'
       AND text NOT LIKE '%this_query%'
ORDER BY last_execution_time DESC       

GO

DROP TABLE [E7ED0174-9820-4B29-BCDF-C999CA319131]   

Shows that both the queries without the 1=1 were satisfied by a single parameterised version of the cached plan whereas the queries with the 1=1 compiled and stored a separate plan for the different constant values.

enter image description here

Ideally you shouldn't be relying on this anyway though and should be explicitly parameterising queries to ensure that the desired elements are parameterised and the parameters have the correct datatypes.

Martin Smith
  • 438,706
  • 87
  • 741
  • 845
2

There is no difference, as they evaluated constants and are optimized out. I use both 1=1 and 0=1 in both hand- and code-generated AND and OR lists and it has no effect.

Cade Roux
  • 88,164
  • 40
  • 182
  • 265
2

Since the condition is always true, SQL Server will ignore it. You can check by running two queries, one with the condition and one without, and comparing the two actual execution plans.

An alternative to achieve your ease of commenting requirement is to restructure your query:

SELECT ...
FROM table t
WHERE 
    t.[column1] = @param1 AND
    t.[column2] = @param2 AND
    t.[column3] = @param3

You can then add/remove/comment out lines in the where conditions and it will still be valid SQL.

adrianbanks
  • 81,306
  • 22
  • 176
  • 206
1

No performance hit. Even if your WHERE clause is loaded with a large number of comparisons, this is tiny.

Best case scenario is that it's a bit-for-bit comparison. Worse case is that the digits are evaluated as integers.

p.campbell
  • 98,673
  • 67
  • 256
  • 322
1

For queries of any reasonable complexity there will be no difference. You can look at some execution plans and also compare real execution costs, and see for yourself.

A-K
  • 16,804
  • 8
  • 54
  • 74