why would you use WHERE 1=0 statement in SQL?

后端 未结 12 2082
没有蜡笔的小新
没有蜡笔的小新 2020-12-08 00:48

I saw a query run in a log file on an application. and it contained a query like:

SELECT ID FROM CUST_ATTR49 WHERE 1=0

what is the use of s

相关标签:
12条回答
  • 2020-12-08 01:13

    It can be useful when only table metadata is desired in an application. For example, if you are writing a JDBC application and want to get the column display size of columns in the table.

    Pasting a code snippet here

    String query = "SELECT * from <Table_name> where 1=0";
    PreparedStatement stmt = connection.prepareStatement(query);
    ResultSet rs = stmt.executeQuery();
    ResultSetMetaData rsMD  = rs.getMetaData();
    int columnCount = rsMD.getColumnCount();
    for(int i=0;i<columnCount;i++) {
        System.out.println("Column display size is: " + rsMD.getColumnDisplaySize(i+1));
    }
    

    Here having a query like "select * from table" can cause performance issues if you are dealing with huge data because it will try to fetch all the records from the table. Instead if you provide a query like "select * from table where 1=0" then it will fetch only table metadata and not the records so it will be efficient.

    0 讨论(0)
  • 2020-12-08 01:17

    As an answer - but also as further clarification to what @AndreaColleoni already mentioned:

    manage many OR conditions in dynamic queries (e.g WHERE 1=0 OR <condition>)

    Purpose as an on/off switch

    I am using this as a switch (on/off) statement for portions of my Query.

    If I were to use

    WHERE 1=1
      AND (0=? OR first_name = ?) 
      AND (0=? OR last_name = ?)
    

    Then I can use the first bind variable (?) to turn on or off the first_name search criterium. , and the third bind variable (?) to turn on or off the last_name criterium.

    I have also added a literal 1=1 just for esthetics so the text of the query aligns nicely.

    For just those two criteria, it does not appear that helpful, as one might thing it is just easier to do the same by dynamically building your WHERE condition by either putting only first_name or last_name, or both, or none. So your code will have to dynamically build 4 versions of the same query. Imagine what would happen if you have 10 different criteria to consider, then how many combinations of the same query will you have to manage then?

    Compile Time Optimization

    I also might add that adding in the 0=? as a bind variable switch will not work very well if all your criteria are indexed. The run time optimizer that will select appropriate indexes and execution plans, might just not see the cost benefit of using the index in those slightly more complex predicates. Hence I usally advice, to inject the 0 / 1 explicitly into your query (string concatenating it in in your sql, or doing some search/replace). Doing so will give the compiler the chance to optimize out redundant statements, and give the Runtime Executer a much simpler query to look at.

    (0=1 OR cond = ?) --> (cond = ?)
    (0=0 OR cond = ?) --> Always True (ignore predicate)
    

    In the second statement above the compiler knows that it never has to even consider the second part of the condition (cond = ?), and it will simply remove the entire predicate. If it were a bind variable, the compiler could never have accomplished this.

    Because you are simply, and forcedly, injecting a 0/1, there is zero chance of SQL injections.

    In my SQL's, as one approach, I typically place my sql injection points as ${literal_name}, and I then simply search/replace using a regex any ${...} occurrence with the appropriate literal, before I even let the compiler have a stab at it. This basically leads to a query stored as follows:

    WHERE 1=1
      AND (0=${cond1_enabled} OR cond1 = ?)
      AND (0=${cond2_enabled} OR cond2 = ?)
    

    Looks good, easily understood, the compiler handles it well, and the Runtime Cost Based Optimizer understands it better and will have a higher likelihood of selecting the right index.

    I take special care in what I inject. Prime way for passing variables is and remains bind variables for all the obvious reasons.

    0 讨论(0)
  • 2020-12-08 01:19

    quoted from Greg

    If the list of conditions is not known at compile time and is instead built at run time, you don't have to worry about whether you have one or more than one condition. You can generate them all like:

    and

    and concatenate them all together. With the 1=1 at the start, the initial and has something to associate with.

    I've never seen this used for any kind of injection protection, as you say it doesn't seem like it would help much. I have seen it used as an implementation convenience. The SQL query engine will end up ignoring the 1=1 so it should have no performance impact.

    Why would someone use WHERE 1=1 AND <conditions> in a SQL clause?

    0 讨论(0)
  • 2020-12-08 01:21

    If the user intends to only append records, then the fastest method is open the recordset without returning any existing records.

    0 讨论(0)
  • 2020-12-08 01:25

    Some systems use scripts and can dynamically set selected records to be hidden from a full list; so a false condition needs to be passed to the SQL. For example, three records out of 500 may be marked as Privacy for medical reasons and should not be visible to everyone. A dynamic query will control the 500 records are visible to those in HR, while 497 are visible to managers. A value would be passed to the SQL clause that is conditionally set, i.e. ' WHERE 1=1 ' or ' WHERE 1=0 ', depending who is logged into the system.

    0 讨论(0)
  • 2020-12-08 01:29

    This may be also used to extract the table schema from a table without extracting any data inside that table. As Andrea Colleoni said those will be the other benefits of using this.

    0 讨论(0)
提交回复
热议问题