how to get the full data from nvarchar? - php

fetching a data from sql server 2000
type nvarchar with length 1500
when i try to print it using print_r or echo in php
the message gets cut off to 255 char, there is no error, and
in database the message is there, but i cant fetch them all
how do i fix this ?
example field message
i just use simple fetch function it work, just cant get the full data
$result = "some query here"
while($line = $VinDB->fetch_array($result)){
if (#$line["message"] != null)
{echo #$line["message"];}
}

If you are using the mssql extension, you have to consider either to change the original type of the column to TEXT/NTEXT, or to cast it to TEXT/NTEXT.
There is a bug in the old extension:
Note: Note to Windows Users:
Due to a limitation in the underlying API used by PHP (MS DBLib C API), the length of VARCHAR fields is limited to 255. If you need to store more data, use a TEXT field instead.
From: http://www.php.net/manual/en/function.mssql-field-length.php

I think you should try setting the data type to text or ntext. It might be an issue regarding the max character limit on nvarchar.

Related

Not receiving correct data from firebird database when using PHP

I have some very odd situation. I am making a query to a firebird database and there is mismatch with the result in PHP. In DB the result is just fine, but when it comes to PHP there are different values.
The query:
SELECT LIST(t."ID", ',') ID,t."Date", LIST(n."Name",',') Name
FROM "Tests" t
LEFT JOIN "Names of tests" n ON t."Name ID" = n."ID"
WHERE t."Locked" = 0
GROUP BY t."Date"
ORDER BY t."Date" DESC
Result in DB:
ID = 546,552 Date = 23.10.2015 Name = Математика (тест),География(тест)
Result in PHP:
ID => 0x0000000200000000,
Date => 2015-10-23,
Name => 0x0000000500000000
I am using "UTF-8" encoding when connecting to DB with ibase_connect() the database encoding is WIN1251.
The result type of LIST() is a blob, not a CHAR or VARCHAR. I don't use PHP myself, but I believe that the Firebird/Interbase driver for PHP requires you to explicitly request the blob.
The values you see for ID and Name are the blob ids that can be used to request the blobs.
You have two options:
Request the blob value using these blob ids, see ibase_blob_open and ibase_blob_get (afaik, you will need to do the correct byte to character conversion yourself)
Cast the value to a VARCHAR (eg CAST(LIST(t."ID", ',') AS VARCHAR(2048)) AS ID)
The downside of the second option is that if you can have really long results, then you also need to cast to a long VARCHAR, otherwise you get truncation errors; and unfortunately varchars are restricted to 32K-2 bytes (8191 characters for UTF8), and a row as a whole to 64K bytes.

How to display 'text' data correctly with Microsoft ODBC driver for Linux? Currently displaying as random characters

I am trying to display the contents of a field in a MS SQL database, the data type of which is 'text'. When I connect to the database with MS Excel on a PC the value looks something like:
Shipped on the: 18/10/12 Toll IPEC Connote Number: XXX XXX XXXX
When I connect to the database with PHP using the Microsoft ODBC driver for Linux, the output of the text field will display random characters, which are slightly different each time I run the exact same script. Here is what it output the last four times:
Xisep)!ØwXment.class.php))
5isep)!ment.class.php))
µ}isep)!Ø}ment.class.php))
t)!!Owner_IDt)Ø©Ø8
Not sure where it's getting the 'ment.class.php' bit from. That looks like the end of the name of one of my classes, but not one that is included in this particular script. Is the driver broken or what? All other data types (int, varchar, datetime etc) seem to display correctly, the problem only seems to happen with this one text field.
Here is the code:
<?php
require('ConnectWise.inc.php');
$config = new CW_Config;
// Connect to database
$dbcnx = odbc_connect("ConnectWise", $config->db_username, $config->db_password);
// Query database
$query = "select * from Billing_Log where Invoice_Number = '24011'";
$result = odbc_exec($dbcnx, $query);
while ($row = odbc_fetch_array($result)) {
echo $row['Top_Comment'] . "\n";
}
odbc_close($dbcnx);
Here is the output of my last few attempts:
\3ȶä!!¶äY!
öÈö§!!ö§Y!
&Èö×!!ö×Y!
Looks like you're getting an overflow. For some reason SQL is passing the length of your text field as 0, which to SQL means "long" but to PHP means "I dont know" and so PHP is showing whatever is in its memory at the location its expecting data (or something like that - any PHP experts care to explain?).
I've seen this with varchar(max) before but not text. (Converting to) Text is normally the way to fix it. So maybe I'm wrong.
Hope this is of some help. Im not a PHP developer, I just have to use it occasionally, and this sounds much like a painful experience I've gone through before :)

Store BLOB-like data in PostgreSQL

I recently switched from MySQL to PostgreSQL. I have one problem left however.
Previously, I would store small images in the BLOB format in MySQL.
PostgreSQL doesn't know such thing as a BLOB.
I tried using BYTEA field type instead. This actually inserts an large (hexadecimal?) string I guess, but now I'm stuck trying to get this string back to displaying an actual image in PHP..
Any ideas? Thanks in advance.
Here is a piece of code I use to save the image in the database:
$data = bin2hex(file_get_contents('php://input'));
if (!empty($data)) {
$sql = "UPDATE asset SET data = X'%s' WHERE uuid = '%s'";
$args = array($data, $asset_uuid);
}
psql (9.1.3) and php 5.3.6 are used
Bytea is a byte array. It's not a bit pattern. See section 4.2.1.5 of PostgreSQL Lexical Structure.
The correct way to enter bytea is '\x...' with hex values. So what you want is SET data = '\x%s'.
You might also want to look into prepared statements with pg_prepare.
Edit: I was able to insert a (text) file into a bytea with this:
$source = file_get_contents( 'hello.php' );
$insert = pg_prepare( $conn, '', 'insert into t (name, data) values($1,$2)' );
pg_execute( $conn, '', array( 'hello.php', $source ) );
3rd Edit: This works fine to insert the file into the database. However, the pgsql driver in PHP is quite impolite. The only way to retrieve the actual data back is using the old bytea escape mechanism, as detailed here: pg_unescape_bytea.
pg_query('SET bytea_output = "escape";');
$result = pg_query( 'select data from t' );
while ( $row = pg_fetch_row( $result ) ) {
echo pg_unescape_bytea( $row[0] );
}
I'm sorry about how annoying this is. The PostgreSQL interface in PHP can do with some major overhaul for binary values.
To insert bytea contents with the pg_* API, the binary value should always be run through the pg_escape_bytea() function, even if it's passed to the pg_execute or pg_query_params functions.
This is because the pg_* layer doesn't "know" that a particular parameter has binary contents, and it does not implement any real support for parameter types anyway. So the text representation must be used. It can either be in the escape form or the hex form, it doesn't matter to the PG server, and it's independant of the value of bytea_output, which is meaningful only for values read from the server.
Example:
$esc=pg_escape_bytea("\000\001\002");
pg_query_params('INSERT INTO some_table(some_col) VALUES($1)', array($esc));
To read bytea contents with the pg_* API, the value must be run through pg_unescape_bytea() after the fetch. Assuming the client library is not older than 9.0 (libq.so.5.3 or higher), it can decode the contents whether it's in hex form or escape form and it will autodetect it. Only with an older library would it be necessary to force bytea_output to escape for it to decode properly, either dynamically with SET or statically for the whole database (ALTER DATABASE SET bytea_output=escape) or in postgresql.conf for the whole instance.
Example:
$p=pg_query("SELECT some_col FROM some_table WHERE...");
$r=pg_fetch_array($p);
$contents = pg_unescape_bytea($r[0]);
Both answers posted here gave me some thoughts, but none were 100% of the answer.
So, I will explain in this answer what I did to get it to work.
When displaying the image, I used this:
header('Content-Type: image/jpeg');
$data = pack("H*", pg_unescape_bytea($data));
echo $data;
I'm running PHP 5.3.8, in PHP 5.4.0 it turns out you can use hex2bin instead of pack.
When adding the image to the database, I used this:
$data = pg_escape_bytea($data); // Escape input for PostgreSQL
$sql = "UPDATE asset SET data = '%s'WHERE uuid = '%s'";
I'm glad it is working now. Thank you both Daniel and Johann!

Why TEXT column returns only 4096 bytes?

I'm storing a long text with mssql_query();
And Using the field with datatype called 'text'.
I tried with different long strings by using str_repeat(), the page takes long time, but in the end submits the result.
When I retrieve the result however, I get only 4096 bytes nomatterwhat.
I tried to retrieve the value with management studio too, and it gets the same outcome.
It looks to me like a storing problem to me. Please advice something... I'm confused.
EDIT for these who asked, this is what I'm using:
function sql_escape($sql) {
/* De MagicQuotes */
$fix_str = stripslashes($sql);
$fix_str = str_replace("'","''",$sql);
$fix_str = str_replace("\0","[NULL]",$fix_str);
return "'".$fix_str."'";
}
$query=mssql_query('update prod_cat set htmlbottom='.sql_escape(str_repeat('\'choose_cat ', 122000)).
' where ID=1' );
$query=mssql_query('select htmlbottom from prod_cat where ID=1');
$a=mssql_fetch_assoc($query);
echo strlen($a['htmlbottom']);
Microsoft's PHP driver (for reference): http://www.microsoft.com/en-us/download/details.aspx?id=20098
But if you don't want to (or can't) change drivers, from this site:
You need to increase the maximum size of a text column to be returned from
SQL Server by PHP. You can do this with a simple SQL query:
SET TEXTSIZE 2147483647
Which you can run with the following PHP (best run just after you make a
connection).
mssql_query("SET TEXTSIZE 2147483647");
A better way to work around the issue is to change the "textlimit" and
"textsize" settings within php.ini, like so:
mssql.textlimit = 2147483647
mssql.textsize = 2147483647
Your MSSQL driver is truncating the text. If you can't change datatypes, drivers, etc., this should fix the issue for you.

MD5 Hashes not matching

I am trying to match a md5 has (generated through php) to its original value in a SQLExpress database.
I am using the following function in my SQL query
master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', 'ID'), 1, 0)
Where 'ID' is the field in the database.
However they both seem to return different values for the md5 hash. I have been using '12290' as a static value to test this.
php md5() returns: 0bd81786a8ec6ae9b22cbb3cb4d88179
The following SQL Statement returns the same output:
DECLARE #password VARCHAR(255)
SET #password = master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', '12290'), 1, 0)
SELECT #password
Yet when I run the following statement from the table:
SELECT ID, master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', CONVERT(NVARCHAR(255), ID)), 1, 0) AS temp
FROM Clients
ORDER BY ID ASC
The 'temp' value matching to the 'ID' value of 12290 returns: 1867dce5f1ee1ddb46ff0ccd1fc58e03
Any help on the matter would be much appreciated!
Thanks
Python helped me to help you.
>>> from hashlib import md5
>>> md5('1\x002\x002\x009\x000\x00').digest().encode('hex')
'1867dce5f1ee1ddb46ff0ccd1fc58e03'
NVARCHAR is Unicode type and it seems from the above experiment that '12990' is stored as UTF-16LE in your database: '1\02\09\09\00\0'.
Assuming that the data encoding in the PHP is UTF-8 data and you don't want to change the existing data in the database, this is how you can fix your PHP script:
<?php
$password = '12290';
$hash = md5(mb_convert_encoding($password, 'UTF-16LE', 'UTF-8')) . "\n";
echo $hash;
?>
Output:
susam#swift:~$ php utf16le-hash.php
1867dce5f1ee1ddb46ff0ccd1fc58e03
In case the data in PHP is in some other encoding such as ASCII, ISO-8859-1, etc. you can change the third argument to mb_convert_encoding accordingly. The list of all supported encodings is available at: http://www.php.net/manual/en/mbstring.supported-encodings.php
Also, see http://www.php.net/manual/en/function.mb-convert-encoding.php
I don't have SQL server to test this on, but the CONVERT command might be creating the NVARCHAR with 240-odd trailing blanks (as you have specified NVARCHAR(255))
Try setting the NVARCHAR to the length of the ID to test:
ARE #password VARCHAR(255)
SET #password = master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', CONVERT(NVARCHAR(5), '12290')), 1, 0)
SELECT #password
Try with different lengths in the CONVERT - is there any difference?
One of two things is most likely the problem:
Either the ID column in that row has a value not exactly equal to '12290' (e.g. extra whitespace)
Or the CONVERT function produces such a value
In any case, a standard debugging approach would be to use an SQL query to SELECT the string lengths of that ID field and the return value of CONVERT; if either is not equal to 5, you found the error.
Alternatively you can perform a dump of the table in question including data, and look at the generated INSERT statement to see what the database says the value in that column is.

Categories