I'm using bindParam to bind the return value of stored procedure once the statement is executed
But i'm getting zero , i've specified output variable of stored procedure as BIGINT
and i'm binding parameter like below
$sql = "{:retval = CALL sp_testProc()}";
$stmt->bindParam('retval', $proc_pass_val, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT, 4);
bindparam is taking Length of data type as last parameter, i'm passing 4 here, but it returns zero, don't know why
Could anybody help me on this
Thanks in Advance
This is what I've done to make it work, Hope this helps someone.
Note: Procedure defined in MSSQL server
Here I want email into a field inorder to get that in an array, you can omit this line select #myemail as student_email; and you can get the value of #myemail into $myemail
My Procedure:
Alter proc [dbo].[sp_test_success](
#Id int=1,
#myemail varchar(250)=null output
)
AS
BEGIN
select #myemail=rtrim(email) from Student where StudentId=#Id;
select #myemail as student_email;-- i put this to get myemail into array
END
Code:
$dbh = new PDO('sqlsrv:Server=Server;Database=database', 'UID', 'Pwd');
$stmt = $dbh->prepare("{CALL sp_test_success(#Id=:Id,#myemail=:myemail)}");
$Id = 4;
$stmt->bindParam('Id', $Id, PDO::PARAM_INT);
$stmt->bindParam('myemail', $myemail, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 500);
$stmt->execute();
$results = array();
do {
$rows= $stmt->fetch();// default fetch type PDO::FETCH_BOTH
$results[]= $rows;
} while ($stmt->nextRowset());
echo "<pre>"; print_r($results);
print "procedure returned $myemail\n"; exit;
Related
Could you please help me with this please, my question is about PHP, PDO and stored procedures in MySQL.
I have created a very simple stored procedure called selectAVG that returns the average grade of a subject via an output parameter, here is a stored procedure that I have created in order to test my code(I cannot post the code reffer to selectAVG because of my boss) but I hope with this you can catch up the whole idea.
DELIMITER $$
USE `ejemplo`$$
DROP PROCEDURE IF EXISTS `selectCount_sp`$$
CREATE DEFINER=`root`#`localhost`
PROCEDURE `selectCount_sp`(
OUT totalEmpleados INT <-- out parameter
)
BEGIN
SELECT COUNT(Nombre) INTO totalEmpleados FROM empleado_php;
END$$
DELIMITER ;
and this is my script.php, what it does is to call the stored procedure and get the total of employees via the output parameter
try {
$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$sql = 'CALL selectCount_sp(#total)';
$stmt = $conn->prepare($sql);
$stmt->execute();
$stmt->closeCursor(); //permite limpiar y ejecutar la segunda query
$r = $conn->query('select #total')->fetch();
print_r ($r);
}
catch (PDOException $pe) {
die("Error occurred:" . $pe->getMessage());
}
my problem is that I cannot get the output value with a simple echo, I have to use print_r in order to get this:
Array ( [#total] => 5 [0] => 5 )
but I just want to get a simple 5, what do I have to do to show for example: echo "the total is:" .$total and have this: the total is 5 ?
You can use ->fetchColumn() in this case:
$r = $conn->query('select #total');
$total = $r->fetchColumn();
If you have PHP 5.4 or greater, then dereferences will also work:
$total = $conn->query('select #total')->fetch(PDO::FETCH_ASSOC)['#total'];
You can do either of these.
This is simply how to address an item in an array.
echo $r[0];
or
echo $r['#total']
Or it might be better to do
$r = $conn->query('select #total as total')->fetch();
echo $r['total']
as I am not sure if PHP would like an # symbol in an array occurance.
Below is some poorly written and heavily misunderstood PHP code with no error checking. To be honest, I'm struggling a little getting my head around the maze of PHP->MySQLi functions! Could someone please provide an example of how one would use prepared statements to collect results in an associative array whilst also getting a row count from $stmt? The code below is what I'm playing around with. I think the bit that's throwing me off is using $stmt values after store_result and then trying to collect an assoc array, and I'm not too sure why...
$mysqli = mysqli_connect($config['host'], $config['user'], $config['pass'], $config['db']);
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
$stmt->bind_param('i', $core['id']);
$result = $stmt->execute();
$stmt->store_result();
if ($stmt->num_rows >= "1") {
while($data = $result->fetch_assoc()){
//Loop through results here $data[]
}
}else{
echo "0 records found";
}
I feel a little cheeky just asking for code, but its a working demonstration of my circumstances that I feel I need to finally understand what's actually going on. Thanks a million!
I searched for a long time but never found documentation needed to respond correctly, but I did my research.
$stmt->get_result() replace $stmt->store_result() for this purpose.
So, If we see
$stmt_result = $stmt->get_result();
var_dump($stmt_result);
we get
object(mysqli_result)[3]
public 'current_field' => int 0
public 'field_count' => int 10
public 'lengths' => null
public 'num_rows' => int 8 #That we need!
public 'type' => int 0
Therefore I propose the following generic solution. (I include the bug report I use)
#Prepare stmt or reports errors
($stmt = $mysqli->prepare($query)) or trigger_error($mysqli->error, E_USER_ERROR);
#Execute stmt or reports errors
$stmt->execute() or trigger_error($stmt->error, E_USER_ERROR);
#Save data or reports errors
($stmt_result = $stmt->get_result()) or trigger_error($stmt->error, E_USER_ERROR);
#Check if are rows in query
if ($stmt_result->num_rows>0) {
# Save in $row_data[] all columns of query
while($row_data = $stmt_result->fetch_assoc()) {
# Action to do
echo $row_data['my_db_column_name_or_ALIAS'];
}
} else {
# No data actions
echo 'No data here :(';
}
$stmt->close();
$result = $stmt->execute(); /* function returns a bool value */
reference : http://php.net/manual/en/mysqli-stmt.execute.php
so its just sufficient to write $stmt->execute(); for the query execution.
The basic idea is to follow the following sequence :
1. make a connection. (now while using sqli or PDO method you make connection and connect with database in a single step)
2. prepare the query template
3. bind the the parameters with the variable
4. (set the values for the variable if not set or if you wish to change the values) and then Execute your query.
5. Now fetch your data and do your work.
6. Close the connection.
/*STEP 1*/
$mysqli = mysqli_connect($servername,$usrname,$pswd,$dbname);
/*STEP 2*/
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
/*Prepares the SQL query, and returns a statement handle to be used for further operations on the statement.*/
//mysqli_prepare() returns a statement object(of class mysqli_stmt) or FALSE if an error occurred.
/* STEP 3*/
$stmt->bind_param('i', $core['id']);//Binds variables to a prepared statement as parameters
/* STEP 4*/
$result = $stmt->execute();//Executes a prepared Query
/* IF you wish to count the no. of rows only then you will require the following 2 lines */
$stmt->store_result();//Transfers a result set from a prepared statement
$count=$stmt->num_rows;
/*STEP 5*/
//The best way is to bind result, its easy and sleek
while($data = $stmt->fetch()) //use fetch() fetch_assoc() is not a member of mysqli_stmt class
{ //DO what you wish
//$data is an array, one can access the contents like $data['attributeName']
}
One must call mysqli_stmt_store_result() for (SELECT, SHOW, DESCRIBE, EXPLAIN), if one wants to buffer the complete result set by the client, so that the subsequent mysqli_stmt_fetch() call returns buffered data.
It is unnecessary to call mysqli_stmt_store_result() for other queries, but if you do, it will not harm or cause any notable performance in all cases.
--reference: php.net/manual/en/mysqli-stmt.store-result.php
and http://www.w3schools.com/php/php_mysql_prepared_statements.asp
One must look up the above reference who are facing issue regarding this,
My answer may not be perfect, people are welcome to improve my answer...
If you would like to collect mysqli results into an associative array in PHP you can use fetch_all() method. Of course before you try to fetch the rows, you need to get the result with get_result(). execute() does not return any useful values.
For example:
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli($config['host'], $config['user'], $config['pass'], $config['db']);
$mysqli->set_charset('utf8mb4'); // Don't forget to set the charset!
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
$stmt->bind_param('i', $core['id']);
$stmt->execute(); // This doesn't return any useful value
$result = $stmt->get_result();
$data = $result->fetch_all(MYSQLI_ASSOC);
if ($data) {
foreach ($data as $row) {
//Loop through results here
}
} else {
echo "0 records found";
}
I am not sure why would you need num_rows, you can always use the array itself to check if there are any rows. An empty array is false-ish in PHP.
Your problem here is that to do a fetch->assoc(), you need to get first a result set from a prepared statement using:
http://php.net/manual/en/mysqli-stmt.get-result.php
And guess what: this function only works if you are using MySQL native driver, or "mysqlnd". If you are not using it, you'll get the "Fatal error" message.
You can try this using the mysqli_stmt function get_result() which you can use to fetch an associated array. Note get_result returns an object of type mysqli_result.
$stmt->execute();
$result = $stmt->get_result(); //$result is of type mysqli_result
$num_rows = $result->num_rows; //count number of rows in the result
// the '=' in the if statement is intentional, it will return true on success or false if it fails.
if ($result_array = $result->fetch_assoc(MYSQLI_ASSOC)) {
//loop through the result_array fetching rows.
// $ rows is an array populated with all the rows with an associative array with column names as the key
for($j=0;$j<$num_rows;$j++)
$rows[$j]=$result->fetch_row();
var_dump($rows);
}
else{
echo 'Failed to retrieve rows';
}
I am rather new at PDO-based MySQL and I'm running into a problem.
This is the method I'm executing :
public function insert( $table, $data )
{
// utility functions to auto-format the statements
$keys = $this->getKeys($data);
$placeholders = $this->getPlaceholders($data);
$q = "INSERT INTO $table ($keys) VALUES ($placeholders)";
// this simply returns a new PDO object
$dbh = $this->createSession();
$stmt = $dbh->prepare($q);
$stmt->execute( array_values($data) );
return $dbh->lastInsertId();
}
After that, I run my method and store the returned value in a variable :
$new_user_id = $U->insert( $data );
var_dump($new_user_id);
And I get
NULL
Note the query is actually executed, and my data is correctly inserted into my table; no problem on that side. It seems it just can't grab the last insert ID as I ask for it.
Thanks for your time.
Not sure about any PDO-specific issues, but by default MySQL only returns an insert id if there's an auto_increment integer field in the database (generally but not necessarily the primary key). If your table doesn't include this nothing is returned by $dbh->lastInsertId()
I've reviewed the code again and I found that my value wasn't returned because of an intermediate method that wasn't passing the value correctly to the top-layer method.
Checking the value at the source shows no problem.
Thanks for the replies anyway.
I was reader about PDO , and I was wondering what is the deference between those two methods:
public function query($sql)
{
$req = $this->db->prepare($sql);
$req->execute();
return $req->fetchAll(PDO::FETCH_OBJ);
}
public function query($sql, $data = array())
{
$req = $this->db->prepare($sql);
$req->execute($data);
return $req->fetchAll(PDO::FETCH_OBJ);
}
In the second method, execute has an empty array as a parameter and the first one doesn't, what is the role of using an empty array as a parameter for execute ?
The array is only empty by default. You can pass values in that array and they will be inserted into your SQL statement appropriately (ie - array key=>field name).
Defining an empty array in the function parameters states that this is an optional parameter and you are not forced to pass it - only when it is relevant. For example, when performing an INSERT command. If you don't pass any value to the $data parameter, it's default value will simply be an empty array.
An example of using default parameters -
function saySomething($text="Hello World!"){
echo $text;
}
saySomething(); // will echo out the default "Hello World!"
saySomething("Goodbye World!"); // will echo out "Goodbye World!" as specified.
First one lets you to run a query without parameters.
Second one lets you to run a query either with parameters or without:
$data = $db->query("SELECT * FROM table");
$data = $db->query("SELECT * FROM table WHERE id=?",array($id));
both works.
You can add you parameter bindings in an array instead of using the bindParam() function beforehand.
for instance you wanna select something by id
$stmt = $dbh->prepare("SELECT * FROM `something` WHERE `id` = ?");
$stmt->execute(array($id));
is the same as
$stmt = $dbh->prepare("SELECT * FROM `something` WHERE `id` = ?");
$stmt->bindParam(1, $id, PDO::PARAM_INT, 11);
$stmt->execute();
Though for the bindParam function you can check better,
Check PHP Manual PDO::excute()
This has been driving me crazy, the issue is I cannot work out How i can get and set the cached data to be displayed within my view.
public function get_something($id, $account_name)
{
$sql = "SELECT one,two,three FROM table WHERE id = ? and account_name = ? ";
$key = md5("SELECT one,two,three FROM table WHERE id = $id and account_name = $account_name ");
$get_result = $this->Core->Core->Memcache->get($key);
if($get_result)
{
// How would I set the Data
}
else
{
$stmt = $this->Core->Database->prepare($sql);
$stmt->bind_param("is", $id, $account_name);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($one, $two, $three);
$stmt->fetch();
//Below is how i set the data
$this->Core->Template->set_data('one', $one);
//Set the Memcache
$this->Core->Memcache->set($key, $stmt, TRUE, 20);
}
So my question is how can I get and set the data from a prepared statement fetch within memcache?
Memcache is a key/value storage system with both the key and the value needing to be serialized. From the php.net page:
Remember that resource variables (i.e. file and connection descriptors) cannot be stored in the cache, because they cannot be adequately represented in serialized state.
It appears your sql statement is looking for three values in a single row. I'm no expert on mysqli, but this is kind of what you want to do:
public function get_something($id, $account_name){
$sql = "SELECT one,two,three FROM table WHERE id = ? and account_name = ? ";
$key = md5("SELECT one,two,three FROM table WHERE id = $id and account_name = $account_name ");
$get_result = $this->Core->Core->Memcache->get($key);
if($get_result){
return $get_result;//#1 just return it, the format is an array like what is being built below
}
else{
$stmt = $this->Core->Database->prepare($sql);
$stmt->bind_param("is", $id, $account_name);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($one, $two, $three);
$stmt->fetch();
//Below is how i set the data
$this->Core->Template->set_data('one', $one);//#2 I don't know what this line does or is for, presumably for something else besides memcache stuff, maybe it acts like return
//Set the Memcache
$array=array();//#3
$array[]=$one;
$array[]=$two;
$array[]=$three;
$this->Core->Memcache->set($key, $array, TRUE, 20);
//this is a function, do you want to return your values somewhere?
}
A few notes, #1 the answer to your question is simple, just return $get_result. It should be an array with three values. #2 I'm not familiar with this line, nor what it does. Is this how your "return" the values to your controller? If so, you'll want to mimick that line where I put the return inside the if #3 This is your problem. You can't save the $stmt variable in memcache, it's a mysqli object, not the data you want. You need to build an array and then save that array. And that should do it for you.
There are other nuances to do, you can loop on the returned values. You should check for mysql not returning anything. But this is the basic starting point to get this going.
Let me know if this works for you.