node-postgres: how to execute “WHERE col IN ()” query?

后端 未结 7 588
梦毁少年i
梦毁少年i 2020-11-28 06:02

I\'m trying to execute a query like this:

SELECT * FROM table WHERE id IN (1,2,3,4)

The problem is that the list of ids I want to filter ag

7条回答
  •  自闭症患者
    2020-11-28 06:23

    The best solution I've found has been to use the ANY function with Postgres' array coercion. This lets you match a column with an arbitrary array of values as if you had written out col IN (v1, v2, v3). This is the approach in pero's answer but here I show that the performance of ANY is the same as IN.

    Query

    Your query should look like:

    SELECT * FROM table WHERE id = ANY($1::int[])
    

    That bit at the end that says $1::int[] can be changed to match the type of your "id" column. For example, if the type of your IDs is uuid, you'd write $1::uuid[] to coerce the argument to an array of UUIDs. See here for the list of Postgres datatypes.

    This is simpler than writing code to construct a query string and is safe against SQL injections.

    Example

    With node-postgres, a complete JavaScript example looks like:

    var pg = require('pg');
    
    var client = new pg.Client('postgres://username:password@localhost/database');
    client.connect(function(err) {
      if (err) {
        throw err;
      }
    
      var ids = [23, 65, 73, 99, 102];
      client.query(
        'SELECT * FROM table WHERE id = ANY($1::int[])',
        [ids],  // array of query arguments
        function(err, result) {
          console.log(result.rows);
        }
      );
    });
    

    Performance

    One of the best ways to understand the performance of a SQL query is to look at how the database processes it. The sample table has about 400 rows and a primary key called "id" of type text.

    EXPLAIN SELECT * FROM tests WHERE id = ANY('{"test-a", "test-b"}');
    EXPLAIN SELECT * FROM tests WHERE id IN ('test-a', 'test-b');
    

    In both cases, Postgres reported the same query plan:

    Bitmap Heap Scan on tests  (cost=8.56..14.03 rows=2 width=79)
      Recheck Cond: (id = ANY ('{test-a,test-b}'::text[]))
      ->  Bitmap Index Scan on tests_pkey  (cost=0.00..8.56 rows=2 width=0)
            Index Cond: (id = ANY ('{test-a,test-b}'::text[]))
    

    You might see a different query plan depending on the size of your table, where there's an index, and your query. But for queries like the ones above, ANY and IN are processed the same way.

提交回复
热议问题