1

I have up to 100 items I would like to insert in one batch operation. I am doing it like this:

INSERT INTO MyTable (f1, f2, ..., fk) VALUES
  (v11, v12, ..., v1k),
  (v21, v22, ..., v2k),
  ...
  (vn1, vn2, ..., vnk)

All is fine, but I am building this string by concatenating the values as is, which means my code is vulnerable to SQL injection.

How can I continue using the bulk insert syntax on one hand, yet be protected from the SQL injection?

EDIT 1

I would like to provide a bit more context. The actual SQL that I am going to use (writing the code at this very moment) has the following form:

WITH new_parent AS (
  INSERT into parent (g1, g2, ..., gm) VALUES (v1, v2, ..., vm) RETURNING id
) INSERT INTO MyTable (parent_id, f1, f2, ..., fk) VALUES
  (new_parent.id, v11, v12, ..., v1k),
  (new_parent.id, v21, v22, ..., v2k),
  ...
  (new_parent.id, vn1, vn2, ..., vnk)
2
  • 1
    What's wrong with passing values through escaping function? Without it even COPY command will be vulnerable to \. sequence. Commented Oct 20, 2013 at 11:06
  • Actually, it seems that PostgreSQL can handle up to 2^15 - 1 parameters in a PREPARE statement, so seems like I can just replace the set of values {vij} with the respective named parameters of the form $1, $2, ... Just found out. Commented Oct 20, 2013 at 11:08

2 Answers 2

1

Use a COPY statement - if it is possible. It is little bit faster, require significantly less memory and it is SQL injection bulletproof - because data use a different channel.

Sign up to request clarification or add additional context in comments.

10 Comments

I have added EDIT 1. Is the COPY statement still relevant?
You need to use CTE? Why you don't use temp table with COPY?
Can you give me an example of how my query would look like if using COPY?
@mark with COPY, you need two steps - first, you create temp table, then you fill table with COPY statement. Using a COPY statement depends on your environment.
But how do I populate the temp table? Am I not back to the same problem of inserting records into a table?
|
0

You can build a concatenated string of parameters instead of the actual values and then pass the values with a single array including all of the values in the right order. For example:

    CREATE TYPE paramValues AS {
    "ID" integer,
    "V1" text
    .
    .
    .
    }
    
    CREATE OR REPLACE FUNCTION bulk(data paramValues[])
      RETURNS integer AS
    $BODY$
    DECLARE 
    
    BEGIN
        WITH new_parent AS (
          INSERT into parent (g1, g2, ..., gm) VALUES (v1, v2, ..., vm) RETURNING id
        ) INSERT INTO MyTable (parent_id, f1, f2, ..., fk) VALUES
          ($1, $2, $3, ..., $k),
          ($k+1, $k+2, $k+3, ..., $k+k),
          ...
          ($m, $m+1, $m+2, ..., $m+k);
        return 1;
    
    END$BODY$

    LANGUAGE 'plpgsql' VOLATILE;
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.