I am having trouble with using PHP PDO interface with Microsoft SQL Server. The problem is with converting PHP number values to use in functions of MS SQL Server. I use the following statement to delete certain records:
$sql = "DELETE FROM table WHERE SUBSTRING(attribute, 1, ?) = ?";
I prepare and execute this statement with code (a little shrinked):
$query = $pdo->prepare ($sql);
$query->execute (array (strlen ('Text'), 'Text'));
But the query always fails. The error is:
SQLSTATE[42000]: [Microsoft][SQL Server Native Client 11.0][SQL Server]Argument data type nvarchar is invalid for argument 3 of substring function.
I am assuming the number from strlen is not parsed into a number, but I don't know how to fix this (except to manually add into the query).
I have found these links, however not very helpful.
http://social.msdn.microsoft.com/Forums/en-US/sqldriverforphp/thread/0f09ac5e-62cd-4ccf-b2cb-848aad23811e
http://drupal.org/node/1169202
The guys on Drupal had same error, but they fixed it with recreating function with casts. Is there any other way to fix this?
Thanks.
Not sure if this will solve it, but try something like this
$length = strlen('Text');
$text = "Text";
$sql = "DELETE FROM table WHERE SUBSTRING(attribute, 1, :len) = :text";
$query = $pdo->prepare ($sql);
$query->bindParam(':len', $length, PDO::PARAM_INT);
$query->bindParam(':text', $text, PDO::PARAM_STR);
$query->execute();
Try:
$query = $pdo->prepare ($sql);
$query->execute (array ((int) strlen ('Text'), 'Text'));
Related
I want to bind Values to a SQL Statement using a PDO connection to an SQL Server via ODBC.
If I execute the statement without a parameter I get a result but if I want to bind a parameter to that sql I get a "Function sequence error" thrown back.
$fromDate = strval(date('Y-d-m'))." 00:00:00.000";
//works
$sql = "SELECT a.FromDate FROM Absence a WHERE a.FromDate > '".$fromDate."'";
$arrParams = [];
runStatement($sql, $arrParams);
//don't work
$sql = "SELECT a.FromDate FROM Absence a WHERE a.FromDate > :fromdate1";
$arrParams = [':fromdate1' => $fromDate];
runStatement($sql, $arrParams);
//thats how I bind the parameters
function runStatement($sql, $arrParams)
{
$stmt = $this->conn->prepare($sql);
foreach($arrParams as $key => $value)
{
$stmt -> bindValue($key, $value);
}
$stmt -> execute();
return $stmt -> fetchAll(PDO::FETCH_ASSOC);
}
I tried to bind the values with bindParam() but the error remains the same. On Sqlite and Ingres Database the bindValue() works fine for me.
I am using PHP 8.x and SQL Server 2012. Installing the php drivers for SQL doesn't work here.
Edit: I could narrow down the error to the date type. Because in the where clause I want to compare two dates.
When I try other statements without dates as binded params the statement works fine.
So the comparison of the datetype is the error here.
Somewhat new to odbc_prepare statements and am having an issue when trying to execute a stored procedure that requires datetime input parameters.
If I am to execute using odbc without using the prepared statement as displayed below I have no issue...
$dblink = db_connect();
$query = "EXEC dbo.[ProcedureName] '" . $dateinput . "'";
odbc_exec($dblink, $query);
Using the odbc_prepare I'm getting an error (only for procedures with DateTime inputs parameters). Example below...
function execute_db($dblink, $query, $params){
$n = sizeof($params);
for($i=0; $i<$n; $i++){
if($i != 0){
$query = $query . ', ?';
}
else{
$query = $query . ' ?';
}
}
$statement = odbc_prepare($dblink, $query);
odbc_execute($statement, $params);
return $statement;
}
$dblink = db_connect();
$query = "EXEC dbo.[ProcedureName]";
$params = array($dateinput);
$result = execute_db($dblink, $query, $params);
This returns the following error:
Warning: odbc_execute(): SQL error: [Microsoft][ODBC SQL Server
Driver]Invalid character value for cast specification, SQL state 22005
in SQLExecute
The date string I'm passing in is in 'mm/dd/yyyy' format and works fine without using prepare. Is there a workaround for this other than changing the stored procedure's input type?
Use the proper ODBC syntax for calling a procedure and use the proper syntax for date times and it might get you further. The call syntax is {call procname(arguments)}. The datetime syntax is {ts ''} - see Date, Time, and Timestamp Escape Sequences and ODBC Datetime Format
Sorry if this seems a really stupid question, but I'm struggling to get to grips with changing from Mysql to Mysqli and prepared statements.
So in mysql, I would have done this:
$q=('SELECT * FROM table WHERE field="'.$variable.'"');
$result = mysql_query($q);
I now know this is not good. So I now have the below:
$stmt = $mysqli->prepare('SELECT * FROM table WHERE field=? LIMIT 1');
$stmt->bind_param('s', $variable);
$stmt->execute();
Problem is that the query doesn't work. Say the ? is actually "tree". So the query becomes:
'SELECT * FROM table WHERE field=tree LIMIT 1'
If I tried to run that query in say phpmyadmin I get "Unknown column tree in where clause". Obviously if I put quotes around it then it works, hence the original query. So how can I get this to work if I can't use quotes, since then you are looking for the literal question mark?
For reference I am then using this code:
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$parameters[] = &$row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $parameters);
while ($stmt->fetch()) {
foreach($row as $key => $val) {
$x[$key] = $val;
}
$results[] = $x;
}
As I can't use get_result() which is very annoying. I have PHP version 5.4, and even the mysqlnd driver, but can't enable it as I'm on a VPS and my host says it might affect other sites on that server. Consequently what is actually just two lines in MySql is actually now something like 15 lines in the 'improved' mysqli. Great.
Any help would be appreciated!
This:
$stmt = $mysqli->prepare('SELECT * FROM table WHERE field=? LIMIT 1');
$stmt->bind_param('s', $variable);
is not equivalent to this:
SELECT * FROM table WHERE field=tree LIMIT 1
Prepared statement placeholders are not the same as copy and pasting in values. You are binding the value "tree" as a string here, the database will actually understand this. The ? is not simply being replaced by the bound value, the database understands the difference between your query structure with its placeholders and the values you're binding into them. Binding the parameter this way is equivalent to running:
SELECT * FROM table WHERE field='tree' LIMIT 1
Consequently what is actually just two lines in MySql is actually now something like 15 lines in the 'improved' mysqli. Great.
Mysqli is not intended to be used as is. It is but a building material for the higher level library. When used wisely, it can give you data in one line:
$data = $db->getAll('SELECT * FROM table WHERE field=?s', $variable);
(BTW, the same goes for the old mysql ext as well)
Here is a part of my insert code that troubles me:
$recepient="test#email.com";
$text="Please track: http://wwwapps.ups.com/WebTracking/processInputRequest?HTMLVersion=5.0&loc=en_US&Requester=UPSHome&tracknum=123456789&AgreeToTermsAndConditions=yes&ignore=&track.x=24&track.y=9";
$date="2013-05-03 08:12:20";
$through="mail";
$status=1;
$q = "INSERT INTO `messages` (`recepient`,`text`,`date`,`through`,`status`) VALUES('".mysql_real_escape_string($to)."','".mysql_real_escape_string($text)."','".date("Y-m-d H:i:s")."','".mysql_real_escape_string($rowuser['through'])."','".intval($status)."')";
try {$db->query($q);} catch(PDOException $ex) {echp" Error: ".$ex.);}
If I remove the link from the $text variable I can see the data added to the database. But in the way I need it to add with the link - the script stops not reporting any errors.
use PDO's powerful prepared statements:
$q = "INSERT INTO messages (recepient,text,date,through,status) ";
$q .= "VALUES (:to,:text,:date,:through,:status)";
$dbinsert = $db->prepare($q);
$dbinsert->execute(array(
':to' => $recipient,
':text' => $text,
':date' => $date,
':through' => $through,
':status' => $status));
This should do it.
Let PDO take care of escaping.
It would appear that you're mixing database libraries, or have wrapped things yourself.
If you're using something like mysqli or PDO for the ->query() call, then mysql_real_escape_string() will NOT work. m_r_e_s() requires an active connection to the DB to operate. Connections established in mysql, mysqli, and PDO are NOT shareable between the libraries.
That means your m_r_e_s() calls will returning a boolean FALSE for failure, and your query will actually look like:
$q = "INSERT .... VAALUES ('', '', '', etc...)";
What's the size of the text column in the database? It's mostly not the reason but I've noticed that your $text is 190 char long.
The problem is with the "?" sign in the $text variable. It is being treated as a placeholder when it is put into the query, and the $db->query expects an array of variables.
The solution is to use a placeholder instead of a $text variable and submit $text variable as params:
$ar[0]=$text;
$q = "INSERT INTO `messages` (`recepient`,`text`,`date`,`through`,`status`)";
$q.= " VALUES('".$to."',?,'".date("Y-m-d H:i:s")."','".$through."',".$status.")";
$db->query($q,$ar);
I'm trying to run a very simple Oracle procedure from PHP, using the following statement:
$sql = 'exec procedureName(param1, param2)';
$sql = oci_parse($connection, $sql); oci_execute($sql);
Running this in Oracle SQL developer returns a successful 'anonymous block completed' message, but running this via PHP returns an 'ORA-00900: invalid SQL statement' error.
Is there anyway to run this procedure from PHP? Many thanks
Looking a little deeper, I think you'll need to put your procedure call inside a PL/SQL BEGIN-END pair, as in:
$sql = 'BEGIN procedureName(:param1, :param2); END;';
$stmt_id = oci_parse($connection, $sql);
oci_bind_by_name($stmt_id, ':param1', $value1);
oci_bind_by_name($stmt_id, ':param2', $value2);
oci_execute($stmt_id);
You'll need to edit the above to use whatever variable names are appropriate in the calls to oci_bind_by_name.
Also note that the presence of semi-colons in the SQL string is important.
Share and enjoy.
$sql = 'BEGIN procedureName(:param1, :param2); END;';
$stmt_id = oci_parse($connection, $sql);
oci_execute($stmt_id);