0

I have to perform a SELECT query on a PostgreSQL database usign the OVER() window function.

It allows to get either the range of selected rows specified through the OFFSET and LIMIT values, or the number of total rows the query would get without the limit:

SELECT
     DISTINCT *, COUNT(id) OVER() AS results_num
FROM (
    SELECT id, name, surname
    FROM users
    WHERE children > 1
    ORDER BY id
) AS x
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;

To develop a paging method I need to set offset and limit dynamically, so, using PDO, I define the query string setting placeholders for OFFSET and LIMIT variables which are then bound through bindParam():

$sql = "SELECT DISTINCT *, COUNT(id) OVER() AS results_num FROM (
    SELECT id, name, surname
    FROM users
    WHERE children > 1
    ORDER BY id
) AS x
OFFSET :offset ROWS FETCH NEXT :limit ROWS ONLY;"

$query = $dbh->prepare($sql);

$query->bindParam(':offset', $offset, \PDO::PARAM_INT);
$query->bindParam(':limit', $limit, \PDO::PARAM_INT);

$result = $query->execute();

The error caught is:

ERROR:  syntax error at or near "$2"
LINE 7:   ) AS x OFFSET $1 ROWS FETCH NEXT $2 ROWS ONLY;
                                            ^

The SQL error code is 42601 (errorInfo returns SQLSTATE[42601]: Syntax error: 7), but it seems to be very generic, under this code I found a lot of different syntax errors.

It is not due to the named placeholders; infact the same happens by using question mark placeholders:

$sql = "SELECT DISTINCT *, COUNT(id) OVER() AS results_num FROM (
    SELECT id, name, surname
    FROM users
    WHERE children > 1
    ORDER BY id
) AS x
OFFSET ? ROWS FETCH NEXT ? ROWS ONLY;"

$query = $dbh->prepare($sql);
$result = $query->execute([$offset, $limit]);

I know PDO also tries to validate the query structure, so is this type of syntax not allowed to be bound by PDO?

EDIT:

The query itself is well-formed and works; as far as now I use dynamic query string composition to set offset and limit, obviously after having properly validated their value:

$sql = "SELECT DISTINCT *, COUNT(id) OVER() AS results_num FROM (
    SELECT id, name, surname
    FROM users
    WHERE children > 1
    ORDER BY id
) AS x
OFFSET " . $offset . " ROWS FETCH NEXT " . $limit . " ROWS ONLY;"
2
  • Have you tried your statement as prepared statement directly in psql ? Commented May 8, 2018 at 20:59
  • @greg Yes, I tested it in several flavours and it works fine. As far as now I use it in production by setting the dynamic value of offset and limit through the concatenation of $offset and $limit variables in the query string. Commented May 9, 2018 at 8:16

0

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.