I'm using PHP to process some XML that I'm getting from a web service and to insert the results into a database. I've created a stored procedure to insert the records and I'm using PDO to prepare a statement that I'd then like to execute multiple times, something like this:
$st = $this->db->prepare('CALL AddClient(:Name, :Id, :Priority, :Territory, :DateCreated, :Result)');
$st->bindParam(':Name', $Name, PDO::PARAM_STR);
$st->bindParam(':Id', $Id, PDO::PARAM_INT);
$st->bindParam(':Priority', $Priority, PDO::PARAM_STR);
$st->bindParam(':Territory', $Territory, PDO::PARAM_STR);
$st->bindParam(':DateCreated', $dateFormat, PDO::PARAM_STR);
$st->bindParam(':Result', $result, PDO::PARAM_STR);
foreach ($this->xml->AccountsDataSet->MainRecord as $Account) {
$Name = (string) $Account->AcctDesc;
$Id = (int) $Account->AcctID;
if ($num = (int)$Account->CDF309607) {
$Priority = self::$priorityFields[$num];
} else {
$Priority = '';
}
if (! $Territory = (string) $Account->AcctState) {
$Territory = '';
}
$date = new DateTime($Account->AcctCreationDate, new DateTimeZone('UTC'));
$dateFormat = $date->format('Y-m-d H:i:s');
$st->execute();
echo $result . '<br />';
}
In this example ':Result' would be a output value from the procedure. I cannot make this work at all though. If I omit the out put parameter both in the procedure code and PHP then one row gets inserted but subsequent calls in the loop fail. To make this work I have to prepare the statement fresh each time in the loop, then binding the parameters to the statement again. I still cannot make this work with an output parameter in the procedure and have to Select a value in the procedure to get some return value to PHP to process.
Does anyone know where I'm going wrong with this? Ideally I'd like to prepare the statement once and then loop through the results, executing it each time with fresh data. Are there any tricks that I'm missing to make all of this work? I'm developing on Windows 7 with Apache 2.2.17, PHP 5.3.5 and MySQL 5.5.8.
EDIT:
Well, the answer to executing the statement multiple times in the loop seems to be to call the PDOStatement::closeCursor() method each time after calling PDOStatement::execute(). Still no idea on how to get the value of an output parameter returned to PHP though.
EDIT
Here's the code for the procedure:
CREATE
PROCEDURE foo.AddClient(IN ClientName VARCHAR(255), IN Client_Id INT UNSIGNED, IN Priority VARCHAR(255), IN Territory VARCHAR(100), IN DateCreated DATETIME, OUT Result VARCHAR(100))
COMMENT 'Procedure to add a new client to the database'
BEGIN
#Declare variables.
DECLARE Priority_Id, Territory_Id TINYINT UNSIGNED DEFAULT NULL;
# Check if a Priority is defined. If so get the id, if not add it and get the id
IF LENGTH(Priority) > 0 THEN
SELECT
PriorityId
INTO
Priority_Id
FROM
client_priority
WHERE
Name = Priority;
IF Priority_Id IS NULL THEN
INSERT INTO client_priority (Name) VALUES (Priority);
SET Priority_Id = LAST_INSERT_ID();
END IF;
END IF;
#Check if a Territory is defined. If so get the id, if not add it and get the id.
IF LENGTH(Territory) > 0 THEN
SELECT
TerritoryId
INTO
Territory_Id
FROM
territories
WHERE
Name = Territory;
IF Territory_Id IS NULL THEN
INSERT INTO territories (Name) VALUES (Territory);
SET Territory_Id = LAST_INSERT_ID();
END IF;
END IF;
#Add the details of the client.
BEGIN
DECLARE EXIT HANDLER FOR SQLSTATE '23000'
SET Result = 'Client already exists'; # Error handler in case client with the same name already exists.
INSERT INTO clients
(ClientId, Name, PriorityId, TerritoryId, DateCreatedSalesNet) VALUES (Client_Id, ClientName, Priority_Id, Territory_Id, DateCreated);
SET Result = 'Client Inserted';
END;
END
The fact is you can't access you result like this, see these posts :
http://bugs.mysql.com/bug.php?id=25970
http://dev.mysql.com/doc/refman/5.0/en/call.html
So you will need to store the result into a MySQL var, then you can display it, like this :
<?php
// change
$st = $this->db->prepare('CALL AddClient(:Name, :Id, :Priority, :Territory, :DateCreated, :Result)');
// to
$st = $this->db->prepare('CALL AddClient(:Name, :Id, :Priority, :Territory, :DateCreated, #result)');
// remove this line
$st->bindParam(':Result', $result, PDO::PARAM_STR);
// change
$st->execute();
echo $result . '<br />';
// to
$st->execute();
echo $this->db->query('SELECT #result')->fetchColumn() . '<br />';
Try adding a string length to the output parameter:
$st->bindParam(':Result', $result, PDO::PARAM_STR, 4000);
Try to add PDO::PARAM_INPUT_OUTPUT:
$st->bindParam(':Result', $result, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);
Related
Is it possible to retrieve the rowid of the last inserted Oracle row in PHP? I was trying:
$statement = oci_parse($conn, "INSERT INTO myTable (...) VALUES ( ...)");
$results = oci_execute($statement);
while($row = oci_fetch_assoc($statement)) {
$rowid = $row['ROWID'];
}
With no luck. I'm getting the error define not done before fetch or execute and fetch at the fetch line.
Declare:
$var = "AAAV1vAAGAAIb4CAAC";
Use:
INSERT INTO myTable (...) VALUES ( ...)
RETURNING RowId INTO :p_val
Bind your variable to a PHP variable:
oci_bind_by_name($statement, ":p_val", $val, 18);
As the previous answer was not really clear to me because it lacks some important information I will point out a similar approach.
In your SQL statement, add the RETURNING INTOclause.
$statement = oci_parse($conn, "INSERT INTO myTable (...) VALUES ( ...) RETURNING ID INTO :id");
Here ID is the name of the column you want to return. Before executing the $statement, you need to bind a PHP variable to your return value. Here I used $returnId (you don't need to declare it beforehand or assign any default value).
oci_bind_by_name($statement, ":id", $returnId);
Only after binding the variable, the statement can be executed.
$success = #oci_execute($statement);
$returnId now has the value of the ID column inserted previously.
SO I'm using PHP and PDO to insert data into a MySQL database.
function addLog($id, $wd, $m, $md, $t, $tz, $y, $ilp, $igp)
{
echo "|2|$wd/$m/$md/$t/$tz/$y/$ilp/$igp|";
$connection = connectUserLogfiles();
try
{
$sql = "INSERT INTO `log_meta` (`log_id`, `weekday`, `month`, `month_day`, `time`, `time_zone`, `year`, `inside_local_ip`, `inside_global_ip`) VALUES (log_id=:log_id, weekday=:weekday, month=:month, month_day=:month_day, time=:time, time_zone=:time_zone, year=:year, inside_local_ip=:inside_local_ip, inside_global_ip=:inside_global_ip);";
$stmt = $connection->prepare($sql);
$stmt->bindParam(':log_id', $id, PDO::PARAM_STR);
$stmt->bindParam(':weekday', $wd, PDO::PARAM_STR);
$stmt->bindParam(':month', $m, PDO::PARAM_STR);
$stmt->bindParam(':month_day', $md, PDO::PARAM_STR);
$stmt->bindParam(':time', $t, PDO::PARAM_STR);
$stmt->bindParam(':time_zone', $tz, PDO::PARAM_STR);
$stmt->bindParam(':year', $y, PDO::PARAM_STR);
$stmt->bindParam(':inside_local_ip', $ilp, PDO::PARAM_STR);
$stmt->bindParam(':inside_global_ip', $igp, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->rowCount();
$stmt->closeCursor();
return $result;
} catch (Exception $ex) {
$_SESSION['error'] = '<p>Error: something went wrong in addLog(), and we have absolutely no idea why. Sorry.</p>';
}
}
the result of the echo statement is as follows:
|1|Sun/Dec/31/12:12:12/Africa/Abidjan/2015/10.0.0.0/9.0.0.0|
Also, a message is displayed which indicates that one row was successfully returned in the Result Set via the $result variable. (this occurs in the index, but i assure you, one row is returned in the Result Set.)
My problem is that the database indicates that every column-value in the inserted row has a value of zero. This also goes for the Primary Key, which is NOT auto-incremented, because that is taken care through the use of PHP. (the lack of auto-increment is a result of how this database is tied to an app and how that app functions.)
After this query is executed, the user is taken to a view which correctly displays all of the associated information as the user inputted the data. However, this is based on the local variables from the user input, and not the database. I felt this was safe to do because at that point, i have confirmed that the user input was valid and that it was inserted into the database correctly.
My primary key, the log_id,is an INT data type.
All other data types are VARCHAR.
There are NO default values set for the table in the database.
NONE of the columns are set as requiring unique values within their respective columns.
NONE of the columns are Foreign Keys.
ALL of the columns are set as nullable, merely because of my lazyness, and because i've already check for null values before this point in the INSERT process.
WHY does the insert not work correctly? I use PHPMyAdmin to operate with the database
Remove the columns from the VALUES (...) of your query -
$sql = "INSERT INTO `log_meta` (`log_id`, `weekday`, `month`, `month_day`, `time`, `time_zone`, `year`, `inside_local_ip`, `inside_global_ip`) VALUES (:log_id, :weekday, :month, :month_day, :time, :time_zone, :year, :inside_local_ip, :inside_global_ip);";
You already defined them in the query, and since there was not space between the equal sign and semicolon - =: your params were not recognized as params.
I'm trying to get a value from a string declared inside a stored procedure, so that I can use it in my PHP-code.
The procedure:
DELIMITER //
CREATE PROCEDURE InsertName
(IN NewName varchar(50), OUT NewID char(25))
BEGIN
DECLARE NewID CHAR(25) DEFAULT (SELECT CONCAT((SELECT unix_timestamp()), (SELECT FLOOR(RAND() * 1000000000000000))));
INSERT INTO User
VALUES (NewID, NewName);
END;
//
DELIMITER ;
The PHP-code that calls the procedure:
$name = $_POST['name'];
$sth = $pdo->prepare("CALL InsertName('$name', #idcode)");
$sth->execute();
$sth->closeCursor();
$sth = $pdo->query("SELECT #idcode AS idcode");
$newid = $sth->fetch(PDO::FETCH_ASSOC);
$idcode=$newid['idcode'];
echo $idcode . " blarg";
The page I'm trying to display only shows " blarg", and nothing else. Something is wrong when fetching the OUT parameter. I have also tried with
SELECT NewID;
in the procedure, it still gives the same result.
Is it possible to retrieve the rowid of the last inserted Oracle row in PHP? I was trying:
$statement = oci_parse($conn, "INSERT INTO myTable (...) VALUES ( ...)");
$results = oci_execute($statement);
while($row = oci_fetch_assoc($statement)) {
$rowid = $row['ROWID'];
}
With no luck. I'm getting the error define not done before fetch or execute and fetch at the fetch line.
Declare:
$var = "AAAV1vAAGAAIb4CAAC";
Use:
INSERT INTO myTable (...) VALUES ( ...)
RETURNING RowId INTO :p_val
Bind your variable to a PHP variable:
oci_bind_by_name($statement, ":p_val", $val, 18);
As the previous answer was not really clear to me because it lacks some important information I will point out a similar approach.
In your SQL statement, add the RETURNING INTOclause.
$statement = oci_parse($conn, "INSERT INTO myTable (...) VALUES ( ...) RETURNING ID INTO :id");
Here ID is the name of the column you want to return. Before executing the $statement, you need to bind a PHP variable to your return value. Here I used $returnId (you don't need to declare it beforehand or assign any default value).
oci_bind_by_name($statement, ":id", $returnId);
Only after binding the variable, the statement can be executed.
$success = #oci_execute($statement);
$returnId now has the value of the ID column inserted previously.
i am using php with mysql.
My stored proc returns values via out parameter via Toad4MySQL but when it comes to php Pdo, it does not capture the return value.
here's my code
$validusername= 'x';
$validemail = 'x';
$validkey = 'x';
$query = $pdo->prepare("Call InsertNewUser(:fullname, :usernamex, :email, :password, :con_password, #:validusername, #:validemail, #:validkey); ");
$query->bindParam(':fullname', $fullname , PDO::PARAM_STR);
$query->bindParam(':usernamex', $usernamex , PDO::PARAM_STR);
$query->bindParam(':email', $email, PDO::PARAM_STR);
$query->bindParam(':password', $password, PDO::PARAM_STR);
$query->bindParam(':con_password', $con_password, PDO::PARAM_STR);
$query->bindParam(':validusername', $validusername, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT);
$query->bindParam(':validemail', $validemail , PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT);
$query->bindParam(':validkey', $validkey , PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT);
$results = $query-> execute();
echo $validemail ; # returns x but not the value that i wanted.
Can anyone help me with this puzzle ?
My Stored Procedure code:
DROP PROCEDURE IF EXISTS InsertNewUser;
CREATE PROCEDURE xxx.`InsertNewUser`(
fullname varchar(255),
username varchar(255),
email_address varchar(255),
password varchar(255),
con_password varchar(255),
out validusername varchar(10),
out validemail varchar(10),
out validkey varchar(155)
)
BEGIN
declare xcnt_1 int;
declare xcnt_2 int;
declare xkey varchar(155);
set xkey = MD5(RAND());
select count(*) into xcnt_1 from user where user.email_address = email_address;
select count(*) into xcnt_2 from user where user.username = username;
if xcnt_1 > 0 then
set validemail = 'false';
else
set validemail = 'true';
end if;
if xcnt_2 > 0 then
set validusername = 'false';
else
set validusername = 'true';
end if;
if xcnt_1 = 0 and xcnt_2 = 0 then
set validkey = xkey;
INSERT INTO user
(user.fullname, user.username, user.email_address, user.password, user.con_password, user.md5validate)
VALUES
(fullname, username, email_address, password, con_password, xkey);
else
set validkey = 'false';
end if;
commit;
END;
ah... finally solved this problem :
for some unknown reasons, i have to change the call statement to :
Call InsertNewUser(:fullname, :usernamex, :email, :password, :con_password, #validusername_global, #validemail_global, #validkey_global);
and use this line of codes to get the data...
$SQL = ' select #validusername_global as validusername, #validemail_global as validemail, #validkey_global as validkey';
$query = $pdo->query($SQL);
while($row = $query->fetch(PDO::FETCH_ASSOC))
{
print_r($row);
}
Executing the PDO prepared statement won't have any effect on $validemail.
After $results = $query->execute();, try adding print_r($query->fetchAll()); to get a better sense of what is being returned from MySQL to PHP when your PHP statement runs the MySQL stored procedure.
Keep in mind that $results is just going to be a boolean indicating whether or not the statement could be executed.
From the PDO manual:
int $length
Length of the data type.
To indicate that a parameter is an OUT
parameter from a stored procedure, you
must explicitly set the length.
http://php.net/manual/en/pdostatement.bindparam.php
You have omitted this parameter, which would explain why it is not being used as an OUT parameter.
if you set $validemail=x and dont manipulate/change nothing with $validemail in later code then obvioulsy echo $validemail will returns x.? whats' wrong with that? either u missed to paste some code
Try wrapping your prepare statement, bind parameters and execute in try, catch blocks and see if PDO spits out any sort of error.