I am getting the following error, When I tried to execute GET_Card_TRANS procedure:
[code] => 6550
[message] => ORA-06550: line 6, column 21:
PLS-00103: Encountered the symbol "" when expecting one of the following:
. ( ) , * # % & = - + < / > at in is mod remainder not rem =>
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || indicator multiset member submultiset
[offset] => 155
[sqltext] => BEGIN
WEB_SHOW.GET_Card_TRANS(
:User_Id,
:Pswd,
:vcard_id
:sdate
:EDATE
:Vcond
:CARD_TRANS_data
);
END;
This is the PHP code:
<?php
// Connect to database
$conn = oci_connect("xxx", "yyy", "aaaa:bb/cc", 'dd');
if (!$conn) {
$e = oci_error($conn);
print_r($e);
exit ("Connection failed.");
}
$user_id = 'demo';
$password = 'password';
$vcard_id = '1-0';
$start_date = '01-01-2016';
$end_date = '01-01-2016';
$condition = '1';
$sql = "BEGIN
web_show.GET_Card_TRANS(
:User_Id,
:Pswd,
:vcard_id
:sdate
:EDATE
:Vcond
:CARD_TRANS_data
);
END;";
$stmt = oci_parse($conn, $sql);
oci_bind_by_name($stmt, ':User_Id', $user_id );
oci_bind_by_name($stmt, ':Pswd', $password );
oci_bind_by_name($stmt, ':vcard_id', $vcard_id );
oci_bind_by_name($stmt, ':sdate', $start_date );
oci_bind_by_name($stmt, ':EDATE', $end_date );
oci_bind_by_name($stmt, ':Vcond', $condition );
// Create a new cursor resource
$curs = oci_new_cursor($conn);
// Bind the cursor resource to the Oracle argument
oci_bind_by_name($stmt,":CARD_TRANS_data",$curs,-1,OCI_B_CURSOR);
if (!oci_execute($stmt)) {
$e = oci_error($stmt);
print_r($e);
exit("Procedure Failed.");
}
// Execute the cursor
if (!oci_execute($curs, OCI_DEFAULT)) {
$e = oci_error($curs);
print_r($e);
exit("Execute cursor Failed.");
}
while (($row = oci_fetch_array($curs, OCI_ASSOC+OCI_RETURN_NULLS)) != false) {
print_r($row);
//echo $row['FIRST_NAME'] . "<br />\n";
}
oci_free_statement($stmt);
oci_free_statement($curs);
oci_close($conn);
?>
Missing commas, perhaps?
This:
$sql = "BEGIN
web_show.GET_Card_TRANS(
:User_Id,
:Pswd,
:vcard_id
:sdate
:EDATE
:Vcond
:CARD_TRANS_data
);
END;"
;
Should instead be:
$sql = "BEGIN
web_show.GET_Card_TRANS(
:User_Id,
:Pswd,
:vcard_id,
:sdate,
:EDATE,
:Vcond,
:CARD_TRANS_data
);
END;";
Related
It gives true but when I use oci_fetch($stmt) it shows error.
oci_fetch(): ORA-24374: define not done before fetch or execute and
fetch
$sql = "DECLARE
C1 KTI_OPPL_DB.MH_ONLINE_PACKAGE_DB.TABLE_OF_LOV;
BEGIN
KTI_OPPL_DB.MH_ONLINE_PACKAGE_DB.GET_VESSEL_TYPE_LOV(C1);
END;";
$stmt = oci_parse($conn, $sql);
$r = oci_execute($stmt);
while (oci_fetch($stmt)) {
$nrows = oci_num_rows($stmt);
}
As I was telling you in the comment section, oci_fetch will not provide any result because the statement you are executing is not a sql statement, but a pl/sql procedure.
How to use OCI_FETCH
Fetches the next row from a query into internal buffers accessible either with oci_result(), or by using variables previously defined with oci_define_by_name().
An example using oci_result
<?php
$conn = oci_connect('hr', 'welcome', 'localhost/XE');
if (!$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}
$sql = 'SELECT location_id, city FROM locations WHERE location_id < 1200';
$stid = oci_parse($conn, $sql);
oci_execute($stid);
while (oci_fetch($stid)) {
echo oci_result($stid, 'LOCATION_ID') . " is ";
echo oci_result($stid, 'CITY') . "<br>\n";
}
// Displays:
// 1000 is Roma
// 1100 is Venice
oci_free_statement($stid);
oci_close($conn);
?>
An example with oci_define_by_name
<?php
$conn = oci_connect('hr', 'welcome', 'localhost/XE');
if (!$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}
$sql = 'SELECT location_id, city FROM locations WHERE location_id < 1200';
$stid = oci_parse($conn, $sql);
// The defines MUST be done before executing
oci_define_by_name($stid, 'LOCATION_ID', $locid);
oci_define_by_name($stid, 'CITY', $city);
oci_execute($stid);
// Each fetch populates the previously defined variables with the next row's data
while (oci_fetch($stid)) {
echo "Location id $locid is $city<br>\n";
}
// Displays:
// Location id 1000 is Roma
// Location id 1100 is Venice
oci_free_statement($stid);
oci_close($conn);
?>
In your case, you are executing a PROCEDURE which is providing as output a user defined type. In this case you might try oci_fetch_array to get the result of the procedure passed as an array of three values ( which is what you get from your output ). PHP and Oracle user defined types are tricky, so I'd try this ( Adapt to your code ):
<?php
$stid = oci_parse($conn, 'BEGIN yourprocedure(:rc); END;');
$refcur = oci_new_cursor($conn);
oci_bind_by_name($stid, ':rc', $refcur, -1, OCI_B_CURSOR);
oci_execute($stid);
// Execute the returned REF CURSOR and fetch from it like a statement identifier
oci_execute($refcur);
echo "<table border='1'>\n";
while (($row = oci_fetch_array($refcur, OCI_ASSOC+OCI_RETURN_NULLS)) != false) {
echo "<tr>\n";
foreach ($row as $item) {
echo " <td>".($item !== null ? htmlentities($item, ENT_QUOTES) : " ")."</td>\n";
}
echo "</tr>\n";
}
echo "</table>\n";
oci_free_statement($refcur);
oci_free_statement($stid);
oci_close($conn);
?>
Without knowing the exact PL/SQL to create your type, we can only guess what TABLE_OF_LOV is. Here is an example that shows getting records from a TABLE OF VARCHAR2, which seems a feasible guess.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 'On');
$c = oci_connect("hr", "welcome", "localhost/XE");
if (!$c) {
$m = oci_error();
trigger_error('Could not connect to database: '. $m['message'], E_USER_ERROR);
}
//
// Create a PL/SQL package that has a 'TABLE OF' OUT parameter
//
$create_pkg = "
CREATE OR REPLACE PACKAGE mypackage AS
TYPE TABLE_OF_LOV IS TABLE OF VARCHAR(20) INDEX BY BINARY_INTEGER;
PROCEDURE GET_VESSEL_TYPE_LOV(p1 OUT TABLE_OF_LOV);
END mypackage;";
$s = oci_parse($c, $create_pkg);
if (!$s) {
$m = oci_error($c);
trigger_error('Could not parse statement: '. $m['message'], E_USER_ERROR);
}
$r = oci_execute($s);
if (!$r) {
$m = oci_error($s);
trigger_error('Could not execute statement: '. $m['message'], E_USER_ERROR);
}
$create_pkg_body = "
CREATE OR REPLACE PACKAGE BODY mypackage AS
PROCEDURE GET_VESSEL_TYPE_LOV(p1 OUT TABLE_OF_LOV) IS
BEGIN
p1(1) := 'one';
p1(2) := 'two';
p1(3) := '';
p1(4) := 'four';
p1(5) := 'five';
END GET_VESSEL_TYPE_LOV;
END mypackage;";
$s = oci_parse($c, $create_pkg_body);
if (!$s) {
$m = oci_error($c);
trigger_error('Could not parse statement: '. $m['message'], E_USER_ERROR);
}
$r = oci_execute($s);
if (!$r) {
$m = oci_error($s);
trigger_error('Could not execute statement: '. $m['message'], E_USER_ERROR);
}
//
// Call the PL/SQL procedure
//
$s = oci_parse($c, "BEGIN mypackage.get_vessel_type_lov(:bv); END;");
if (!$s) {
$m = oci_error($c);
trigger_error('Could not parse statement: '. $m['message'], E_USER_ERROR);
}
$r = oci_bind_array_by_name($s, ":bv", $array, 5, 20, SQLT_CHR);
if (!$r) {
$m = oci_error($s);
trigger_error('Could not bind a parameter: '. $m['message'], E_USER_ERROR);
}
$r = oci_execute($s);
if (!$r) {
$m = oci_error($s);
trigger_error('Could not execute statement: '. $m['message'], E_USER_ERROR);
}
var_dump($array);
?>
Output is:
$ php so3.php
array(5) {
[0]=>
string(3) "one"
[1]=>
string(3) "two"
[2]=>
string(0) ""
[3]=>
string(4) "four"
[4]=>
string(4) "five"
}
You may find other solutions such as writing 'PL/SQL wrappers' in the USING PL/SQL WITH OCI8 chapter on p187 of the free book The Underground PHP and Oracle Manual.
I'm a beginner in PHP programming.
I have an SP in SQL Server with input, output and ReturnValue parameters that returns data from an sample table.
CREATE PROCEDURE [dbo].[sp_PHP]
#in1 int, #in2 int, #out3 int OUTPUT
WITH EXEC AS CALLER
AS
SET #out3 = #in1 * #in2
SELECT * FROM PHP
RETURN #in1 + #in2
This is my PHP code
<?php
try
{
$conn = new PDO("sqlsrv:Server=xxxxx,1433;Database=xxxxxx", "xx", "xx");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (Exception $e)
{
die(print_r($e->getMessage()));
}
$query = '{? = CALL sp_PHP(?, ?, ?)}';
$stmt = $conn->prepare($query);
$returnVariable = -1;
$inputVariable1 = 18;
$inputVariable2 = 24;
$outputVariable3 = -1;
$stmt->bindParam(1,$returnVariable, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, 100);
$stmt->bindParam(2,$inputVariable1, PDO::PARAM_INT);
$stmt->bindParam(3,$inputVariable2, PDO::PARAM_INT);
$stmt->bindParam(4,$outputVariable3, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, 100);
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_BOTH);
foreach($results as $row) {
echo $row['PHP_ID'].' '.$row['PHP_Char'].'<br>';
}
echo '<hr>';
echo 'Return value: '.$returnVariable.'<br>';
echo 'Output parameter: '.$outputVariable3.'<br>';
?>
If I remove the line in the SP
SELECT * FROM PHP
and don't read the data received in PHP with following code
$results = $stmt->fetchAll(PDO::FETCH_BOTH);
foreach($results as $row) {
echo $row['PHP_ID'].' '.$row['PHP_Char'].'<br>';
}
I receive the correct values of $returnVariable (42) and $outputVariable3 (432).
But if I read (and show) the data read from the SP, $returnVariable and $outputVariable3 are equal to -1 (the assigned value)
I wanto to read output parameter, ReturnValue and data at the same time.
Is it possible? Where am I wrong?
Thanks!!
Solution:
The value of the output (or input/output) parameter is accessible when you consume all results returned by the stored procedure (PDO and not PDO versions). In your case you need to move throw resultsets with PDOStatement::nextRowset to get the values for the output parameters.
Example:
I've reproduced your example and next code works for me.
<?php
$server = 'server\instance,port';
$database = 'database';
$uid = 'user';
$pwd = 'password';
try {
$conn = new PDO("sqlsrv:server=$server;Database=$database", $uid, $pwd);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage());
}
try {
$sql = "{? = CALL sp_PHP(?, ?, ?)}";
#$sql = "EXEC ? = sp_PHP(?, ?, ?)";
$stmt = $conn->prepare($sql);
$returnVariable = -1;
$inputVariable1 = 18;
$inputVariable2 = 24;
$outputVariable3 = -1;
$stmt->bindParam(1, $returnVariable, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->bindParam(2, $inputVariable1, PDO::PARAM_INT);
$stmt->bindParam(3, $inputVariable2, PDO::PARAM_INT);
$stmt->bindParam(4, $outputVariable3, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->execute();
do {
echo 'Result set:'."<br>";
while ($row = $stmt->fetch( PDO::FETCH_ASSOC) ){
print_r($row)."<br>";
}
echo "<br>";
echo "<br>";
} while ($stmt->nextRowset());
} catch( PDOException $e ) {
die( "Error executing query" );
}
$stmt = null;
$conn = null;
echo 'Stored procedure return value: '.$returnVariable."</br>";
echo 'Stored procedure output parameter: '.$outputVariable3."</br>";
?>
I am trying to input a date value from the user and then using that value in the query.
My date value is like this 2017.07.21 08:59:26
$MYDATE= $data[$i]->MYDATE;
//ALSO I ADDED
$str = oci_parse($conn, "ALTER SESSION SET NLS_DATE_FORMAT = 'DD.MM.YYYY HH24:MI:SS'");
oci_execute($str);
//
$sql = 'INSERT INTO MYTABLE(ID,MYDATE)'.'VALUES(:ID,to_date(:MYDATE,\'YYYY.MM.DD HH24:MI:SS\'))';
$compiled = oci_parse($conn, $sql);
oci_bind_by_name($compiled, ':ID', $ID);
oci_bind_by_name($compiled, ':MYDATE', $MYDATE);
oci_execute($compiled);
It gave me this error:
inconsistent datatypes: expected DATE got NUMBER
This script:
<?php
/*
drop table mytable purge;
create table mytable (id number, mydate date);
*/
error_reporting(E_ALL);
ini_set('display_errors', 'On');
$c = oci_connect("hr", "welcome", "localhost/XE");
if (!$c) {
$m = oci_error();
trigger_error('Could not connect to database: '. $m['message'], E_USER_ERROR);
}
$sql = <<<'END'
INSERT INTO MYTABLE(ID,MYDATE) VALUES(:ID,to_date(:MYDATE,'YYYY.MM.DD HH24:MI:SS'))
END;
$id = 1;
//$mydate = '2017.07.21 08:59:26'; // also works
$mydate = date("Y.m.d H:i:s");
echo "input value: ", $mydate, "\n\n";
$s = oci_parse($c, $sql);
if (!$s) {
$m = oci_error($c);
trigger_error('Could not parse statement: '. $m['message'], E_USER_ERROR);
}
$r = oci_bind_by_name($s, ':id', $id);
if (!$r) {
$m = oci_error($s);
trigger_error('Could not bind a parameter: '. $m['message'], E_USER_ERROR);
}
$r = oci_bind_by_name($s, ':mydate', $mydate);
if (!$r) {
$m = oci_error($s);
trigger_error('Could not bind a parameter: '. $m['message'], E_USER_ERROR);
}
$r = oci_execute($s, OCI_NO_AUTO_COMMIT);
if (!$r) {
$m = oci_error($s);
trigger_error('Could not execute statement: '. $m['message'], E_USER_ERROR);
}
// Fetch back the data
$s = oci_parse($c, "select to_char(mydate, 'YYYY.MM.DD HH24:MI:SS') as mydate from mytable");
if (!$s) {
$m = oci_error($c);
trigger_error('Could not parse statement: '. $m['message'], E_USER_ERROR);
}
$r = oci_execute($s, OCI_NO_AUTO_COMMIT);
if (!$r) {
$m = oci_error($s);
trigger_error('Could not execute statement: '. $m['message'], E_USER_ERROR);
}
oci_fetch_all($s, $r);
var_dump($r);
oci_rollback($c);
?>
gives this output:
input value: 2021.04.06 10:50:20
array(1) {
["MYDATE"]=>
array(1) {
[0]=>
string(19) "2021.04.06 10:50:20"
}
}
Things you can do:
do a var_dump() on your input date, to show its type
do a DESC on the table to show your datatype
I believe you'd added it for testing, but in production you would want to avoid running ALTER SESSION for each connection, since this adds overhead. Instead use the TO_DATE, or set the environment variables NLS_DATE_FORMAT and NLS_LANG (both are needed) before PHP starts. See the Globalization chapter in The Underground PHP and Oracle Manual
I`m working with PDO and prepare statements and now I want to implement transactions, but when I do it I get this error:
Call to a member function beginTransaction() on a non-object in
The code is:
include_once '../../includes/db_connect.php';
include_once '../../includes/psl-config.php';
$mysqli->query("SET NAMES 'utf8'");
date_default_timezone_set('America/Mexico_City');
$hora = date("d-m-Y g:i a");
$mysqli->beginTransaction();
//OBTENCIÓN DE LA INFORMACIÓN
$id = $mysqli->real_escape_string( $_POST["id"] );
$fechaEntrada = date("Y-m-d");
$estatus = "Disponible";
$idUser = $mysqli->real_escape_string( $_POST['idUser'] );
$idUser = $idUser . " " . $hora;
//SELECIONAR INFORMACIÓN DE LA MAQUINA A ENTRAR
$sqlMaquina = "SELECT tipo, clave FROM maquinas_orden_renta WHERE id = $id";
$res = $mysqli->query($sqlMaquina);
$rows = $res->num_rows;
if (!$res)
printf("Error message: %s\n", $mysqli->error);
$objMaquinaRenta = $res->fetch_object();
$tipoMaquina = $objMaquinaRenta->tipo;
$idMaquina = $objMaquinaRenta->clave;
$sql = "UPDATE maquinas_orden_renta SET entradaReal = ?, estatus = ?,updated_by = ? WHERE id = ?";
$stmt = $mysqli->prepare($sql);
if ( false === $stmt )
die('prepare() failed: ' . htmlspecialchars($mysqli->error));
$rc = $stmt->bind_param('sssi', $fechaEntrada, $estatus, $idUser, $id );
if ( false === $rc )
die('bind_param() failed: ' . htmlspecialchars($stmt->error));
$rc = $stmt->execute();
if ( false === $rc )
die('execute() failed: ' . htmlspecialchars($stmt->error));
else{
if ($tipoMaquina == "conID") {
$sql2 = "UPDATE maquinas SET estatus = ?, updated_by = ? WHERE IdMaquina = ?";
$stmt = $mysqli->prepare($sql2);
if ( false === $stmt )
die('prepare2() failed: ' . htmlspecialchars($mysqli->error));
$rc2 = $stmt->bind_param('ss', $estatus, $idUser, $idMaquina );
if ( false === $rc2 )
die('bind_param2() failed: ' . htmlspecialchars($stmt->error));
$rc2 = $stmt->execute();
if ( false === $rc2 )
die('execute2() failed: ' . htmlspecialchars($stmt->error));
else
echo "Éxito";
}
}
if (false === $rc AND false === $rc2) {
echo "exito";
$mysqli->commit();
}else{
$mysqli->rollBack();
echo "error: $error";
}
$stmt->close();
So, I don`t know if the function beginTransaction is wrong or something.
It has to be $mysqli->begin_transaction(); on the connection not the statement. With a transaction you want to do more than one single statement.
http://php.net/manual/en/mysqli.begin-transaction.php
I can't figure this out. This is my variables:
$id = 1;
$exp = 1;
$energy = 1;
$payout = rand ( 100 , 300 );
here is the query
$sql = 'update players set ' .
'exp = exp + :exp, ' .
'energy = energy - :energy, ' .
'cash = cash + :cash ' .
'where id = :id';
An example of this as a string would be:
update players set exp = exp + 1, energy = energy - 1, cash = cash + 170 where id = '1'
When I input this in phpmyadmin it works. Thats why I don't understand why this does not work:
try
{
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->bindParam(':exp', $exp, PDO::PARAM_INT);
$stmt->bindParam(':energy', $energy, PDO::PARAM_INT);
$stmt->bindParam(':cash', $payout, PDO::PARAM_INT);
$result = $stmt->execute();
$stmt->closeCursor();
}
catch (Exception $e)
{
die ($e->getMessage() );
}
if ( !$result )
{
trigger_error("mysql: " . $sql, E_USER_ERROR);
$data = array( "message" => T_gettext("Something went wrong."));
return json_encode( $data );
}
This results in a false $result = something wrong with query.
What have I done wrong? + how do I get a more detailed mysql error message from PDO?
Are you actually throwing exceptions from your connection for you to catch? Try this and see if you get any error messages:
$db = new PDO($connection_string);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);