Skip to main content

PHP KB: No records found when using SQL variables and PDO parameters

Issue

The PDO class for PHP throws an error when running queries against SQL Server and returning multiple results sets.


Cause

Without the benefit of the details around the implementation of SQL Server or the SQLSRV PDO driver, there's no way to know what's causing this issue.  However, the anecdotal evidence points to the the lack of support in the SQLSRV driver for SQL Server's ability to return multiple datasets.

One of the errors that has been encountered reported a question mark (?) placeholder in each place where an SQL variable was in the script that was passed to the PDO::prepare() method call.  This was taken to mean that the method was perceiving each SQL variable as a parameter that it should be looking for in the parameters array passed in the PDOStatement::execute() method.  In other words, it was interpreting SQL parameters (variables) as PDO parameters (?).

Ultimately, this issue is likely to come down to the use of the table data type or temporary tables in the query.


Solution

Use the NO COUNT flag as follows, and at the top of the script.

SET NO COUNT ON


Environment

SQL Server version 2008
PHP version 5.3 Windows
PDO driver version SQLSRV 2.0
Apache version 2.4 Windows


Details

While it’s difficult to know for sure without extensive testing, the situation seems to be when using SQL variables (@VARIABLENAME) in conjunction with PDO parameters (using the ? placeholder).  There is also some expectation that the issue exists when a query returns multiple results sets.

The sample query below is an example of a case that will present this issue.

DECLARE @variableA INT
DECLARE @variableB TABLE (otherTableID INT)

SET @someID = ?

INSERT into @variableB (otherTableID)
SELECT otherTableID FROM sourceTable WHERE sourceTableID = @someID


SELECT *
FROM yetAnotherTable
WHERE yetAnotherTableID = findMeID

This query would run fine when run directly on SQL Server.  However, when used as the query in a PDO call, like the following, it fails.

$Query = $Conn->prepare("/* Query form example. */");
$Query->execute(array("someIDValue"));

$data = $Query->fetchAll(PDO::FETCH_ASSOC);

The following three (3) lines present the solution, which are really just the first two (2) lines with the NOCOUNT flag set as the first line.

DECLARE @variableA INT
DECLARE @variableB TABLE (otherTableID INT)

SET @someID = ?

INSERT into @variableB (otherTableID)
SELECT otherTableID FROM sourceTable WHERE sourceTableID = @someID


SELECT *
FROM yetAnotherTable
WHERE yetAnotherTableID = findMeID

Comments

Popular posts from this blog

Remove control of Chrome being managed by organization on personal devices

Chrome may indicate that it's being managed by a user's organization. This warning is provided by the Chrome Policies feature of the browser. To know if an instance of Chrome is managed by an organization, there will be an entry at the bottom of the browser’s hamburger menu (three dot menu), on the right side of the browser window that reads, "Managed by your organization." This is likely due to an entry in the Chrome Policies listing, which can be found by loading this page in the browser: chrome://policy The policies listed in this section are stored in the computer's file system in one of the following locations as JSON files. /usr/share/chromium/policies/managed /usr/share/chromium/policies/recommended Remove the offending JSON files, and click the Reload policies button. The Managed by your organization entry in the browser menu should be gone. A notice like this on instances of Chrome for work, school, library, or other devices that belong to an organizati...

Allow Windows authentication using SQL Server driver with DBeaver

DBeaver will allow Microsoft Windows single sign on access when connecting to Microsoft SQL Server using the SQL Server driver (rather than jTDS ).  From the driver properties settings, set the integratedSecurity flag to true . Open the Connection configuration panel and choose the Driver properties section. Set the integratedSecurity flag to true . A subtle, but important step is to not provide username and password credentials to the connection.

Connecting to SQL Server with jTDS using Windows Authentication

UPDATE:   At one point the tip in this article to set the USENTLV2 flag to true was accurate, but it appears it is no longer necessary, at least as far as DBeaver 's use of the driver is concerned.  If it solves an authentication problem, then great.  The expectation is that, an update in one of the packages that make this sort of connection possible has resolved the issue that at one time made this flag necessary. Connecting to Microsoft SQL Server using jTDS with a username and password that's managed by the database manager is pretty straightforward.  It may become a little more problematic however, when trying to use Windows authentication when connecting from a Windows machine. Do not supply a username and password. Set the USENTLMV2 property to true. NOTE:   Step 1 assumes a connection being made from a Windows machine.  If the connection is being made from something else, user credentials may actually be necessary. If the connect...