DataTables: Tried to bind parameter number 65536. SQL Server supports a maximum of 2100 parameters.

Podemos encontrar este error en el método complex() de la librería ssp.class.php de DataTables. Esta función en casos normales debería funcionar, pero resulta que si utilizas el filtro de repente nos salta este error.

«error»:»An SQL error occurred: SQLSTATE[IMSSP]: Tried to bind parameter number 65536. SQL Server supports a maximum of 2100 parameters.

¿Qué está pasando?

Vamos a empezar con entender que hace la función sql_exec. Esta función ejecuta la sql utilizando variables Bind para realizar la ejecución de los filtros Where. La función que realiza la sustitución es bindValue que se ejecuta siempre que $bindings sea un array()

// Bind parameters
if ( is_array( $bindings ) ) {
    for ( $i=0, $ien=count($bindings) ; $i<$ien ; $i++ ) {
        $binding = $bindings[$i];
        $stmt->bindValue( $binding['key'], 
        $binding['val'], $binding['type'] );
    }
}

En la ejecución del método complex() hay 3 llamadas al sql_exec:

  1. La prímera (main query) que nos devuelve los datos. 
  2. La segunda (Data set length after filtering) que nos devuelve el número total de registros filtrados.
  3. La tercera (Total data set length) que es el total de registros sin filtrar.

La que nos da el error es la tercera llamada. En esta llamada intenta utilizar la variable $bindings que sustituiría los valores del Where.  Pero la variable Where que se utiliza es $whereAllSql que NO TIENE NINGÚN VALOR A SUSTITUIR.

$whereAllSql es un parámetro que le podemos pasar al método complex() para realizar la consulta por defecto. Por ejemplo un listado de alumnos donde siempre queremos que aparezcan los de la sección A. Añadiríamos a ese parámetro el texto correspondiente a la cláusula where:

SSP::complex($_GET, $sql_details, $table, $primaryKey, $columns, null, "(section='A')")

SOLUCIÓN

Por lo que el error lo podemos controlar de forma sencilla. La solución  es enviar el parámetro $bindings vacío a la función sql_exec que nos da el error:

Código Original

// Total data set length
$resTotalLength = self::sql_exec( $db, 
$bindings,
"SELECT COUNT({$primaryKey})
FROM   $table 
$whereAllSql"
);

Código Nuevo

// Total data set length
$resTotalLength = self::sql_exec( $db, 
"",
"SELECT COUNT({$primaryKey})
FROM   $table 
$whereAllSql"
);