Opening an Excel file in c# - c#

So there are a lot of questions regarding this method on SO, but none seem to answer my question. I firstly had an issue with the connectionstring (although it seems to work in other areas of my code correctly). This was resolved easily.
Now the issue is with a simple SELECT query via a OLEDBCommand (Text) that keeps popping up the following error?
"SELECT [Opportunity#],[BidManager],[Prob %],[Opportunity_Stage].[Opportunity_Status],[Term],[Sign Date] FROM [Sheet1$];"
No value given for one or more required parameters.
but their are no parameters????
Checked and double checked the columns names, but to no avail. Also tried removing the special characters from the column names, but still the same exception.

I'd suggest trying to run SELECT * FROM [Sheet1$] that way you'll know pretty certain if it's a column issue or an issue with the rest of the code.
Also, I can't check at the very moment, but are you sure there should be a ; after the select statement, isn't that just when you want to execute multiple statements?

OleDbCommand requires two parameters, the command string you are trying to execute and the OleDbConnection itself. Are you calling it correctly?
Dim myConnection As New OleDbConnection(myConnString)
OleDbCommand myCommand = new OleDbCommand(mySelectQuery,myConnection);

I've had this error with an OleDb command when my column names were incorrect.
"No value given for one or more required parameters."
I assume that the database interprets any columns names that it cannot find as parameters

Related

OleDb Update Query is not updating the database [duplicate]

This question already has answers here:
OleDbParameters and Parameter Names
(2 answers)
Closed 3 years ago.
I'm trying to update 4 columns in my database where the UID matches, the query runs fine with no errors output but the database remains unchanged. The database is fully closed and nothing else has it open except the code. I'm quite new to using databases in code so I'm completely stumped at trying to find the error here.
The update query code is as a follows:
conn.Open();
OleDbCommand UpdateUserCMD = new OleDbCommand("Update Accounts_Info Set Unique_ID=#Unique_ID, Last_Login_Date=#Last_Login_Date, Last_IP=#Last_IP, Last_MAC=#Last_MAC" + " Where Unique_ID=#Unique_ID", conn);
UpdateUserCMD.Parameters.AddWithValue("#Last_Login_Date", DateTime.Now.ToString("yyyy.MM.dd_hh:mm:ss"));
UpdateUserCMD.Parameters.AddWithValue("#Last_IP", GetIPAddress(Dns.GetHostName()).ToString());
UpdateUserCMD.Parameters.AddWithValue("#Last_MAC", GetMACAddress());
UpdateUserCMD.Parameters.AddWithValue("#Unique_ID", TempGUIDHolder);
UpdateUserCMD.ExecuteNonQuery();
conn.Close();
The connection string is as follows:
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=E:/A-Level/Development/A_Level_AI_Project/A_Level_AI_Project/resources/Accounts.accdb");
Other query's work fine so i don't think its the connection string at fault.
I think you should remove the part of your update query where you SET the unique id
Update Accounts_Info Set Unique_ID=#Unique_ID, Last_Login_Date ...
^^^^^^^^^^^^^^^^
don't put this in
Reason I say this is because I'm near certain that OLE does NOT support named parameters even though you've written them and it "seems to work" for other queries. OLE only supports positional parameters so the order of AddWithValue calls must match the order of parameter appearance in the query
because your query contains an extra Uniqueid parameter the order you've called AddWithValue, men's that your logindate is being assigned to the uid, your ip is assigned to the logon date, mac to ip. It shouldn't actually run, because there is no value provided for the 5th parameter.
If you're having trouble getting what I mean, change all the #parameter names in the query to ?
After you've sorted out the parameters, capture the return value from ExecuteNonQuery and it will tell you how many records were affected. If it's 0 then the where clause matched nothing; double check that the value in tempGuidHolder appears in the table
If you're catching and swallowing an exception (and I believe this code should cause an exception because not all parameters are filled), don't ;)

ORA-01036: illegal variable name/number when running query through C#

I am trying to use ALTER USER query for Oracle database using OracleCommand in C# in the following code. It creates the query if the values for Username and password are not empty strings. But I get an error "ORA-01036: illegal variable name/number" when ExecuteNonQuery() is executed.
string updateQuery = "ALTER USER :user IDENTIFIED BY :password";
connection = new OracleConnection(LoginPage.connectionString);
connection.Open();
OracleCommand cmd = new OracleCommand(updateQuery, connection);
cmd.Connection = connection;
for(int i=0;i<usersList.Count;i++)
{
if (!(selectedUsersArray[i].Equals("")) && !passwordArray[i].Equals(""))
{
OracleParameter userName = new OracleParameter();
userName.ParameterName = "user";
userName.Value = selectedUsersArray[i];
OracleParameter passwd = new OracleParameter();
passwd.ParameterName = "password";
passwd.Value = passwordArray[i];
cmd.Parameters.Add(userName);
cmd.Parameters.Add(passwd);
cmd.Prepare();
cmd.ExecuteNonQuery();
}
}
Could you please suggest what is wrong with my implementation?.
The root cause
In Oracle you have three kinds of SQL statements (and additionally there are PL/SQL blocks):
Statements in the Data Definiton Language (DDL). These statements modify the structure of the database. They begin usually with the verbs "ALTER" or "CREATE"
Statements in the Data Modification Langugage (DML). There statements modify the content inside of tables, leaving the structure of each table unmodified. These statements usually begin with "INSERT", "MERGE" or "DELETE".
Statements in what I call "query language" (there seems to be no canonical name for these). This statements start with the verb "SELECT".
Bind variables in Oracle are only allowed in some special places in DML and query statements. You are trying to use bind variables in a places where they are not allowed. Hence the error.
Solution
Build your statement without bind variables. Build the complete query string instead using string concatenation.
If you want to sanitize the input before concatenating the string, use the DBMS_ASSERT package.
Background
Bind variables can only be used when Oracle can build a query plan without knowing the value of the variable. For DDL statements, there is no query plan. Hence bind variables are not allowed.
In DML and query statements, bind variables are only allowed, when they are used inside a tuple (regarding the underlying set theory), i.e. when the value will be compared with the value in a table or when the value will be inserted in a table. They are not allowed to change the structure of the execution plan (e.g. to change the target table or to change the number of comparisons).
Just for others getting this error and looking for info on it, it is also thrown if you happen to pass a binding parameter and then never use it. I couldn't really find that stated clearly anywhere but had to prove it through trial and error.
I just spent several days checking parameters because I have to pass 60 to a stored procedure. It turns out that the one of the variable names (which I load into a list and pass to the Oracle Write method I created) had a space in the name at the end. When comparing to the variables in the stored procedure they were the same, but in the editor I used to compare them, I didnt notice the extra space. Drove me crazy for the last 4 days trying everything I could find, and changing even the .net Oracle driver. Just wanted to throw that out here so it can help someone else. We tend to concentrate on the characters and ignore the spaces. . .
You defined one oracleCommand but used it in 'for'.
it means you are adding parameter with the same name to one OracleCommand.
you should use cmd.Parameters.clear() to refresh your parameters.
for(int i=0;i<usersList.Count;i++)
{
if (!(selectedUsersArray[i].Equals("")) && !passwordArray[i].Equals(""))
{
cmd.Parameters.clear();//Add this line
OracleParameter userName = new OracleParameter();
userName.ParameterName = "user";
userName.Value = selectedUsersArray[i];
OracleParameter passwd = new OracleParameter();
passwd.ParameterName = "password";
passwd.Value = passwordArray[i];
cmd.Parameters.Add(userName);
cmd.Parameters.Add(passwd);
cmd.Prepare();
cmd.ExecuteNonQuery();
}
}
The Oracle error ORA-01036 means that the query uses an undefined variable somewhere. From the query we can determine which variables are in use, namely all that start with #. However, if you're inputting this into an advanced query, it's important to confirm that all variables have a matching input parameter, including the same case as in the variable name, if your Oracle database is Case Sensitive.
This error happens when you are also missing cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add(new OracleParameter("GUSERID ", OracleType.VarChar)).Value = userId;
I was having eight parameters and one was with space at the end as shown in the above code for "GUSERID ".Removed the space and everything started working .
I was having the same problem in an application that I was maintaining, among all the adjustments to prepare the environment, I also spent almost an hour banging my head with this error "ORA-01036: illegal variable name / number" until I found out that the application connection was pointed to an outdated database, so the application passed two more parameters to the outdated database procedure causing the error.
You cannot pass user/table name to pl/sql with a parameter. You can create a procedure and build sql and then execute immediately to achieve that.
I have faced same problem ... For the problem is like this, I am calling the PRC inside cpp program and my PRC taking 4 arguments but while calling I used only 1 arguments so this error came for me.
Begin Example_PRC(:1); End; // this cause the problem
Begin Example_PRC(:1,:2,:3,:4); End; // this is the solution
I had the same issue today when using Python module cx_Oracle. In my case, the root cause was an invalid variable name.
Example: SELECT * FROM DATA WHERE KEY IN (:_0, :_1, ...)
When I changed _0 to var0, it worked fine.
From this blog post, I found these rules for variable names:
Must start with a letter
Maximum size is limited to 30 letters
Cannot contain whitespace characters
Can contain dollar sign ('$'), underscore ('_') and hash sign ('#')
Is case-insensitive
I had the same problem, was learning connection to oracledb.
previous code-
SELECTALLCANDIDATES = "Select * from candidate_master";
data= await connection.execute(SELECTALLCANDIDATES, {autoCommit:true})
Removed the {autoCommit:true} and it started working fine.Correct code-
SELECTALLCANDIDATES = "Select * from candidate_master";
data= await connection.execute(SELECTALLCANDIDATES)
Still don't know why but it works.
Check your named variables match, I had the same problem, I had a spelling mistake/typo in one of my parameters

Escaping various characters in C# SQL from a variable

I'm working a C# form application that ties into an access database. Part of this database is outside of my control, specifically a part that contains strings with ", ), and other such characters. Needless to say, this is mucking up some queries as I need to use that column to select other pieces of data. This is just a desktop form application and the issue lies in an exporter function, so there's no concern over SQL injection or other such things. How do I tell this thing to ignore quotes and such in a query when I'm using a variable that may contain them and match that to what is stored in the Access database?
Well, an example would be that I've extracted several columns from a single row. One of them might be something like:
large (3-1/16" dia)
You get the idea. The quotes are breaking the query. I'm currently using OleDb to dig into the database and didn't have an issue until now. I'd rather not gut what I've currently done if it can be helped, at least not until I'm ready for a proper refactor.
This is actually not as big problem as you may see it: just do NOT handle SQL queries by building them as plain strings. Use SqlCommand class and use query parameters. This way, the SQL engine will escape everything properly for you, because it will know what is the code to be read directly, and what is the parameter's value to be escaped.
You are trying to protect against a SQL Inject attack; see https://www.owasp.org/index.php/SQL_Injection.
The easiest way to prevent these attacks is to use query parameters; http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter.aspx
var cmd = new SqlCommand("select * from someTable where id = #id");
cmd.Parameters.Add("#id", SqlDbType.Int).Value = theID;
At least for single quotes, adding another quote seems to work: '' becomes '.
Even though injection shouldn't be an issue, I would still look into using parameters. They are the simpler option at the end of the day as they avoid a number of unforeseen problems, injection being only one of them.
So as I read your question, you are building up a query as a string in C#, concatenating already queried column values, and the resulting string is either ceasing to be a string in C#, or it won't match stuff in the access db.
If the problem is in C#, I guess you'll need some sort of escaping function like
stringvar += escaped(columnvalue)
...
private static void escaped(string cv) as string {
//code to put \ in front of problem characters in cv
}
If the problem is in access, then
' escapes '
" escapes "
& you can put a column value containing " inside of '...' and it should work.
However my real thought is that, the SQL you're trying to run might be better restructured to use subqueries to get the matched value(s) and then you're simply comparing column name with column name.
If you post some more information re exactly what the query you're producing is, and some hint of the table structures, I'll try and help further - or someone else is bound to be able to give you something constructive (though you may need to adjust it per Jet SQL syntax)

Is order of parameters for database Command object really important?

I was debugging a database operation code and I found that proper UPDATE was never happening though the code never failed as such. This is the code:
condb.Open();
OleDbCommand dbcom = new OleDbCommand("UPDATE Word SET word=?,sentence=?,mp3=? WHERE id=? AND exercise_id=?", condb);
dbcom.Parameters.AddWithValue("id", wd.ID);
dbcom.Parameters.AddWithValue("exercise_id", wd.ExID);
dbcom.Parameters.AddWithValue("word", wd.Name);
dbcom.Parameters.AddWithValue("sentence", wd.Sentence);
dbcom.Parameters.AddWithValue("mp3", wd.Mp3);
But after some tweaking this worked:
condb.Open();
OleDbCommand dbcom = new OleDbCommand("UPDATE Word SET word=?,sentence=?,mp3=? WHERE id=? AND exercise_id=?", condb);
dbcom.Parameters.AddWithValue("word", wd.Name);
dbcom.Parameters.AddWithValue("sentence", wd.Sentence);
dbcom.Parameters.AddWithValue("mp3", wd.Mp3);
dbcom.Parameters.AddWithValue("id", wd.ID);
dbcom.Parameters.AddWithValue("exercise_id", wd.ExID);
Why is it so important that the parameters in WHERE clause has to be given the last in case of OleDb connection? Having worked with MySQL previously, I could (and usually do) write parameters of WHERE clause first because that's more logical to me.
Is parameter order important when querying database in general? Some performance concern or something?
Is there a specific order to be maintained in case of other databases like DB2, Sqlite etc?
Update: I got rid of ? and included proper names with and without #. The order is really important. In both cases only when WHERE clause parameters was mentioned last, actual update happened. To make matter worse, in complex queries, its hard to know ourselves which order is Access expecting, and in all situations where order is changed, the query doesnt do its intended duty with no warning/error!!
Within Access, an ADODB.Command object ignores parameter names. In fact I can refer to a parameter using a bogus name (which doesn't even exist in the SQL statement) and ADO doesn't care. All it seems to care about is that you supply parameter values in the exact same order as those parameters appear in the SQL statement. BTW, that is also what happens if I build the SQL statement with ? place-holders instead of named parameters.
While I realize that your question is about c# and OleDbCommand, it looks to me like Dot.Net's OleDbCommand may be operating the same as Access' ADODB.Command. Unfortunately, I don't know Dot.Net ... but that is my hunch. :-)
The order is important because of the use of ? placeholders in the command string.
If you want to list the parameters in any order, it's best to use named parameters, such as #word, #sentence, etc.
condb.Open();
OleDbCommand dbcom = new OleDbCommand("UPDATE Word SET word=#word,sentence=#sentence,mp3=#mp3 WHERE id=#id AND exercise_id=#exercise_id", condb);
dbcom.Parameters.AddWithValue("#id", wd.ID);
dbcom.Parameters.AddWithValue("#exercise_id", wd.ExID);
dbcom.Parameters.AddWithValue("#word", wd.Name);
dbcom.Parameters.AddWithValue("#sentence", wd.Sentence);
dbcom.Parameters.AddWithValue("#mp3", wd.Mp3);
I have been doing some tests with using OleDbCommand and its parameters collection against an Access DB. The ordering of parameters is of course necessary, since this is a limitation of the OLE DB .NET provider. But there is a problem that you can encounter when using question marks as place holders.
Say you have a query ("stored procedure") in your Access DB that looks like this, very simplified here:
parameters
prmFirstNumber Long,
prmSecondNumber Long;
select
fullName
from
tblPersons
where
numberOfCars < prmFirstNumber And
numberOfPets < prmSecondNumber And
numberOfBooks beteween prmFirstNumber And prmSecondNumber
Here you see that simply changing to question marks would break the query.
I have found though, as a solution to this, that you can actually use names for parameters. So you can let the query above remain as it is. You just have to use the same order when you run the query. Like in this case, you first add the parameter prmFirstNumber and then prmSecondNumber, and then you run the query.
When reusing parameters, i.e. executing a query more than once and setting new values for the parameters each time, one must call the prepare method of the command object right after having defined the parameters. There are some details there that need to be fulfilled too, look at the documentation for "prepare". Not calling prepare causes strange behaviour without error messages which can corrupt your database or cause wrong information to be presented to users.
I can add also that when queries are stored in the Access DB with parameters specified, like in my example above, then the ordering of the parameters is unambiguously defined by the parameters-section.
I also made a routine, "retrieveDeclaredJetParametersInOrder", which automatically populates an OleDbCommand object with those named parameters, in the correct order. So my code can look like this:
Dim cmd As New OleDbCommand("qryInAccessDB", Conn)
cmd.CommandType = CommandType.StoredProcedure
Conn.Open()
retrieveDeclaredJetParametersInOrder(cmd)
cmd.Parameters("prmOneOfTheParametersPerhapsTheLastOneDeclared").Value = 1
cmd.Parameters("prmAnotherone").Value = 20
cmd.Parameters("prmYetAnotherPerhapsTheFirstOneDeclared").Value = 300
cmd.ExecuteNonQuery()
Conn.Close()
So, as you see, I can handle it as if parameters are named, and never have to bother with their ordering.
The retrieveDeclaredJetParametersInOrder of course adds extra time to execution, since it involves an extra call to the DB, where it retrieves the SQL-text and then parses out the parameter names and types.

Updating tables with column names containing # symbols using OleDbCommandBuilder in C#

Greetings great SO comrades;
I'm trying to use this code to make changes to a SQL Server database:
adapter = new OleDbDataAdapter(
Db.GetRecordSql(table.Name, recordId), Db.Connection);
OleDbCommandBuilder cmd = new OleDbCommandBuilder(adapter);
DataSet ds = new DataSet();
adapter.Fill(ds);
Then later, when saving changes made to a DataRow:
adapter.Update(new DataRow[] { row });
It works exactly the way I want it to work. The DB operations are all very simple, and the app supports multiple database formats, so this is the method that suits the task.
My problem is that this method fails when the row contains a column with an # sign in its name. The database schema prefixes column names with an # sign to denote private meta data, such as creation/modification dates and checksums.
When a column name contains an # sign, the Update method throws an OleDbException:
Must declare the scalar variable #created
Great. Now what?
Seriously, I've googled this thing to death. I know it's a bit unusual to include an # symbol in a column name, but that's the hand I've been dealt.
Any ideas? Pretty please? :)
You should be able to specify the QuotePrefix and QuoteSuffix characters in the command builder:
cmd.QuotePrefix = "[";
cmd.QuoteSuffix = "]";
After doing that, the command it builds will have brackets around all the names (columns and tables). And I suppose it goes without mentioning, but be sure that the prefix and suffix values you use are valid for the underlying database. For example, for some databases, it might be necessary to use double quotes instead of brackets.

Categories