I'm having problems trying to run a stored procedure on MSSQL2000 using PHP PDO. I've tried all the combinations, but cant get any results apart from Invalid cursor state error.
The procedure is inside a database that is used by another application. I'm just reaching inside it to pull information out to display on PHP. So modifying the stored procedure (even to instead that SET NOCOUNT ON) is a no-no.
The stored procedure takes two arguments - a start and end date. There is also a RETURN_VALUE parameter.
I can run the following command in the SQL Query Analyzer and dumps rows of data fine:
EXEC [availability_enquiry] '08-24-2015 0:0:0.000', '08-26-2015 0:0:0.000'
Seems pretty straight forward, but when I try to code it and run it, I get nothin:
$dbConn = null;
$connectionString = sprintf('%s:Driver=%s;Server=%s;Database=%s;TrustedConnection=yes;', 'odbc', '{SQL Server Native Client 10.0}', 'mypc', 'testdb');
$dbConn = new PDO($connectionString, 'root', '123qew');
$dbConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "EXEC [availability_enquiry] '08-24-2015 0:0:0.000', '08-26-2015 0:0:0.000'";
$stmt = $dbConn->query($sql, PDO::FETCH_ASSOC);
$data = $stmt->fetch();
print_r($data);
I get an PDO Expection: 'Invalid cursor state' on the $stmt->fetch() line.
$stmt = $dbConn->prepare($sql);
$stmt->execute();
$data = $stmt->fetch();
print_r($data);
Still get an PDO Expection: 'Invalid cursor state'. Must be something to do with the fetch. Try something else:
$data = array();
do {
$results[count($results)] = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
while($stmt->nextRowset());
Still nothing!? Any ideas?
UPDATE1:
Tried another method:
$sql = "{CALL availability_enquiry (:startdate, :enddate)}";
$stmt = $dbConn->prepare($sql);
$startdate = "2015-08-24T00:00:00";
$enddate = "2015-08-26T00:00:00";
$stmt->execute(array(
':startdate'=>$startdate,
':enddate'=>$enddate
));
$data = $stmt->fetch();
print_r($data);
Also tried it as:
$startdate = "2015-08-24T00:00:00";
$stmt->bindParam(':startdate', $startdate, PDO::PARAM_STR);
$enddate = "2015-08-26T00:00:00";
$stmt->bindParam(':enddate', $enddate, PDO::PARAM_STR);
$stmt->execute();
But both give me an 'Invalid character value for cast specification' error message. Tried it with my own and the newly suggested date format.
If I use the same format of the date that is inside the table that the stored procedure uses:
$startdate = "2015-08-11 09:42:18.890";
I get an 'Invalid cursor state' error message. I'm hoping this is one step closer?
Related
I'm trying to execute a stored procedure on SQL Server using PDO. Everything runs fine, but when I try to read the output parameter (whose type is UNIQUEIDENTIFIER) the only thing I get is a NULL.
I've tried running my script on Debian 9 with PHP 7.0 and Ubuntu 18.10 with PHP 7.2 and changing the PDO type of my parameter, with no success.
$order_uid = null;
$sql = "EXEC spInsertOrder ?, ?, ?, ?...";
$stmt = $db->prepare($sql);
$stmt->bindParam(29, $order_uid, PDO::PARAM_INPUT_OUTPUT | PDO::PARAM_STR, 50);
if ($stmt->execute() === false) {
echo $stmt->errorCode();
print_r($stmt->errorInfo());
}
I expect to get the UUID that SQL Server emits, instead this error raises:
Fatal error: Uncaught PDOException: SQLSTATE[IMSSP]: An invalid type
for parameter 5 was specified. Only booleans, integers, floating point
numbers, strings, and streams may be used as parameters.
Before you read the value of your OUTPUT parameter, you need to consider the following:
If your stored procedure executes SELECT statements, you need to consume all results with PDOStatement::nextRowset, before accessing the value of your output parameter.
If your statement executes INSERT or UPDATE statements, put SET NOCOUNT ON as first line in your procedure to stop SQL Server to return the count of the affected rows as a resultset.
set your PHP variable to null.
Working example (tested with PHP 7.1.12 and PHP Driver for SQL Server (PDO) 4.3.0+9904):
T-SQL:
CREATE PROCEDURE [dbo].[sp_UID]
#id UNIQUEIDENTIFIER OUTPUT
AS BEGIN
SET NOCOUNT ON
SET #id = NEWID()
END
PHP:
<?php
# Connection info
$server = 'server\instance,port';
$database = 'database';
$uid = 'uid';
$pwd = 'pdw';
# Connection
try {
$dbh = new PDO("sqlsrv:server=$server;Database=$database", $uid, $pwd);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch( PDOException $e ) {
die("Error connecting to SQL Server. ".$e->getMessage());
}
# Stored procedure
try {
$sql = "{CALL sp_UID(?)}";
$uid = null;
$stmt = $dbh->prepare($sql);
$stmt->bindParam(1, $uid, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 36);
$stmt->execute();
// If your procedure returns result set, you need to fetch result and then get the value for your output parameter
/*
do {
while ($row = $stmt->fetch( PDO::FETCH_ASSOC )) {
}
} while ($stmt->nextRowset());
*/
} catch( PDOException $e ) {
die( "Error executing stored procedure: ".$e->getMessage());
}
$stmt = null;
# End
$dbh = null;
echo $uid;
?>
Output:
F689A035-C3DB-4D4E-88FB-52F5DA133FA8
I have hard time trying to do a simple insert into my sqlite3 db using php7.0
This code prints result correctly, so SELECT's work
$dbconn = new PDO('sqlite:/home/rooter/Desktop/XSS/db/ex1');
$stmtinit = $dbconn->prepare("select count() from tokens;");
$stmtinit->execute();
$rows = $stmtinit->fetch(PDO::FETCH_BOTH);
$tks = $rows[0];
print "tokens_size:".$tks;
But code below doesn't do anything and doesn't throw any error/warning/notice. Table tokens has unchanged size.
$dbconn = new PDO('sqlite:/home/rooter/Desktop/XSS/db/ex1');
$stmt = $dbconn->prepare("insert into tokens(user, token) values ('plaintxt','plaintxt')");
$stmt->execute();
If i try to do that insert manually in db, it works properly.
Following advice from Fred -ii- i turned error mode on
$dbconn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Which resulted in message: "attempt to write a readonly database". That happened because when I was creating database I was root.
A few months ago, my Ubuntu package auto-updated PHP from 7.0.8 to 7.0.13, at which point my script for updating photos stored on a SQL database started failing. I got around this by reinstalling 7.0.8. Last month, I was again auto-updated to 7.0.15 and my script failed again.
My script writes a jpg image to a MS-SQL database, using PDO & FreeTDS, plus Large Objects (LOB) to handle the photo. I emphasise that it worked up to PHP version 7.0.8. The following is a test script isolating my problem.
<?php
$dsn = 'dblib:dbname=photos;host=gary';
$id = 693925;
$dbh = new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$photo = file_get_contents("coco.jpg");
$query = "UPDATE photo_table SET photo = :photo WHERE id = :id";
$stmt = $dbh->prepare($query);
$stmt->bindValue(":photo", $photo, PDO::PARAM_LOB);
$stmt->bindValue(":id", $id, PDO::PARAM_INT);
$stmt->execute();
}
}
catch (PDOException $e) {
echo $e->getMessage();
}
The result is an "Incorrect syntax" error!?
SQLSTATE[HY000]: General error:
102 Incorrect syntax near '����'.[102] (severity 15) [(null)]
Using the latest available PHP version 7.0.15, reading from the database works, including reading the photo as a Large Object. There is no problem writing every other field to the database, it only fails on my image.
Despite searching over the last few weeks, I still have to find someone else reporting the same problem.
I am after any advice, either a change to the code, or some configuration settings to allow LOBs to work again.
I suggest you use bindParam instead of bindValue always because in bindParam
Unlike PDOStatement::bindValue(), the variable is bound as a
reference and will only be evaluated at the time that
PDOStatement::execute() is called.
$photo = file_get_contents("coco.jpg");//change this to below
$photo = fopen($_FILES['file']['tmp_name'], 'rb');
$query = "UPDATE photo_table SET photo = :photo WHERE id = :id";
$stmt = $dbh->prepare($query);
$stmt->bindValue(":photo", $photo, PDO::PARAM_LOB);//change to this below
$stmt->bindParam(":photo", $photo, PDO::PARAM_LOB);
$stmt->bindValue(":id", $id, PDO::PARAM_INT);//change this to below
$stmt->bindParam(":id", $id, PDO::PARAM_INT);
This is just only suggestions check here...... http://php.net/manual/en/pdo.lobs.php & http://www.php.net/manual/en/pdostatement.bindparam.php#refsect1-pdostatement.bindparam-description
My solution/workaround was to convert the binary from the image into hexadecimal representation before sending the data to SQL.
$photo = bin2hex(file_get_contents("coco.jpg"));
converting it back again during the SQL statement.
$query =
"UPDATE photo_table SET photo=CONVERT(varbinary(max), :photo, 2) WHERE id = :id";
im trying to use mysqli with bind_result but all i get is null values. My $stmt
number of rows is greater than 0 so i do have some data in it.
I dont realy understand what value should come into bind_result
I have read at the manual http://php.net/manual/en/mysqli-stmt.bind-result.php
And they dont explain what should i put in the bind_result.
Should i put there the column names? if yes, as strings? how do i get my wanted values?
Here is my code thanks for helping:
$sql = "SELECT * FROM comments WHERE workout_name = ? AND user = ?";
$stmt = $mysqli->prepare($sql) or trigger_error($mysqli->error."[$sql]");
$stmt->bind_param('ss', $workout_name, $user);
$workout_name = "rytg";
$user = "tomer";
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($comment, $commented_user);
if($stmt->num_rows > 0)
{
$response["workouts"] = array();
while ($stmt->fetch())
{
// temp user array
$workouts = array();
$workouts["comment"] = $comment;
$workouts["user"] = $commented_user;
// push single product into final response array
array_push($response["workouts"], $workouts);
}
}
Your only problem is insufficient error reporting
error_reporting(E_ALL);
ini_set('display_errors',1);
Just add these lines at the top of your code and you will be immediately informed of the exact problem with your code.
Note that on the production server you have to turn displaying errors off and logging on
I don't have a working PHP installation next to me at the moment, so I can't verify it, but I believe you might have to bind both parameters and result before you execute the query, like so:
$workout_name = "rytg";
$user = "tomer";
$stmt = $mysqli->prepare($sql) or trigger_error($mysqli->error."[$sql]");
$stmt->bind_param('ss', $workout_name, $user);
$stmt->bind_result($comment, $commented_user);
$stmt->execute();
I'm not too sure about store_result() either. I don't recall having to use it while retrieving the results, so you might want to try running your code without it and see what happens.
I just started using PHP PDO with MySQL stored procedures and I have problem with how to get OUT parameters from the procedure call. I looked at many similar stackoverflow topics, but unfortunately I couldn't find a way to resolve my issue :|
Here are the details:
The procedure takes 1 input parameter and has 2 mandatory output parameters, and returns result status in them.
This is how I call it:
$input = 5;
$mydb = new PDO("mysql:host=localhost;dbname=mydb", "user", "pass");
$proc = $mydb->prepare("CALL proc_name($input, #o_code, #o_message)");
$proc->execute();
The procedure returns INT in the #o_code parameter and STRING in the #o_message parameter.
If it's called from CLI, and after the call I write in the CLI
select #o_code, #o_message;
everything is OK, that is I am able to see the values returned in these OUT parameters.
However I cannot do it from PHP code - for some reason I always get FALSE results. The procedure do it's job correctly, but I just cannot get its results.
I tried the following methods to get the values, right after I make the call described above:
$output = $proc->fetch(PDO::FETCH_ASSOC); // also with PDO:FETCH_OBJ
$output = $mydb->query("select #o_code, #o_message");
$output = $mydb->query("select #o_code, #o_message")->fetch();
$output = $mydb->query("select #o_code, #o_message")->fetchColumn();
$output = $mydb->query("select #o_code, #o_message")->fetchAll();
but none of these return any result different from NULL or FALSE. I also tried with bindParam, but still could not make it work.
Thank you for any help on this issue and good day!
----- EDIT -----
Here is the code that I tried with bindParam, which still does not work:
$input = 5;
$proc = $mydb->prepare("CALL proc_name(?, ?, ?)");
$proc->bindParam(1, $input, PDO::PARAM_INT);
$proc->bindParam(2, $code, PDO::PARAM_INT);
$proc->bindParam(3, $message, PDO::PARAM_STR);
$proc->execute();
var_dump($code, $message); // NULL, NULL
The problem was that the first query that is calling the stored procedure is not considered as finished and closed, and PDO will not execute another query until the previous query is done.
The solution was to add $proc->closeCursor();
The whole working sample is:
$input = 5;
$mydb = new PDO("mysql:host=localhost;dbname=mydb", "user", "pass");
$proc = $mydb->prepare("CALL proc_name($input, #o_code, #o_message)");
$proc->execute();
$proc->closeCursor();
$output = $mydb->query("select #o_code, #o_message")->fetch(PDO::FETCH_ASSOC);
var_dump($output); // array('#o_code'=>value, 'o_message'=>value)