I'm moving PHP code from mysql to ms sql server.
This will execute my query:
$r = $db_conn->prepare($sql);
$r->execute();
Before I start processing, I need to count how many rows were returned.
old code:
$r->num_rows;
new code:
$rows = $r->fetchAll(PDO::FETCH_ASSOC);
$rcount = count($rows);
All good, but when I try to access values from 1st row I'm getting nothing...
try {
$row = $r->fetch(PDO::FETCH_ASSOC);
} catch (Exception $ex) {
return 0;
}
I need to repoint to 1st row in my recordset after doing the count, how can I do this without having to requery the database again?
I'm new to PHP, sorry for dumb and probably obvious question.
Thanks in advance.
There isn't a way in PDO to reset the pointer. You could execute the query again, but given that you've already fetched all the data with your call to fetchAll, that is wasteful. Instead, to access the data, simply loop over the $rows array e.g.
foreach ($rows as $row) {
// do something
}
Note that if you expect an exception on fetch, it is likely you might get one on fetchAll too, so you should wrap the call to fetchAll in a try/catch block:
try {
$rows = $r->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $ex) {
return 0;
}
One possible approach, if you use PHP Driver for SQL Server, is to use PDOStatement::rowCount and client-side cursor. With this type of cursor row count is available after a query is executed, but this type of cursor should be used for small (medium) result sets.
<?php
# Connection
$server = 'server\instance,port';
$database = 'master';
$uid = 'uid';
$pwd = 'pwd';
# PDO Connection
try {
# SQL authentication
$conn = new PDO("sqlsrv:server=$server;Database=$database", $uid, $pwd);
# Windows authentication
#$conn = new PDO("sqlsrv:server=$server;Database=$database");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage());
}
# Client-side cursor
try {
$options = array(
PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL,
PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED
);
$stmt = $conn->prepare("SELECT * FROM master.sys.server_principals", $options);
$stmt->execute();
echo 'Row count: '.$stmt->rowCount().'<br>';
while ($row = $stmt->fetch(PDO::FETCH_ASSOC) ){
echo 'Login name: '.$row['name'].'<br>';
}
} catch( PDOException $e ) {
die( "Error executing query".$e->getMessage() );
}
# End
$stmt = null;
$conn = null;
?>
Related
Good day!
I am working on building a dummy application form that inserts data to a mySQL database. When running the functions, I successfully insert the data into the database. However, when the functions worked successfully, I am getting an error SQLSTATE[HY000]: General error
I thought it was occurring within my database access function, but it seems to be connecting alright. Here is my db access function:
function connectToDB($params)
{
try
{
$conn = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare($params['sql']);
$stmt->execute($params['bindParam']);
$results = array();
$results['rowCount'] = $stmt->rowCount();
if($results['rowCount'] == 1)
{
$results = $stmt->fetch(PDO::FETCH_ASSOC);
return $results;
} elseif($results['rowCount'] < 2) {
$results = $stmt->fetch(PDO::FETCH_ASSOC);
return $results;
} elseif($results['rowCount'] > 2) {
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $results;
} elseif($results['rowCount'] == 2) {
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $results;
}
} catch (PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
return $params;
}
Is there something I am missing in my code or is there something that shouldn't be in my db access code? I hope to learn from this to apply it in the future while I'm still trying to learn/improve on my PHP along the way. I hope I did my best to explain my issue and I appreciate your time reading!
Thank you
You do not use fetchAll().
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
with insert queries. Removing this statement it should fix your problem. Remember every fetch and fetchAll from your code.
I'am trying to perform simple SELECT query from PHP PDO to MSSQL database. While query contains cyrillic symbols in WHERE condition, result is empty (if not contains, result return successfully). What can I do to correct query?
putenv('ODBCSYSINI=/etc/');
putenv('ODBCINI=/etc/odbc.ini');
$configODBC = config('database.odbc');
try {
$this->pdo = new PDO('odbc:'. $configODBC['default']['source'], $configODBC['default']['username'], $configODBC['default']['password']);
} catch (PDOException $e) {}
...
$statement = $this->pdo->prepare("SELECT * FROM [DB].[dbo].table WHERE policy_num LIKE '%cyrillic_symbols%'");
$result = $statement->execute();
if ($result) {
while ($out = $statement->fetch()) {
var_dump($out[0]);
}
}
PS. MSSQL version 2012. Data in UTF-8 encoding.
I'll post this as an answer, because it's too long for comment. UTF-8 all the way through, suggested by #RiggsFolly has all the answers. In your case, you need to convert values from CP-1251 from/to UTF-8 . I've made this simple test case, see if this will help you:
T-SQL:
CREATE TABLE CyrillicTable (
[CyrillicText] varchar(200) COLLATE Cyrillic_General_CI_AS
)
INSERT INTO CyrillicTable
(CyrillicText)
VALUES
('Понедельник'),
('Вторник')
PHP (file is UTF-8 encoded, using Notepad++):
<?php
# Connection info
$hostname = 'server\instance,port';
$dbname = 'database';
$username = 'uid';
$pw = 'pwd';
# Connection
try {
$dbh = new PDO("odbc:Driver={SQL Server Native Client 11.0};Server=$hostname;Database=$dbname", $username, $pw);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch( PDOException $e ) {
die( "Error connecting to SQL Server. ".$e->getMessage());
}
# Query
try {
echo "Query"."<br>";
$sql = "SELECT * FROM dbo.[CyrillicTable] WHERE CyrillicText LIKE '%".iconv('UTF-8', 'CP1251', 'онед')."%'";
$stmt = $dbh->query($sql);
while ($row = $stmt->fetch( PDO::FETCH_ASSOC )) {
foreach($row as $name => $value) {
echo $name.": ".iconv('CP1251', 'UTF-8', $value)."<br>";
}
}
echo "<br>";
} catch( PDOException $e ) {
die( "Error executing query: ".$e->getMessage());
}
$stmt = null;
# Query
try {
echo "Prepared query"."<br>";
$sql = "SELECT * FROM dbo.[CyrillicTable] WHERE CyrillicText LIKE ?";
$stmt = $dbh->prepare($sql);
$text = 'орни';
$text = "%$text%";
$text = iconv('UTF-8', 'CP1251', $text);
$stmt->bindParam(1, $text, PDO::PARAM_STR);
$stmt->execute();
while ($row = $stmt->fetch( PDO::FETCH_ASSOC )) {
foreach($row as $name => $value) {
echo $name.": ".iconv('CP1251', 'UTF-8', $value)."<br>";
}
}
echo "<br>";
} catch( PDOException $e ) {
die( "Error executing stored procedure: ".$e->getMessage());
}
$stmt = null;
# End
$dbh = null;
?>
Notes:
Consider using parameterized query.
I have a reasonably complicated stored procedure in MSSQL 2008 R2 that, in the end, results in a small table being returned. The PHP will be called from javascript and I want it to return the array as JSON to be used in table in the javascript.
I am using PHP to access it and, using the profiler, can see that I am calling the SP and passing the correct parameters to it.
My PHP looks like this:
try {
$dbh = new PDO("sqlsrv:Server=(local);Database=cddDispo");
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo json_encode("Error connecting to the server.");
die ();
}
$lot = $_POST["lot-input"];
$layerAdder = $_POST["layer-input"];
$adder = substr($layerAdder,-3,3);
$adder = str_replace('=','',$adder);
$layer = substr($layerAdder,0,strpos($layerAdder,' '));
$sth = $dbh->prepare('EXEC dbo.pullDispo ?,?,?');
$sth->bindParam(1,$lot,PDO::PARAM_STR);
$sth->bindParam(2,$layer,PDO::PARAM_STR);
$sth->bindParam(3,$adder,PDO::PARAM_STR);
$array = array();
try {
$sth->execute();
while($row = $sth->fetch(PDO::FETCH_ASSOC)) {
//I want to build my output array here
}
}catch (PDOException $e) {
echo "Error getting data, please try again.";
die();
}
header('Content-type: application/json');
echo json_encode($array);
This is the first time that I have tried to return table results from a stored procedure and even with several PHP Manual/ Google searches I have not figured out how to capture the table back in the PHP. I have a less elegant workaround (write the SP table to a static table and call that table later in the PHP) but would rather figure out if I can do in a more elegant manner. Any advice is much appreciated.
I thought it might be useful if I posted my final code:
function array_push_assoc($array,$key,$value) {
$array[$key] = $value;
return $array;
}
header('Content-type: application/json');
try {
$dbh = new PDO('sqlsrv:Server=(local);Database=cddDispo');
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo json_encode('Error connecting to the server.');
die ();
}
$lot = $_POST['lot'];
$layer = $_POST['layer'];
$adder = $_POST['adder'];
$sth = $dbh->prepare('EXEC dbo.pullDispo ?,?,?');
$sth->bindParam(1,$lot,PDO::PARAM_STR);
$sth->bindParam(2,$layer,PDO::PARAM_STR);
$sth->bindParam(3,$adder,PDO::PARAM_STR);
$results = array();
$combinedArray = array();
$array = array();
$count = 0;
try {
$sth->execute();
do {
$results[] = $sth->fetchAll(PDO::FETCH_ASSOC);
}while ($sth->nextRowset());
foreach($results as $row) {
if($count == 0) {
$headerArray =
[
'Lot' =>$row['Lot'],
'Layer' =>$row['Measured Layer'],
'Product' =>$row['MES Product'],
'Adder' =>$row['Adder Chart']
];
$combinedArray = array_push_assoc($combinedArray,'header',$headerArray);
}
$count++;
//This is for formatting of final table
if($row['UDL'] == 0) {
$udl = 'NA';
} else {
$udl = round($row['UDL'],4);
}
$infoArray =
[
'Wafer' =>$row['Wafer'],
'Type' =>$row['Type'],
'Count' =>$row['Count'],
'CDD' =>round($row['CDD'],3),
'UCL' =>round($row['UCL'],4)
];
array_push($array,$infoArray);
}
$combinedArray = array_push_assoc($combinedArray,'detail',$array);
}catch (PDOException $e) {
echo json_encode('Error running stored procedure.');
die();
}
echo json_encode($combinedArray);
Could it be that your stored procedure is returning multiple result sets? This includes output like warning messages or number of rows affected. Try adding SET ANSI_WARNINGS OFF or SET NOCOUNT ON at the top of your stored procedures after the AS. You can also try advancing to the next result set in PHP before trying to get the results by calling $stg->nextRowset() before $sth->fetchAll().
Use fetchAll() to get your resultset, then encode that array as your json response:
$array = array();
try {
if($sth->execute()){
$array = $sth->fetchAll(PDO::FETCH_ASSOC);
}else{
$array = array('error'=>'failed to execute()')
}
}catch (PDOException $e) {
echo "Error getting data, please try again.";
die();
}
header('Content-type: application/json');
echo json_encode($array);
When you are calling a stored procedure with multiple result sets, you probably do not want to add SET NOCOUNT ON into every procedure you have; you always can add
$dbh->setAttribute(constant('PDO::SQLSRV_ATTR_DIRECT_QUERY'), true);
$dbh->query("SET NOCOUNT ON");
before of
$dbh->prepare($query);
and it will work.
I'm on my way learning about PDO from phpro.org, and a little bit confuse.
<?php
try {
$dbh = new PDO("odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=C:\pdo-tutorial.mdb;Uid=Admin");
}
catch (PDOException $e)
{
echo $e->getMessage();
}
?>
What is Uid? and what value should I enter?
And, about the query
<?php
try {
$dbh = new PDO("odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=C:\pdo-tutorial.mdb;Uid=Admin");
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';
/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM animals";
/*** fetch into an PDOStatement object ***/
$stmt = $dbh->query($sql);
/*** echo number of columns ***/
$result = $stmt->fetch(PDO::FETCH_ASSOC);
/*** loop over the object directly ***/
foreach($result as $key=>$val)
{
echo $key.' - '.$val.'<br />';
}
/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
I'm using odbc, but why the foreach functions just echo the first row, not looping echoing all my value in the database? here are the result.
Connected to database
ID - 1
animal_type - kookaburra
animal_name - bruce
can you tell me why?
For your second question:
You need to use fetchAll() instead of fetch(), which only gives you one row at a time.
In your code, try:
$result = $stmt->fetchAll(PDO::FETCH_ASSOC); (though that will change what your foreach loop looks like).
Alternatively, you can use a while loop to fetch each row as you need it:
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
//Do something with $row
}
Uid is Username with which you want to connect to database, if your mdb file is not protected you may omit this parameter.
To fetch all results you have to use fetchAll (http://php.net/manual/en/pdostatement.fetchall.php).
It appears I can connect to my database using PDO, but can't execute any queries with it. Example:
private function connect() {
try {
$link = new PDO("mysql:host=$this->sHost;dbname=$this->sName", $this->sUser, $this->sPass);
}
catch (PDOException $e) {
die ($e);
}
print_r($link);
$result = $link->query("select * from mt3_users");
var_dump($result);
$row = $result->fetch($result);
die("Your id is: ".$row["id"]);
//$link = mysql_connect($this->sHost, $this->sUser, $this->sPass);
if (!$link) {
echo "Failed to connect to $this->sHost!";
return false;
}
return $link;
}
This returns the following:
PDO Object ( ) bool(false)
Fatal error: Call to a member function fetch() on a non-object in Database.php on line 32
So basically, $link is coming back as a PDO object (I changed my username and password to see if an exception was caught; it was) and PDOConnection::Query is returning null for some reason. This is my first time dealing with PDOs -- am I doing something funny?
Most likely the query fails, are you sure of the name of the table mt3_users and that you have selected the right database? That error message shows that $result is not an object and that's due to an error in the query.
Also:
$row = $result->fetch($result);
should be
$row = $result->fetch();
unless you want to specify options to fetch(), but you don't pass the object as argument.
Array ( [0] => 00000 [1] => 1046 [2] => No database selected ) Array ( )
Nevermind, I guess. It turns out that while migrating from using regular MySQL functions, I wasn't setting $this->sName ($this->sName was null. I'm half surprised it didn't throw an exception. Only half, though)
Fixed.
But thank you guys for the answers :)
can you give this a try
private function connect() {
try {
$link = new PDO("mysql:host=$this->sHost;dbname=$this->sName", $this->sUser, $this->sPass);
return $link ;
}
catch (PDOException $e) {
die ($e);
}
}
$pdolink = $this->connect();
$rows = $pdolink->query("select * from mt3_users");
foreach($rows as $row ){
echo("Your id is: ".$row["id"]);
}
and if you need to stick with fetchAll function
private function connect() {
try {
$link = new PDO("mysql:host=$this->sHost;dbname=$this->sName", $this->sUser, $this->sPass);
return $link ;
}
catch (PDOException $e) {
die ($e);
}
}
$pdolink = $this->connect();
$q = $pdolink->prepare("select * from mt3_users");
$q->exectue();
$rows = $q->fetchAll();
var_dump($rows);
foreach($rows as $row ){
echo("Your id is: ".$row["id"]);
}
In order to get the error in your query:
$result = $link->query(...);
if($result===FALSE){
print_r( $link->errorInfo);
exit();
}
// the correct way to fetch one row
$link->fetch(PDO::FETCH_ASSOC); // or whatever way you want to fetch data