I’m trying to update a value in a MS Access DB (*.mdb) using OleDB in C#. Nothing fancy, except that I need to choose the row by an binary value, a VARBINARY(4).
Naively I thought UPDATE MYTABLE SET VALUE= 'new' WHERE BINVALUE=01020304; would work. But is does not.
Alternative tries were:
UPDATE MYTABLE SET VALUE= 'new' WHERE BINVALUE='01020304';
UPDATE MYTABLE SET VALUE= 'new' WHERE BINVALUE='0x01020304';
UPDATE MYTABLE SET VALUE= 'new' WHERE BINVALUE=0x01020304;
UPDATE MYTABLE SET VALUE= 'new' WHERE BINVALUE=CAST('01020304' as VARBINARY);
UPDATE MYTABLE SET VALUE= 'new' WHERE BINVALUE=CAST(01020304 as VARBINARY);
UPDATE MYTABLE SET VALUE= 'new' WHERE BINVALUE=CAST('01020304' as VARBINARY(4));
UPDATE MYTABLE SET VALUE= 'new' WHERE BINVALUE=CAST(01020304 as VARBINARY(4));
UPDATE MYTABLE SET VALUE= 'new' WHERE BINVALUE=CONVERT(varbinary(4),'01020304');
UPDATE MYTABLE SET VALUE= 'new' WHERE CAST(BINVALUE as VARCHAR(MAX)) = CAST('01020304' as VARCHAR(MAX));
UPDATE MYTABLE SET VALUE= 'new' WHERE CAST(BINVALUE as VARCHAR(MAX)) = CAST(01020304 as VARCHAR(MAX));
UPDATE MYTABLE SET VALUE= 'new' WHERE CONVERT(VARCHAR(MAX), BINVALUE) = CONVERT(VARCHAR(MAX), '01020304');
Using CAST results in a syntax error exception: missing operator.
Using CONVERT results in exception: Undefined function 'CONVERT' in expression.
The number of affected rows, in int result, is always zero. Using UPDATE MYTABLE SET VALUE= 'new' WHERE VALUE= old; works, but will sometimes hit more than one row.
While trying and failing to find a way to circumvent checking BINVALUEI noticed that you should not use Arabic commas (‘) around values in the WHERE clause. UPDATE MYTABLE SET VALUE= 'new' WHERE VALUE='old'; does NOT work while UPDATE MYTABLE SET VALUE= 'new' WHERE VALUE=old; works.
Using MS Query yields different results concerning the Arabic commas:
UPDATE MYTABLE SET VALUE='new' WHERE BINVALUE='01020304' executes, but has no effect.
UPDATE MYTABLE SET VALUE='new' WHERE BINVALUE=01020304 results in the error message “Syntax error in number in query expression ‘BINVALUE=01020304’.”
I can’t reproduce the error message “Column BINVALUE can’t be used in the criteria.” that I mentioned in the comments.
Using other columns to identify the desired row does not work, as most values are the same. Strangely enough BINVALUE serves as a the primary key.
On top of that, I am not allowed to change the DB schema, as a legacy application needs it exactly that way.
Based on gloomy.penguin’s input I assume there is a problem with the type casting/matching in the WHERE clause. This leads to the question how casting/conversion is done in OleDB or Access as the CAST operator appears to be known, but CONVERT is not. My guess would be that CAST has another syntax than in standard SQL for whatever reasons.
Any suggestions, how this update query can be made to work?
This is my stripped down example code:
static String ToHexString(Byte[] buffer)
{
String str;
str = BitConverter.ToString(buffer).Replace("-", string.Empty);
return (str);
}
...
String table = "MYTABLE";
String newvalue = "new";
Byte[] binvalue = { 1, 2, 3, 4 };
String providerStr= @"Provider=Microsoft.JET.OLEDB.4.0;" + @"data source=C:\myDB.mdb";
connection = new OleDbConnection(providerStr);
connection.Open();
String cmd = @"UPDATE " + table + " SET VALUE= '" + newvalue + "'"
+ " WHERE BINVALUE= '" + ToHexString(binvalue) + "'"
+ ";";
OleDbCommand command = new OleDbCommand(cmd, connection);
int result = command.ExecuteNonQuery();
connection.Close();
I figured out a way to solve the type casting issue I have been facing.
Apparently it is not possible using SQL syntax, but using a command with parameters.
Instead of:
I had to use:
Of course it would be cleaner to add all parameters this way. I omitted that to highlight the important part.
For further reading, an example of how to read and write images as binary data to a DB
on the C# helper blog.