Database query not returning full string - php

I'm saving a json string in the database which appears to be stored correctly in SQL Server, however when trying to fetch the data it only returns part of the json string.
I'm using PDO and json_encode to save the data.
The json string stored is approximately 1000 characters long, and the table field allows a length of 4096.
Fetching result:
$sql = "SELECT TOP 1 * FROM MyTable WHERE id = :id ORDER BY id DESC;";
$params = array(
":id" => $id
);
$sth = $this->db->prepare($sql);
$sth->execute($params);
$result = $sth->fetch(PDO::FETCH_ASSOC);
Saving result:
$json = json_encode($_POST);
$sql = "INSERT INTO MyTable(data) VALUES (:data);";
$params = array(
":data" => $data
);
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
Example Json stored in SQL Server:
{
"checkbox_1":"on",
"checkbox_2":"on",
"checkbox_3":"on",
"text_1":"my text",
"images":[
13685
],
"date":"11-11-2015"
}
Example Json returned:
{
"checkbox_1":"on",
"checkbox_2":"on",
"checkbox_3":"on",
"text_1
Update
It appears that the length of the string returned is always: 255
Could this be an SQL Server configuration or perhaps PDO?

Turns out that the protocol I was using to connect to SQL Server via PDO limits to 255 characters when fetching from a varchar column.
The workaround is to either change the column to TEXT or cast it to text in the SQL
SELECT CAST(my_column as TEXT)
ODBC query on MS SQL Server returning first 255 characters only in PHP PDO (FreeTDS)

Edit: Looks like OP's issue was something else, but I'll leave this below for future people that might have a similar issue, which can be solved by looking to TEXTSIZE.
Looks like the issue might be with the TEXTSIZE variable in SQL Server, which limits the length of returned text via PHP.
See what the current value is using
SELECT ##TEXTSIZE
and update it to a higher value using
SET TEXTSIZE 2147483647
Where the number is the max character count (defaults to/maxes out at the above value).
Here's the MSDN page on TEXTSIZE: https://msdn.microsoft.com/en-us/library/ms186238.aspx

Related

Update Oracle CLOB with PHP

I have an Oracle table with 1 field of datatype CLOB.
I want to replace the contents of the CLOB with a long string (over 4,000 characters).
Is OCI8 the easiest way to do this using PHP?
Regular sql would be simply something like this:
Update TableX
Set clobFieldX = 'my very long string'
Where keyField = 'value';
I've been googling for a simple example but can't find one that updates the CLOB with a 'where something = something' clause.
http://php.net/manual/en/function.oci-new-descriptor.php has an example of an insert statement. I'll try it in a bit, but it is as simple as changing the insert example to an update example?
Side note: is OCI the best way to interact with Oracle with PHP? Is there is a friendlier library/extension?
This worked: function updateClob($groupId,$memberList,$conn) {
$sql = "UPDATE LP_GROUP SET MEMBER_EXPR_XML = EMPTY_CLOB() WHERE GROUP_ID = '$groupId' RETURNING MEMBER_EXPR_XML INTO :lob";
//echo $sql."\n";
$clob = OCINewDescriptor($conn, OCI_D_LOB);
$stmt = OCIParse($conn, $sql);
OCIBindByName($stmt, ':lob', &$clob, -1, OCI_B_CLOB);
OCIExecute($stmt,OCI_DEFAULT);
if($clob->save($memberList)){
OCICommit($conn);
echo $groupId." Updated"."\n";
}else{
echo $groupId." Problems: Couldn't upload Clob. This usually means the where condition had no match \n";
}
$clob->free();
OCIFreeStatement($stmt);
}

SQL not returning rows present in table correctly

I have an issue with a table in a database. There are three columns as follows:
Name (VARCHAR(25))
QText (TEXT)
AText (TEXT)
My query is run through PDO as:
SELECT `AText` FROM `Exam_QA_Data` WHERE `Name` = '$name' AND `QText` = '$question'
After processing it looks like this and obviously the length of the $question variable will change:
SELECT `AText` FROM `Exam_QA_Data` WHERE `Name` = 'ExamServerTestExam' AND `QText` = 'This is the first question'
From what I can see depending on the length of the string in place of $question, sometimes it will return a row, other times it returns nothing.
If the string is short (27 chars) then it returns the 'AText' content for that row, though if the string is long (106 chars) nothing if $question is a long string. I checked the entry in the database and the entire string is present, so the row is there exactly as it is being searched for.
I have also tried using:
SELECT `AText` FROM `Exam_QA_Data` WHERE `Name` = '$name' AND `QText` LIKE '%$question%'
Can't understand if this is a database issue or not and if so why? It appears to be a problem with the length of the input string.
Thank you very much.
So after some tests, I discovered that the search doesn't like a string that is over 80 characters long. In order to do this but still get the same result I input the string with a wildcard as shown in the following codeblock:
function grab_ans_given_ques($conn, $question, $examName){
// Split the string here into two parts and join with a wildcard (%)
$ques = substr($question, 0, 20)."%".substr($question, -20, strlen($question));
$sql = $conn->prepare("SELECT `AText` FROM `Exam_QA_Data` WHERE `Name` = '$examName' AND `QText` LIKE '%$ques%'");
$sql->execute();
Thank you all who gave some advice or tried to help with this!

How save binary data in SQL Server with PEAR

How do I do an insert into an SQL 'Image' field using the PEAR DB library and sql like this:
insert into MyTable (myBlob) values (BlobData)
where BlobData is obtained using file_get_contents and looks like this:
"BMN\x0\x0\x0\x0\x0\x0\x06\x0\x0\x0(\x0\x0\x0\x2\x0\x0\x0\x3\x0\x0\x0\x1\x0\x18\x0\x0\x0\x0\x0\x18\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0ÿÿÿÿÿÿ\x0\x0\x0\x0ÿÿÿÿ\x0\x0ÿÿÿÿÿÿ\x0\x0"
I get syntax errors, guessing I need to escape the data somehow. Php code:
$data = file_get_contents('c:\\temp\\test.bmp');
$sql = "insert into MyTable (myBlob) values ('".$data."'); //just using inline sql for now to get it working
$db->query($sql);
I found that using bin2hex and writing the binary data as a hex string works:
$FileDataBin = file_get_contents($myFile);
$FileDataHex = '0x'.bin2hex($FileDataBin);
$qry = 'update MyTable set SomeBinaryField = '.$FileDataHex.' where SomeOtherField=?';
$DB->query($qry, array('some data'));
Note the '0x' prefix and that there are no quotes around the data.

MySQL loose comparison on INT fields

I recently saw something in MySQL which I consider odd, however, I am unsure if it is MySQL doing this or PHP.
Basically I have this query using the PDO library:
SELECT * FROM users WHERE id=:id OR email=:id
Using the bound parameter of xxx#gmail.com as :id. It is able to find the record where email is NULL and id is 0. After some investigation I found out that this was because there was some lose casting being done that meant xxx#gmail.com was being casted as 0 (like in PHP) to compare with id. The id field is INT.
Is this MySQL or PHP? Is there a way to stop loose casting and comparisons from happening in MySQL using the PHP PDO driver?
If it matters my table is MyISAM.
Edit
The exact code being used is:
$result = database::getInstance()->query("
SELECT * FROM users WHERE partner_id = :id OR email = :id LIMIT 1",
array(':id'=>$id)
);
Whereby database is a singleton instance which routes queries to the PDO library. It does no alteration to the query except run it for me. I know this part works since it is unit tested and it works with every other query in the application, this is the only malfunctioning query.
And the code within the query function:
if($params===array()){
$command=$this->_connection->prepare($sql);
}else{
$paramCount=0;
// Then arguments have been supplied
foreach($params as $field => $param){
if(is_array($param)){
$values = $params[$field];
unset($params[$field]);
$fparams=array();
foreach($values as $value){
$fparams[]=$this->paramPrefix.$paramCount;
$params[$this->paramPrefix.$paramCount++]=$value;
}
$sql=str_replace($field,'('.implode(', ',$fparams).')',$sql);
}
}
$command=$this->_connection->prepare($sql);
}
$command->setFetchMode(PDO::FETCH_ASSOC);
foreach($params as $field=>$param)
$command->bindValue($field,$param);
$command->execute();
return $command;
Just run SELECT 'string' = 0; and that should answer your question.
(For further reference: it returns 1)
Ok try this. note the (string) cast if this works, PDO is using some type checking and recast in the function bindValue
$result = database::getInstance()->query("
SELECT * FROM users WHERE partner_id = :id OR email = :id LIMIT 1",
array(':id'=>((string)$id))
);

PHP ODBC_FETCH_INTO returns null for large nvarchar

I'm storing data in SQLServer 2008 using PHP.
The data type is nVarChar(Max).
Very large strings post and save correctly, however when I odbc_fetch_into, the values longer than 4104 characters place a null value in the array.
I can select left([Note], 4104) and it will return the left 4101 characters, but when I select left([Note], 4105), it places null into the array.
Is there something I need to do to my PHP array to make it accept larger values?
Or perhaps fetch the fields separately?
$SQL = "SELECT left([Note],4104) FROM [myTable] WHERE [myKey] = myVariable"; //Works for all strings!
//$SQL = "SELECT [Note] FROM [myTable] WHERE [myKey] = myVariable"; //Works for strings <= 4104 characters
$row = array();
$stuff = array();
$prep = odbc_prepare($conn, $SQL);
$ret = #odbc_execute($prep);
while (odbc_fetch_into($prep,$row)) {
array_push($stuff,$row);
}
echo json_encode($stuff);
UPDATE: I just did a var_dump on $stuff, and come to find out it has a lot of garbage after character #4104. In Firefox, lots of diamond/question-mark characters, along with remnants of the PHP source and previously-returned results.
Ok, I have a partial answer anyhow...
there's a parameter in PHP.ini called odbc.defaultlrl. That value will limit the return size of an odbc field.
Still not sure why all the gabage was there at the end. When I changed the field value from nvarchar(max) to varchar(max) or text, the garbage disappeared but the size limitation was still there.
My php.ini was set to 4096 - not sure how I was getting 4104 bytes out of it.

Categories