I've been all over the web with this one and I am surprised how I can't seem to find any way to do what I looking for.
I am using the Oracle.DataAccess.Client library in my C# project, not the deprecated System.Data.OracleClient.
I have a very simple table:
CREATE TABLE testing (
ID NUMBER(10),
COMMENTS CLOB,
DATECREATED DATE DEFAULT (SYSDATE) NOT NULL,
DATEMODIFIED DATE
);
INSERT INTO testing (ID, COMMENTS) VALUES(1, 'this is a test');
The above obviously works just fine. The problem is, this being a comment field it will be changed. In my C# program I would like to allow users to save comments. For this example I am removing anything complex.
I have a button on a form and a textbox called "comments".
using (OracleConnection connection = new OracleConnection(<VALID CONN STRING GOES HERE>)) {
connection.Open();
using (OracleCommand command = new OracleCommand()) {
command.Connection = connection;
command.CommandText = "UPDATE testing SET COMMENTS = :COMMENTS, DATEMODIFIED = sysdate WHERE ID = :ID";
command.CommandType = CommandType.Text;
command.Parameters.Add("ID", OracleDbType.Int32, ParameterDirection.Input).Value = 1;
command.Parameters.Add("COMMENTS", OracleDbType.Clob, ParameterDirection.Input).Value = comments.Text;
command.ExecuteNonQuery();
}
}
So basically this code works as long as I don't attempt to write the Clob. If I save the date modified is created as expected. However when I save with the Clob, nothing happens. No error message from oracle, no exception, nothing.
If I forgo parameterization and do it the wrong way:
command.CommandText = "UPDATE testing SET COMMENTS = " + comments.Text + ", DATEMODIFIED = sysdate";
There is no problem. It seems the parameterization is the issue here.
It turns out I was correct in that parameterization was the issue, however I can say it was a very basic mistake. Anyway the statement was actually running perfectly fine but the parameters were being added out of order.
Note how in the following code ID is added last, as it is the last parameter (where clause.)
using (OracleConnection connection = new OracleConnection(<VALID CONN STRING GOES HERE>)) {
connection.Open();
using (OracleCommand command = new OracleCommand()) {
command.Connection = connection;
command.CommandText = "UPDATE testing SET COMMENTS = :COMMENTS, DATEMODIFIED = sysdate WHERE ID = :ID";
command.CommandType = CommandType.Text;
command.Parameters.Add("COMMENTS", OracleDbType.Clob, ParameterDirection.Input).Value = comments.Text;
command.Parameters.Add("ID", OracleDbType.Int32, ParameterDirection.Input).Value = 1;
command.ExecuteNonQuery();
}
}
In order to use the binding out of order for ODP .NET, you need to specify this extra command (better practice) This was not required if you had previously used Microsoft's provider.
Command.BindByName=true;
Can you test your update with > 32K in the comment to see if it errors?
From my experience an Oracle CLOB can be written to in this context by converting a String to a character array with the following:
String input = "string value";
OracleParameter parm = new OracleParameter("parameter_name", OracleDbType.Clob);
parm.Direction = ParameterDirection.Input;
parm.Value = input.toCharArray();
as a CLOB is a character large object.
Related
As I am new to coding I have to get an id from user and compare it to a table from students that contains a foreign key of sectionid. I would really appreciate if you help me what to do next I have searched but I'm not understanding anything.
[HttpPost]
public ActionResult CheckSectionIDagainststudentID(string sectionID)
{
int x = Int32.Parse(sectionID);
ConnectionManager connManager = new ConnectionManager();
SqlConnection conn = connManager.GetConnection();
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Select * From Student Where sectionid = " + x;
cmd.Connection = conn;
conn.Open();
cmd.ExecuteNonQuery();
}
Although you MIGHT be close (not knowing all your tables), I would finish what you have using a SqlDataAdapter. That does a bunch of the work for you when loading into a table.
replace your "cmd.ExecuteNonQuery()" line with something like.
var sda - new SqlDataAdapter();
sda.Command = cmd;
var tbl = new DataTable();
sda.Fill( tbl );
This should pull down all records and put into a datatable object for you. Then you can go through each record and do whatever you need.
Also, fix your parameters. if expecting a number, do so. But from a web post, everything comes in as string and you need to parse as you have done. use int.TryParse() command (read up on that), to prevent crash if some bad text comes in unexpectedly.
Finally fix your query now and all future to prevent sql-injection. use place-holders and then your parameter, such as
cmd.CommandText = "Select * From Student Where sectionid = #parmSectionID";
cmd.Parameters.AddWithValue( "parmSectionID", x );
Dont add the "#" to the string representation in the parameters line.
Definitely read-up on more SQL commands throughout S/O and also SQL-Injection especially this early on in your development. Dont start with bad techniques that will bite you in the long run.
I have an ASP webpage that gets a string from the user. These strings are usually complex SQL queries or code snippets, so I need to insert them into database with the characters like \n, \r. And then read it in the same format so all another user has to do is copying the code and running it.
Problem is, when inserting to database, they are cut. I am using SQL Server, here is my code for inserting to database:
OdbcConnection conn = new OdbcConnection();
StringBuilder query = new StringBuilder();
OdbcCommand command = new OdbcCommand();
string db= null;
db = connectionstr;
conn.ConnectionString = veritabani;
conn.Open();
db = null;
string detail = this.txtdetail.Text;
command = conn.CreateCommand();
if (string.IsNullOrEmpty(hdnFilename.Value))
{
query.Append(" INSERT INTO SUPPORT (title, detail, date) VALUES (?,?,?) ");
command.CommandText = query.ToString();
command.Parameters.Add("#title", OdbcType.VarChar).Value = this.txtbaslik.Text;
command.Parameters.Add("#detail", OdbcType.NVarChar).Value = detail;
command.Parameters.Add("#date", OdbcType.DateTime).Value = DateTime.Now.ToString();
}
else
{
query.Append(" INSERT INTO SUPPORT (baslik, detail, date, file) VALUES (?,?,?,?) ");
command.CommandText = query.ToString();
command.Parameters.Add("#title", OdbcType.VarChar).Value = this.txtbaslik.Text;
command.Parameters.Add("#detail", OdbcType.NVarChar).Value = detail;
command.Parameters.Add("#date", OdbcType.DateTime).Value = DateTime.Now.ToString();
command.Parameters.Add("#file", OdbcType.VarChar).Value = hdnFilename.Value;
}
command.ExecuteNonQuery();
command = null;
conn.Close();
conn = null;
Code works fine and inserts into the database, had to translate a few variables to give you guys a better idea, original has no syntax errors.
The thing is, sql statements had comment lines in them, so if I were to copy paste the query, It would not work. Removing them helped, I will leave the question here for future generations. Thank you for the answers.
I am new to Access and saving data to it. I have a date time field which I used in Visual Studio to make the form and chose date time picker. I am not sure where I am going wrong but I know it is the calendar picker causing the issue. I get error syntax error in insert to statement.
Here is the code I have
string When = qaWhendateTimePicker.Value.ToString("HH:mm:ss.fff");
then my save query
SQLString = "INSERT INTO QAAnswers (QuestionID,CallMonitorNumber,When) VALUES('"+QuestionID + "','" + CallMonitorNumber + "','" + When + "');";
This is of course the shorten version. But for the love of me if I take out the when it saves to the database fine
The Access database I have WHEN SET AS DATE / TIME.
Should I have it set to text? I would think no because then I can not pull queries based on date.
Thanks in advance as I been at this for many hours.
UPDATE
Per comment below i have changed the syntax. Here is what i have. If i put the .value or .date it does not work. I am sure it is something I am doing wrong. I get the error failed to convert parameter value from datetimepicker to datetime. Thanks as I am learning a lot doing this in access.
ad.InsertCommand = new OleDbCommand("insert into QAAnswers ([CallMonitorNumber],[When],[ProperGreeting],[AssureHelp],[AccountVerification],[ConfirmCaller],[ProperPoliciesSolutions],[ProperPoliciesAdmin],[AppropriateTools],[TroubleshootingSteps],[ConfirmResolved],[CustomerEducation],[CSATSurvey],[ThanksCallerBrand],[ProfessionalToneAttitude],[CustomerInvolved],[CallPace],[Empathy],[PhoneEtiquette],[DiffuseEscalated],[UnacceptableCallPractice],[Notes],[ScorePotential],[ScoreActual],[FinalScore]) values (#CallMonitorNumber,#When,#ProperGreeting,#AssureHelp,#AccountVerification,#ConfirmCaller,#ProperPoliciesSolutions,#ProperPoliciesAdmin,#AppropriateTools,#TroubleshootingSteps,#ConfirmResolved,#CustomerEducation,#CSATSurvey,#ThanksCallerBrand,#ProfessionalToneAttitude,#CustomerInvolved,#CallPace,#Empathy,#PhoneEtiquette,#DiffuseEscalated,#UnacceptableCallPractice,#Notes,#ScorePotential,#ScoreActual,#FinalScore)", con);
ad.InsertCommand.Parameters.Add("#QuestionID", OleDbType.VarChar).Value = agentIDNumbertextBox.Text.ToString();
ad.InsertCommand.Parameters.Add("#CallMonitorNumber", OleDbType.VarChar).Value = qaCallMonitorNumbertextBox.Text.ToString();
ad.InsertCommand.Parameters.Add("#When", OleDbType.DBDate).Value = qaWhendateTimePicker;
UPDATED ANSWER
I finally figured it out. Not sure if this is the best way but i just ignored the datetimepicker. I wish i could use the datepicker. Instead i just input the date it was added in by using this statement (shorten version ) Notice the [when] and the Date() .
DateTime now = DateTime.Now;
ad.InsertCommand = new OleDbCommand("insert into QAAnswers ([CallMonitorNumber],[When]) values (#CallMonitorNumber,Date())", con);
I hope this helps someone else. I really do not like using access for a DB but that is what i have to work with .
I gave points to marc as i never heard of parametrized query
You should use a parametrized query to do the insert, to avoid SQL injection attacks!
Something like this:
SQLString = "INSERT INTO QAAnswers (QuestionID, CallMonitorNumber, When) VALUES(?, ?, ?);";
and then when you prepare your insert statement, you need to add three parameters (in Access typically defined as p1, p2, p3) and assign values to those.
using (OleDbConnection conn = new OleDbConnection(YourConnectionStringHere))
using (OleDbCommand cmd = new OleDbCommand(SQLString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("p1", OleDbType.VarChar, 50).Value = QuestionID;
cmd.Parameters.Add("p2", OleDbType.VarChar, 50).Value = CallMonitorNumber;
cmd.Parameters.Add("p3", OleDbType.DBDate).Value = When;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
This will also take care of avoiding issues with dates in string format, and issues with single quotes and all those messy things.
You can use this method also:-
write your insert query in a stored procedure(or you can use query directly) then call it in your method
string strcon = ConfigurationManager.ConnectionStrings["YourConnectionStringName"].ConnectionString;
con.ConnectionString = strcon;
con.Open();
SqlCommand cmd = new SqlCommand("[Your_StoredProcedureName]", con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.Parameters.AddWithValue("#value1", value1);
da.SelectCommand.Parameters.AddWithValue("#value2", value2);
da.SelectCommand.Parameters.AddWithValue("#value3", value3);
int result = da.SelectCommand.ExecuteNonQuery();
return result ;
I finally figured it out. Not sure if this is the best way but i just ignored the datetimepicker. I wish i could use the datepicker. Instead i just input the date it was added in by using this statement (shorten version ) Notice the [when] and the Date() .
DateTime now = DateTime.Now;
ad.InsertCommand = new OleDbCommand("insert into QAAnswers ([CallMonitorNumber],[When]) values (#CallMonitorNumber,Date())", con);
I have posted the code I have below
I am trying to get the data from an Access 2002-2003 database
If I take out everything after the WHERE clause and just use "SELECT * FROM [{0}] then it takes all the data from the table with no problems. I have double checked the field names, they are definitely correct. I have more than 1 table with the same field names, so I thought maybe I would need to include the table name before the field name, but with or without the table I still get the same exception. I have tried moving the position of the square brackets, again with no success...
Even if I include only one of the WHERE clauses, the code no longer works, and I can't for the life of me work out why.. I have spent hours looking at numerous posts here and on other sites related to this error, but none of the suggestions have helped me..
The Destination field is a 'memo' field in Access.
The Next Collection fields are date fields, GVars.currentDate is set earlier in the code to be today's date (with the time portion set to 00:00:00).
GVars.thisFY is also set programatically as a string prior to this.
Any tips would be appreciated.
string sql;
OleDbDataAdapter adapter;
sql = string.Format(
"SELECT * FROM [{0}] WHERE {0}.[Destination] = #Destination AND {0}.[Next Collection] BETWEEN #NextCollectionA AND #NextCollectionB"
, GVars.thisFY);
// Create the command object
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;
// Add values to the fields
cmd.Parameters.AddWithValue("#Destination", "Henwood");
cmd.Parameters.AddWithValue("#NextCollectionA", GVars.currentDate);
cmd.Parameters.AddWithValue("#NextCollectionB", GVars.currentDate.AddDays(1));
adapter = new OleDbDataAdapter(cmd.CommandText, conn);
System.Diagnostics.Debug.Print(cmd.CommandText);
try
{
adapter.Fill(ds);
GVars.bLblLastUpdate = DateTime.Now.ToString("HH:mm:ss");
}
catch (Exception ex)
{
}
EDIT:
Thanks Vladislav for the answer, corrected code posted below:
string sql;
OleDbDataAdapter adapter;
sql = string.Format(
"SELECT * FROM [{0}] WHERE [{0}].[Destination] = #Destination AND [{0}].[Next Collection] BETWEEN #NextCollectionA AND #NextCollectionB"
, GVars.thisFY);
// Create the command object
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;
cmd.Connection = conn;
// Add values to the fields
cmd.Parameters.Add("#Destination", OleDbType.Char).Value = "Henwood";
cmd.Parameters.Add("#NextCollectionA", OleDbType.DBDate).Value = GVars.currentDate;
cmd.Parameters.Add("#NextCollectionB", OleDbType.DBDate).Value = GVars.currentDate.AddDays(1);
adapter = new OleDbDataAdapter(cmd);
try
{
adapter.Fill(ds);
GVars.bLblLastUpdate = DateTime.Now.ToString("HH:mm:ss");
}
Try to specify types for the parameters you add.
Another thing I notice is that to your adapter you are passing only the CommandText.
You should pass the whole command object.
Greetings all,
I have a question. I am trying to build a parametrized query to get me the number of rows from a table in Oracle. Rather simple. However I am an Oracle newbie..
I know in SQL Server you can do something like:
Select #outputVariable = count(*) from sometable where name = #SomeOtherVariable
and then you can set up an Output parameter in the System.Data.SqlClient to get the #outputVariable.
Thinking that one should be able to do this in Oracle as well, I have the following query
Select count(*) into :theCount from sometable where name = :SomeValue
I set up my oracle parameters (using System.Data.OracleClient - yes I know it will be deprecated in .Net 4 - but that's what I am working with for now) as follows
IDbCommand command = new OracleCommand();
command.CommandText = "Select count(*) into :theCount from sometable where name = :SomeValue";
command.CommandType = CommandType.Text;
OracleParameter parameterTheCount = new OracleParameter(":theCount", OracleType.Number);
parameterTheCount .Direction = ParameterDirection.Output;
command.Parameters.Add(parameterTheCount );
OracleParameter parameterSomeValue = new OracleParameter(":SomeValue", OracleType.VarChar, 40);
parameterSomeValue .Direction = ParameterDirection.Input;
parameterSomeValue .Value = "TheValueToLookFor";
command.Parameters.Add(parameterSomeValue );
command.Connection = myconnectionObject;
command.ExecuteNonQuery();
int theCount = (int)parameterTheCount.Value;
At which point I was hoping the count would be in the parameter parameterTheCount that I could readily access.
I keep getting the error ora-01036 which http://ora-01036.ora-code.com tells me to check my binding in the sql statement. Am I messing something up in the SQL statement? Am I missing something simple elsewhere?
I could just use command.ExecuteScaler() as I am only getting one item, and am probably going to end up using that, but at this point, curiosity has got the better of me. What if I had two parameters I wanted back from my query (ie: select max(ColA), min(ColB) into :max, :min.....)
Thanks..
Some versions of the ADO does not need the colon : configuring OracleParameter.
Instead of:
new OracleParameter(":theCount", OracleType.Number);
try
new OracleParameter("theCount", OracleType.Number);
Anyway, I think you have to use the ExecuteScalar() function of the IDbCommand and avoiding use of into (which I'm not sure it's valid on this context). I mean:
IDbCommand command = new OracleCommand();
command.CommandText = "Select count(*) from sometable where name = :SomeValue";
command.CommandType = CommandType.Text;
OracleParameter parameterSomeValue = new OracleParameter("SomeValue", OracleType.VarChar, 40);
parameterSomeValue .Direction = ParameterDirection.Input;
parameterSomeValue .Value = "TheValueToLookFor";
command.Parameters.Add(parameterSomeValue );
command.Connection = myconnectionObject;
int theCount = (int)command.ExecuteScalar();
Disclaimer: The code have not been compiled, and may be have any little error.
Update: If you take a look on the Oracle SELECT syntax, you will see that The SELECT INTO sentence is not recognized. But it's valid in PLSQL syntax as you can see here. You can try one of the following to see if it works (not tested):
command.CommandText = "begin Select count(*) into :someCount from sometable where name = :SomeValue; end;";
I think the problem is that you have a trailing space in the parameter name for parameterTheCount.
Edit
Now remove the colons from the parameter names in the constructor to OracleParameter.