I have a table in which there is one column named:
'eZip' (varbinary(5), null).
Now I am adding value from a web form like this:
cmd.Parameters.Add("#eZip", SqlDbType.VarBinary).Value = BitConverter.GetBytes(int.Parse(txtZip.Text.ToString()));
Its working but instead of putting a valid zip code, it is inserting this into my column:
<Binary data>
What I am doing wrong here?
I don't think you are doing anything wrong per-se. if you define the field as varbinary you will always see "Binary Data" in SQL Server's management tools, regardless of the data.
Are you sure you don't want just CHAR(n) OR VARCHAR(n) for the zip code?
If you can't change the data type of that column, all you need to do is convert the value when you get the data back out. As recommended by others, you should at least change your code to assume that the five bytes are characters, not integers.
Insert the value:
cmd.Parameters.Add("#eZip", SqlDbType.VarBinary).Value = System.Text.Encoding.ASCII.GetBytes(txtZip.Text.ToString());
Retrieve the value in SSMS tools:
SELECT CONVERT(VARCHAR(5), [eZip]) AS [eZip] FROM #zip_table;
Retrieve the value from a DataRow dr in C#:
System.Text.Encoding.ASCII.GetString(dr["eZip"]);
If you can change the column to a CHAR(5) or VARCHAR(5), then no conversion will be necessary.
Related
Is there a way to get the actual encoded string saved in the Database of column with DataType Bytea. Because when the record is fetched in C# it returns as System.Byte[] which I don't want. I want the data which is saved in that column
E'\\\142\\\247\\\ and so on till the data ends.
I will appreciate your support
When I am querying the data through
SELECT tpl::TEXT from Cards where ecode="xyz";
I get the following error
Error: Cannot cast type bytea to text
Line1: Select tpl::TEXT from cards
Thank you
Like this
As you see that the Bytea column is showing System.Byte[] which was overwritten by my application because the code in C# stores the data in the DataTable column as System.Byte[] while updating the data I didn't decode it and update it .
I am using Navicat premium when I query data it shows me the result when I right click on the grid result and copy as insert statement it shows me two result for different rows
like this
INSERT INTO "public"."cards" ("ecode", "tpl") VALUES ('4210149888659', E'System.Byte[]');
INSERT INTO "public"."cards" ("ecode", "tpl") VALUES('3650257637661',E '\\247\\377\\001\\021\\340\\000\\230\\000\\002U\\000e\\000\\362\\000\\002-\\000\\253\\000p\\000\\002\\207\\000~\\000g\\000\\002\\215\\000{\\000\\317\\000\\002\\334\\000h\\000\\222\\000\\001|\\000\\004\\001U\\000\\002\\202\\000K\\000\\201\\000\\001\\000\\000\\204\\000\\241\\000\\001w\\000\\213\\000\\305\\000\\002\\021\\000V\\000\\237\\000\\002L\\001=\\001\\364\\000\\001X\\001"\\001\\313\\000\\002J\\000\\010\\001\\324\\000\\001\\370\\000\\037\\001J\\000\\002;\\0017\\000\\202\\000\\002\\300\\000\\317\\0007\\000\\002\\215\\000[\\000\\004\\011\\017\\007\\012\\005\\015\\014\\006\\016\\012\\007\\010\\005\\005\\007\\011\\010\\001\\004\\012\\017\\002\\003\\010\\012\\004\\010\\005\\003\\013\\014\\005\\017\\007\\003\\010\\003\\001\\011\\004\\012\\006\\020\\011\\005\\013\\015\\010\\002\\004\\005\\010\\007\\011\\012\\000\\002\\002\\020\\012\\003\\015\\000\\005\\002\\017\\003\\000\\006\\016\\020\\010\\017\\014\\000\\001\\012\\001\\010\\011\\002\\004\\007\\010\\000\\002\\006\\011\\007\\003\\020\\011\\003\\001\\005\\011\\000\\007\\002\\012\\002\\000\\020\\000\\016\\004\\017\\004\\003\\011\\017\\000\\003\\004\\000\\001\\007\\017\\002\\001\\017\\014\\006\\002\\016\\015\\011\\015\\006\\014\\016\\010\\020\\013\\000\\003\\006\\015\\002\\005\\020\\015\\016\\015\\004\\001\\003\\015\\010\\010\\006\\014\\002\\007\\020\\014\\011\\001\\000\\014\\010\\003\\016\\001\\015\\017\\020\\013\\006\\013\\016\\013\\011\\001\\014\\013\\004\\013\\002\\013\\001\\000'
);
You can't just convert it because PostgreSQL can't guarantee it can be converted safely. The best you can do is to convert the escaped form into a string and that's not what you probably want. Keep in mind that since bytea is binary data there is no way that PostgreSQL can be sure that the string that comes out will be legit. You could have embedded nulls in a UTF-8 string, for example, which could cause some fun with buffer overruns if you aren't careful.
This is the sort of thing that should be done in the client-side and you should assume that the data is binary, and not necessarily a valid string. If you want to store strings, store text fields, not bytea.
I am working on a C# project that gathers data from different sources and stores the data in a SQL Server database. I sometimes get String or binary data would be truncated. error which is very annoying. I want to determine which column causes this error and log it. Is there another way than checking parameter lengths?
What I did is if the column is varchar(50), checking if data length is greater than 50. I feel like this is like a walkaround and wonder if there is any other neat solution.
Edit
if(data1.Length>50) logIt("col1, data1, condition");
else if(data2.Length>80) logIt("col2, data2, condition");
else {
SqlParameter p1 = (new SqlParameter("#p1", DbType.String));
p1.Value = string.IsNullOrEmpty(data1) ? SqlString.Null : (object)data1;
s1.Parameters.Add(p1);
SqlParameter p2 = (new SqlParameter("#p2", DbType.String));
p2.Value = string.IsNullOrEmpty(data2) ? SqlString.Null : (object)data2;
s1.Parameters.Add(p2);
s1.ExecuteNonQuery("UPDATE mytable SET col1=#p1,col2=#p2 WHERE condition=#condition");
}
void logIt(string p){
using (StreamWriter writer = new StreamWriter("log.txt"))
{
writer.WriteLine("Caused by:"+ p);
writer.WriteLine(DateTime.Now);
writer.WriteLine("--------------------------------------------");
}
}
Personally I would always check all of my parameters against the table that contains the data they will be used in. If the table says varchar (50) my parameter should be no longer than 50. I never write a stored proc without doing this and I presume you can simlarly limit parameter defintion on the c# side. Don't allow a user to type in more information than your table field can accept.
If you are pulling data from other databases or Excel spreadsheets, then you may have a differnt set of problems.
First you need to examine the incoming data carefully and determine if the column size you currently have is too small for the needed content. I find often when the data is too large, the information in the field is garbage and should be thrown out (things like notes about a contact being placed in the email field for instance instead of an email). You may even want to consider if you shoud be validating the input data in some fields.
If you need to keep the size and you aren't concerned about losing the extra characters, then you need to cast the data to the correct size before inserting it into your database or you need to create an exception process that will pull out the records which cannot be sent to the database into an exception table and return them to the people who own the orginal data to be fixed.
As you mentioned, In one of the INSERT statements you are attempting to insert a too long string into a string (varchar (50)) column.
You have to increase the column size to 50+ or 100, to fix the issue. To find which column is causing this issue is put some logs or run SQL Profiler or Enable All exceptions from VS -> Debug Menu -> Exceptions (Check all exceptions).
I'm using a query in C#. I'm printing out data from a database.
Its number of columns is about 200 and the first column's type is TIMESTAMP.
Other types don't have a problem being printed out. Only TIMESTAMP does.
Someone said I can use TIMESTAMP to get TO_CHAR(COLUMN_NAME, 'YYYYHHDD')
I want to show all of database. But if I want, I should type all of column.
This way newly created columns aren't shown.
I want to use query like this, but it doesn`t work:
SELECT TO_CHAR(TIME, 'HHMMSS'), * FROM DATAS
Please help me with this query.
The following works for me:
SELECT CONVERT(numeric(20,0), stamp + 0) FROM ...
This is where "stamp" is timestamp column.
Assuming you are using SQL Server, you have to read the timestamp value as a byte array and convert it to string. The SQL Server Data Type Mappings on MSDN show that Timestamp maps to Byte[] and can be accessed by the GetSqlBinary or GetBytes methods.
The mapping also shows that timestamp is actually a row version number that changes automatically each time a row is modified. It has nothing to do with time. It's just an incrementing 8 byte number. This number has no meaning for end-users and there is probably no point in showing it anywhere.
If you still want to display it, you can convert the timestamp bytes to an Int64 type using the BitConverter.ToInt64 method.
This might seem an easy question for some, but I am struggling with it.
I am trying to use SQLDataReader.GetFieldType to check if a certain field is an Image field. Lets assume the first field of the result set is an Image field, if I do:
reader.GetFieldType(0).ToString;
I get System.Byte[] But is this the correct way to check for it? I really don't like:
if (reader.GetFieldType(0).ToString="System.Byte[]")
Is there a better way?
Thanks,
AJ
You could always shorten it a bit:
if(reader.GetFieldType(0) == typeof(byte[]));
Unfortunately there's no direct mapping from an image field in SQL Server to a .NET CLR type...which is why you get a byte array.
You might want to add further checking to make sure that the byte array being returned is actually an image (byte arrays are used for image, binary, varbinary, and rowversion columns as well).
You can check the type mappings at:
MSDN - Mapping CLR Parameter Data
It's preferable to use the Type.IsAssignableFrom method instead of looking at the type name itself.
Type fieldType = reader.GetFieldType(0);
bool isImageField = typeof(byte[]).IsAssignableFrom(fieldType);
This gives you some measure of compile-time safety.
Note: This doesn't actually guarantee that the field will contain images - any form of binary data can be stored in image/binary/varbinary fields, so the only way to see if it is truly an image is to read the value and try loading it as one. But you can use this to check if the field is a binary field.
An alternative way could be to use the SqlDataReader.GetSchemaTable method. This will return a datatable containing the schema of the resultset, and makes available the actual datatype from the db - e.g. the DataTypeName column of the schema table returned will be the actual SQL Server datatype like varchar, and the ProviderSpecificDataType column will be a System.Data.SqlType
e.g.
DataTable dataSchema = reader.GetSchemaTable();
// dataSchema.Rows[0]["DataTypeName"] would return the sql server
// data type name for the first column in the resultset.
You might have to check for the first bytes to see if they make an image header. Otherwise, you might deal with an audio file, for instance. So a byte array doesn't necessarily represent an image.
I am using C# & MYSQL to develop a desktop application.
In one of my form I have a DataGridView (dgvBookings) and in my database table I have a table tblBookings which contains a field specialization of type BLOB.
I am selecting data with following query,
SELECT * FROM tblBookings WHERE IsActive=1;
and then binding the data with DataGridView as,
dgvBookings.DataSource = ds.Tables["allbookings"];
BUT after binding the data in gridview it shows Byte[] Array value for all rows of column specialization which is of BLOB type.
How yo solve this problem, I want the data in String format, whatever is written in that column should be show as it is there in the grid.
You'll have to convert the byte array to a string before using the DataSet:
DataTable allBookings = ds.Tables["allbookings"];
DataColumn column = allBookings.Columns.Add("NotABlobAnyMore", typeof(string));
foreach (DataRow row in allBookings.Rows) {
row[column] = Encoding.Unicode.GetString((byte[])row["specialization"]);
}
dgvBookings.DataSource = allBookings ;
In the sample I'm using Unicode, but you should use whatever encoding was used to generate the byte array (blob).
If you are going to allow updates on the new column, you'll have to convert the string back to an array of bytes (in the old column) before sending the data back to the database.
Sink the CellFormatting event and cast the byte array to a String, or cast the BLOB to a character type in your SQL query.
Well, the inherent problem with a BLOB is that it... isn't text. It is binary. It could be an image (jpg etc), an exe, or it could be text... but in which encoding? UTF8? Not simple. If it was a CLOB I'd hope it works OK - but otherwise I would fully anticipate that you'd have to parse the BLOB manually, otherwise how would it be interpreted?
For an arbitrary BLOB, the closest I can think of is to just show something like the hex... but with DataTable even that is a challenge. You could do it for a class via a TypeConverter...