I'm using .Net framework 4.0. and I've the the source code like this:
....
using (MySqlCommand cmd = new MySqlCommand())
{
cmd.Connection = conn;
String query = "SELECT a.process_id, a.prod_dt, a.vlt_dt, a.prod_month, a.karoseri, a.error_flag, a.created_by, date_format(a.created_dt, '%Y%m%d') as created_dt, a.updated_by, date_format(a.updated_dt, '%Y%m%d') as updated_dt FROM tb_t_vlt_web a " +
"WHERE a.process_id = '" + processId + "'";
DataTable dt = CSTDDBUtil.ExecuteQuery(query);
if (dt.Rows.Count > 0)
{
as400Con = CSTDDBUtil.GetAS400Connection();
as400Con.Open();
using (OdbcCommand as400Cmd = new OdbcCommand())
{
as400Cmd.Connection = as400Con;
as400Cmd.CommandText = "INSERT INTO DCDLIB.TBTVLT(VLPRID, VLPRDT, VLVLDT, VLPRMO, VLKRCD, VLERFG, VLCRBY, VLCRDT, VLCHBY, VLCHDT) VALUES " +
"(?,?,?,?,?,?,?,?,?,?)";
foreach (DataRow dr in dt.Rows)
{
as400Cmd.Parameters.Add("1", OdbcType.VarChar).Value = dr["process_id"].ToString();
as400Cmd.Parameters.Add("2", OdbcType.Numeric).Value = dr["prod_dt"];
as400Cmd.Parameters.Add("3", OdbcType.Numeric).Value = dr["vlt_dt"];
as400Cmd.Parameters.Add("4", OdbcType.VarChar).Value = dr["prod_month"].ToString();
as400Cmd.Parameters.Add("5", OdbcType.VarChar).Value = dr["karoseri"].ToString();
as400Cmd.Parameters.Add("6", OdbcType.VarChar).Value = dr["error_flag"].ToString();
as400Cmd.Parameters.Add("7", OdbcType.VarChar).Value = dr["created_by"].ToString();
as400Cmd.Parameters.Add("8", OdbcType.Numeric).Value = dr["created_dt"];
as400Cmd.Parameters.Add("9", OdbcType.VarChar).Value = dr["updated_by"].ToString();
as400Cmd.Parameters.Add("10", OdbcType.Numeric).Value = dr["updated_dt"];
as400Cmd.ExecuteNonQuery();
as400Cmd.Parameters.Clear();
}
as400Cmd.Dispose();
}
}
... Next Process Below ...
When I execute the program, there is an error occurred on as400Cmd.ExecuteNonQuery();. The error was:
ERROR [00000] [IBM][System i Access ODBC Driver]Column 4: CWB0111 - Input data is too big to fit into field
ERROR [22001] [IBM][System i Access ODBC Driver]Column 4: Character data right truncation.
And then, I've checked the AS400 and there is no problem with the column size.
How can I resolved this error..?
Structure table of TBTVLT
We can't tell what the actual problem is easily because you haven't given us the error message, but the first thing to do is stop doing this:
insertQuery = String.Format("INSERT INTO DCDLIB.TBTVLT(VLPRID, VLPRDT, VLVLDT, VLPRMO, VLKRCD, VLERFG, VLCRBY, VLCRDT, VLCHBY, VLCHDT) VALUES " +
"('{0}',{1},{2},'{3}','{4}','{5}','{6}',{7},'{8}',{9})",
Never build up SQL queries by inserting values into the SQL itself. Instead, you parameterized SQL, and add the parameters to the command.
This will:
Keep your SQL easier to read
Avoid SQL injection attacks
Avoid unnecessary string conversions
I wouldn't be at all surprised if the problem is due to date/time to string conversions.
See the "Using Parameters" MySql documentation for examples.
Related
New to stackoverflow and very much a c# beginner
Currently creating a form which produces a bar chart from data stored in a database. The chosen record is identified by pID (patient's ID) and tdate (Test date). These values are determined by 2 combo boxes that the user can select from, The problem I am having is that only the first and last records stored in the database are populating the barchart.
if (radioButtonTestResult.Checked)
{
foreach (var series in TestResultBarChart.Series)
{
series.Points.Clear();
}
string tdate = comboBox2.Text;
using (SqlConnection connection = new SqlConnection(#"Data Source= (LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\MMSEDB.mdf;Integrated Security=True"))
{
connection.Open();
string sql = "SELECT T_CLOCK_SCORE,T_LANGUAGE_SCORE,T_RECALL_SCORE,T_REGISTRATION_SCORE,T_ORIENTATION _SCORE,T_TIME FROM TEST_RESULTS WHERE P_ID='" + pID + "' AND T_DATE='"+ tdate +"'";
using(SqlCommand command = new SqlCommand(sql, connection))
{
command.CommandTimeout = 3600;
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
{
MessageBox.Show("hello4");
String clockScoreString = reader["T_CLOCK_SCORE"].ToString();
MessageBox.Show(clockScoreString);
clockScore = Int32.Parse(clockScoreString);
String langScoreString = reader["T_LANGUAGE_SCORE"].ToString();
langScore = Int32.Parse(langScoreString);
String recallScoreString = reader["T_RECALL_SCORE"].ToString();
recallScore = Int32.Parse(recallScoreString);
String regScoreString = reader["T_REGISTRATION_SCORE"].ToString();
regScore = Int32.Parse(regScoreString);
String orientScoreString = reader["T_ORIENTATION_SCORE"].ToString();
orientScore = Int32.Parse(orientScoreString);
String timeScoreString = reader["T_TIME"].ToString();
timeScore = Int32.Parse(timeScoreString);
}
reader.Close();
}
}
this.TestResultBarChart.Series["Series1"].Points.AddXY("Clock Score", clockScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Language Score", langScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Recall Score", recallScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Registration Score", regScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Orientation Score", orientScore);
}
}
Here is a pic of the data:
Test_results_table
here is a pic of the interface with the first record working:
interface
I know this has something to do with the reader but can't work out how to get to function correctly
Any help is very much appreciated
You are reading in a loop all the returned values, then exit from the loop and use just the last value to set your Points. You should move the Point settings inside the loop
....
while (reader.Read())
{
clockScore = Convert.ToInt32(reader["T_CLOCK_SCORE"]);
langScore = Convert.ToInt32(reader["T_LANGUAGE_SCORE"]);
recallScore = Convert.ToInt32(reader["T_RECALL_SCORE"]);
regScore = Convert.ToInt32(reader["T_REGISTRATION_SCORE"]);
orientScore = Convert.ToInt32(reader["T_ORIENTATION_SCORE"]);
timeScore = Convert.ToInt32(reader["T_TIME"]);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Clock Score", clockScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Language Score", langScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Recall Score", recallScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Registration Score", regScore);
this.TestResultBarChart.Series["Series1"].Points.AddXY("Orientation Score", orientScore);
}
reader.Close();
Note that your query is built using string concatenation. This is a well known problem with database code. Never do it and use a parameterized query
EDIT
Looking at your comment below, I repeat the advice to use a parameterized query instead of string concatenation. Not only this avoid Sql Injection hacks but also you don't leave the job to understand the meaning of your values to the database engine
DateTime tDate = Convert.ToDateTime(comboBox2.Text);
......
string sql = #"SELECT
T_CLOCK_SCORE,T_LANGUAGE_SCORE,T_RECALL_SCORE,
T_REGISTRATION_SCORE,T_ORIENTATION_SCORE,T_TIME
FROM TEST_RESULTS
WHERE P_ID=#id AND T_DATE=#date";
using(SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.Add("#id", SqlDbType.Int).Value = pID;
command.Parameters.Add("#date", SqlDbType.Date).Value = tdate;
command.CommandTimeout = 3600;
using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
....
In this example I assume that the variable pID is of type integer and the variable tDate is of type DateTime matching the type of the database fields. This doesn't leave any doubt to the database engine on your values.
Of course if the fields are of different type then you should change the SqlDbType accordingly.
My sample code is as follows, I am getting following error;
Data Type Mismatch error in criteria expression.
Details => ScannerAlarmLimits is my table from .mdb database.
string jointS = dsetChamberS1.Tables[0].Rows[tot][0].ToString();
int select1S = Convert.ToInt32(jointS);
string sqlQuery1S = "SELECT TMin,TMax,HMin,HMax from ScannerAlarmLimits WHERE ScannerID='" +select1S+ "'";
OleDbCommand cmd1S = new OleDbCommand(sqlQuery1S, conn);
OleDbDataAdapter adapter1S = new OleDbDataAdapter(cmd1S);
adapter1S.Fill(dsetTempS, "ScannerAlarmLimits");
I just added single quote in the condition of where clause, now its working.
var query = "SELECT * from checkinout where read <> '1'";
If your ScannerID column is integer, then you should not use single quotes with it. Single quotes are for characters. Like;
WHERE ScannerID = " + select1S;
But as a better way, you should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks. Aka bobby-tables.
And use using statement to dispose your connections, commands and adapters.
string jointS = dsetChamberS1.Tables[0].Rows[tot][0].ToString();
int select1S = Convert.ToInt32(jointS);
using(var conn = new OleDbConnection(conString))
using(var cmd1S = conn.CreateCommand())
{
cmd1S.CommandText = "SELECT TMin,TMax,HMin,HMax from ScannerAlarmLimits WHERE ScannerID = #id";
cmd1S.Parameters.AddWithValue("#id", OleDbType.Integer).Value = select1S;
using(var adapter1S = new OleDbDataAdapter(cmd1S))
{
adapter1S.Fill(dsetTempS, "ScannerAlarmLimits");
}
}
I've been searching for a while but the answers I find usually involve stored procedures or different functionality.
I am trying to execute a reader and also return a scalar in the one query. I thought I could do this using an output parameter, but I get an exception to check my syntax near NULL = #rows_found(), so it appears the output parameter is not getting initialized.
Basically I need to know if this is possible as I haven't found a code sample like this that works.
command.CommandText = #"
SELECT SQL_CALC_FOUND_ROWS
accounting.*
FROM
accounting
WHERE
transaction_type = #transaction_type
LIMIT
#index, #results;
SET #total_rows = FOUND_ROWS();
";
command.Parameters.AddWithValue("transaction_type", transaction_type);
command.Parameters.AddWithValue("index", index);
command.Parameters.AddWithValue("results", results);
MySqlParameter totalRows = new MySqlParameter("total_rows", 0);
totalRows.Direction = System.Data.ParameterDirection.Output;
command.Parameters.Add(totalRows);
using (MySqlDataReader dr = command.ExecuteReader())
{
while (dr.Read())
invoices.Add(new AccountingDataModel(dr));
}
invoices.Total = (int)totalRows.Value;
cmd.Parameters["#output"].Value.ToString()
Use command object to access your out parameter ....
you can not access out perameter directly.
You Should use like
invoices.Total = Convert.ToInt32(command.Parameters["total_rows"].Value.ToString())
example for stored procedure
MySqlCommand cmd = new MySqlCommand(nameOfStoredRoutine, connection);
cmd.CommandType = CommandType.StoredProcedure;
//input parameters
for (int i = 0; i < (parameterValue.Length / 2); i++)
{
cmd.Parameters.AddWithValue(parameterValue[i, 0], parameterValue[i, 1]);
cmd.Parameters[parameterValue[i, 0]].Direction = ParameterDirection.Input;
parameterList = parameterList + parameterValue[i,0] + " " + parameterValue[i,1] + " ";
}
//single output parameter
cmd.Parameters.AddWithValue("#output", MySqlDbType.Int32);
cmd.Parameters["#output"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery(); //Execute command
return Convert.ToInt32(cmd.Parameters["#output"].Value.ToString());
It seems that this is not possible. From the documentation of MySqlParameter's members for the Direction property:
Gets or sets a value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value parameter. As of MySQL version 4.1 and earlier, input-only is the only valid choice.
So the parameter is, no matter what you set Direction to, always an input parameter. If you change the value from null to anything else (e.g. 15) you should see that the generated query is something like
SET 15 = FOUND_ROWS()
Eventually i ended up running two queries. Probably this is not as performant as it could be, but at least it gets the desired result (using EF Core):
using (var context = new MyDbContext(...))
{
context.Database.OpenConnection();
var estates = context.MySet
.FromSql("SELECT SQL_CALC_FOUND_ROWS * FROM myset LIMIT 25 OFFSET 25")
.ToList();
var cmd = context.Database.GetDbConnection().CreateCommand();
cmd.CommandText = "SELECT FOUND_ROWS()";
var rows = (long)cmd.ExecuteScalar();
context.Database.CloseConnection();
}
I'm trying to write into an Access db. The OLE DB connection is stored on the main form (mainFrm). I read and write using the same connection in other parts of my app. For some reason, at this one spot it says I have a syntax error. I have tried writing it different ways but still get the same error message
public OleDbConnection newCon = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\MorganWillis\Documents\PlannerAppData\MainDB.accdb");`
ListViewItem newnote = new ListViewItem(nameTextBox.Text);
newnote.SubItems.Add(DateTime.Today.ToShortDateString());
newnote.SubItems.Add(noteTextBox.Text)`
mainFrm.notesList.Items.Add(newnote);
string tempname = nameTextBox.Text;
DateTime now = DateTime.Today;
string tempnote = noteTextBox.Text;
if(mainFrm.newCon.State == ConnectionState.Closed)
mainFrm.newCon.Open();
OleDbCommand noteCom = new OleDbCommand("INSERT INTO Notes (noteName, noteDate, note)" + "VALUES (?,?,?)", mainFrm.newCon);
noteCom.Parameters.Add("noteName", OleDbType.Char, 50, "noteName").Value = tempname;
noteCom.Parameters.Add("noteDate", OleDbType.DBDate, 8, "noteDate").Value = now.ToShortDateString();
noteCom.Parameters.Add("note", OleDbType.Char, 1000, "note").Value = tempnote;
OleDbDataAdapter noteadapt = new OleDbDataAdapter();
noteadapt.InsertCommand = noteCom;
noteadapt.InsertCommand.ExecuteNonQuery();
mainFrm.newCon.Close();
Close();
You have an errant + in the middle of your query.
It must be eliminated.
Notes was is a key word in access so it wouldn't let me use it for a table name but when I changed the table name it worked just fine Than you everyone for your help!
//the #Question column name needs to change according to the checkbox. For example Checkbox1 - Question1
SqlConnection con = new SqlConnection(...);
String sql = "UPDATE INQUIRY2 set #Question = #str WHERE email = #email AND base = #base;";
SqlCommand cmd = new SqlCommand(sql, con);
con.Open();
//checkbox2 - question 2
//if (CheckBox3.Checked == true)
//{
// str = str + CheckBox3 + 'x';
//}
DataTable theDataTable = null;
// Verify that dt is actually in session before trying to get it
if(Session["dt"] != null)
{
theDataTable = Session["dt"] as DataTable;
}
//Verify that the data table is not null
if(theDataTable != null)
{
email = theDataTable.Rows[0]["email"].ToString();
base1 = theDataTable.Rows[0]["base"].ToString();
}
//checkbox1 - question 1
if (CheckBox9.Checked == true)
{
str = str + CheckBox9.Text + 'x';
strQuestOne = theDataTable.Columns["Question1"].ToString();
}
cmd.Parameters.AddWithValue("#email", email);
cmd.Parameters.AddWithValue("#str", str);
cmd.Parameters.AddWithValue("#Question", strQuestOne);
cmd.Parameters.AddWithValue("#base", base1);
cmd.ExecuteNonQuery();
con.Close();
You are using a parameter for a column name. Database objects (columns names, tables, stored procedures or any other objects) cannot be passed as parameters. Only actual values for columns or variables can be parameters. You need to build your SQL statement dynamically in this case:
String sql ="UPDATE INQUIRY2 set " + strQuestOne + "= #str WHERE email = ...
But now you should be carefull because you code is at risk of SQL injection attack.
Your SQL uses #param type in the string.
If you are looking to execute a stored procedure of some sort to negate most sql injection attacks on a website you might want to consider calling a stored procedure and adding SqlCommand.Parameter to the SqlCommand.Parameters Collection.
Otherwise if you want to just execute the sql you should do
string sql = String.Format("UPDATE TABLE set COLUMN = {0} where OTHERCOLUMN = {1}", varValue, varWhere);