How to execute pl sql block using oledb in c# - c#

I am executing Pl/Sql block using OLEDB in C#.
The code is:
string a1;
a1 = discom1.Text.ToString();
my_querry10 = "BEGIN"+
"SELECT * from MasterCompliant WHERE Discom ='" + a1 + "';"+
"" + var1 + " = SQL%ROWCOUNT;"+
"END;";
OleDbCommand cmd12 = new OleDbCommand(my_querry10, conn);
conn.Open();
cmd12.ExecuteNonQuery();
The exception is coming to statement:
"cmd12.ExecuteNonQuery" as
"Invalid SQL statement; expected 'DELETE', 'INSERT', 'PROCEDURE', 'SELECT', or 'UPDATE'."
MasterCompliant is table name; Discom is column name and var1 is integer.

It seems to me that you don't need a separate block for this at all - you can just use SELECT COUNT(1) and ExecuteScalar:
string sql = "SELECT COUNT(1) FROM MasterCompliant WHERE Discom = ?";
int count;
// Open and close a connection each time you need one - let the connection pool
// handle making that efficient.
using (var connection = new OleDbConnection(...))
{
connection.Open();
using (var command = new OleDbCommand(sql, conn))
{
command.Parameters.Add("#v", OleDbType.VarChar).Value = discom1.Text;
count = (int) command.ExecuteScalar();
}
}
It's possible that you need to cast to long instead of int - you should basically try it and see.
Note how using a parameterized query makes the SQL simpler to read and prevents SQL Injection attacks.

Remove semicolon near a1
Discom ='" + a1 + "';"+ to Discom ='" + a1 + "'"+
"BEGIN"+
"SELECT * from MasterCompliant WHERE Discom ='" + a1 + "'"+
"" + var1 + " = SQL%ROWCOUNT;"+
"END;"

Related

String meant to store date in a table is converting an int for unknown reason

I'm trying to get the date to store as a string in a table, but the date keeps converting to a negative 4 digit number which correlates with the date, and I can't for the life of me figure out where I've messed up. Note that I'm using a combo of C# and SQL Server
foreach(DataRow dr in dt.Rows)
{
int qty = 0;
string pname = "";
SqlCommand cmd3 = con.CreateCommand();
cmd3.CommandType = CommandType.Text;
cmd3.CommandText = "insert into order_item values('" + orderid.ToString() + "','" + dr["product"].ToString() + "'," +
"'" + dr["price"].ToString() + "','" + dr["qty"].ToString() + "','"+ dr["total"].ToString() + "')";
cmd3.ExecuteNonQuery();
qty = Convert.ToInt32(dr["qty"].ToString());
pname = dr["product"].ToString();
SqlCommand cmd6 = con.CreateCommand();
cmd6.CommandType = CommandType.Text;
cmd6.CommandText = "update stock set product_qty = product_qty - " + qty + " where product_name = '"+pname.ToString()+"'";
cmd6.ExecuteNonQuery();
// date keeps getting updated to negative 4 digit number which coordinates with the date. ex: 14-01-2020 is converting to -2007.
SqlCommand cmd7 = con.CreateCommand();
cmd7.CommandType = CommandType.Text;
**cmd7.CommandText = "update stock_over_time set product_qty = product_qty - " + qty + ", date_changed = " + date.ToString("dd-MM-yyyy") + "" +
" where product_name = '" + pname.ToString() + "'";**
cmd7.ExecuteNonQuery();
}
The immediate problem is that:
, date_changed = " + date.ToString("dd-MM-yyyy") + "
will become
, date_changed = 15-01-2020
which is: -2006, which is (because of how dates are stored) some time in July 1894.
A bad fix for this would be to add quotes, but this is: bad - it has a range of problems to do with internationalization (is 08-01 the first of August? the 8th of January?), SQL injection, etc.
The correct fix is to use parameters throughout. For example:
cmd7.CommandText = #"
update stock_over_time
set product_qty = product_qty - #qty,
date_changed = #date
where product_name = #pname";
This, however, requires you to add parameters with the values.
The simplest way to do this would be with Dapper:
string pname = ...
int qty = ...
DateTime date = ...
con.Execute(#"
update stock_over_time
set product_qty = product_qty - #qty,
date_changed = #date
where product_name = #pname",
new { pname, qty, date });
Note: all of your database access should be parameterized, either like the above, or using raw ADO.NET, or using tools like EF etc. Not just this one place; everywhere.
A date should not be stored as a string datatype, instead change date-changed to a datetime type (or even just a date, since the values stored have no "time" element).
Also, it is advisable to use a parameterized query to avoid SQL injection
string sql = #"update stock_over_time set product_qty = product_qty - #qty, date_changed = #date where product_name = #pname";
using (SqlConnection connection = new SqlConnection(connString)
{
connection.Open();
using (SqlCommand cmd= new SqlCommand(sql, connection))
{
cmd.Parameters.Add("#qty", SqlDbType.SqlInt32).value = qty;
cmd.Parameters.Add("#date", SqlDbType.SqlDateTime).value = date;
cmd.Parameters.Add("#pname", SqlDbType.Varchar, 50).value = pname;
cmd.ExecuteNonQuery();
}
}

Update query for adding new values to the existing records in a database using textbox in visual c#

updatequery = #"UPDATE EMP_DETAILS SET ADVANCE_SAL = 'ADVANCE_SAL + '" +
Convert.ToDecimal(txtADV.Text) + "'' WHERE EMP_ID = '" +
Convert.ToInt64(txtEID.Text) + "')";
What is wrong with the above code?
.
.
.
The modified code which has an error [Scalar variable #ADVANCE_SAL not declared] is as follows:
var c = dtimePick.Value.TimeOfDay;
SqlParameter param = new SqlParameter("#ADVANCE_SAL", SqlDbType.Decimal);
param.Value = Convert.ToDecimal(txtADV.Text);
command.Parameters.Add(param);
updatequery = #"UPDATE EMP_DETAILS SET ADVANCE_SAL = ADVANCE_SAL + #ADVANCE_SAL , LATEST_ADVANCE_DATE = '"+c+"' WHERE ENAME = '"+txtEID.Text+"' ";
The error is that you are enclosing ADVANCE_SAL with single quote. To make it cleaner and safer from sql injection, you must parameterized the query,
updatequery = #"UPDATE EMP_DETAILS
SET ADVANCE_SAL = ADVANCE_SAL + #ADVANCE_SAL
WHERE EMP_ID = #EMP_ID"
using (SqlConnection connection = new SqlConnection(/* connection info */))
{
using (SqlCommand command = new SqlCommand(updatequery , connection))
{
// must do proper error handling
connection.Open();
command.Parameters.Add(new SqlParameter("ADVANCE_SAL", Convert.ToDecimal(txtADV.Text)));
command.Parameters.Add(new SqlParameter("EMP_ID", Convert.ToInt64(txtEID.Text)));
int results = command.ExecuteNonQuery();
}
}
Why you are adding single quote to the EMP_ID and ADVANCE_SAL they are numeric and don't need ', i think following is what you wanted...
updatequery = #"UPDATE EMP_DETAILS SET ADVANCE_SAL = ADVANCE_SAL + " +
Convert.ToDecimal(txtADV.Text) + " WHERE EMP_ID = " +
Convert.ToInt64(txtEID.Text) + ")";
There are many problems with your implementation.
1- SQL injection vulnerability - Rad more on this here
2- Your query building is not correct, it should be like following. (Quotes are not correct for ADVANCE_SAL)
updatequery = #"UPDATE EMP_DETAILS SET ADVANCE_SAL = ADVANCE_SAL + " +
Convert.ToDecimal(txtADV.Text) + " WHERE EMP_ID = '" +
Convert.ToInt64(txtEID.Text) + "'";
3- If any employee have not opted for advance salary (in that case the ADVANCE_SAL value can be null in the table). Your query will update it with NULL as NULL + SomeValue = NULL
For example
SELECT NULL +10.0 AS Total
Output
Total
-----
NULL
try this
updatequery = #"UPDATE EMP_DETAILS SET ADVANCE_SAL = 'ADVANCE_SAL + '" +
Convert.ToDecimal(txtADV.Text) + "'' WHERE ( EMP_ID = '" +
Convert.ToInt64(txtEID.Text) + "')";

C# How to update bool in a database a sql query

How to update bool in a database a sql query
below is the code i have but i am unsure of how to implement the checkbox.
Thank you for any help.
i have updated the code to remove the sql injection problems.
con.Open();
OleDbCommand cmd = new OleDbCommand(String.Concat("Select * From ", comboBox1.Text), con);
cmd.CommandType = CommandType.Text;
string tableName = comboBox1.Text.ToString();
cmd.CommandText = #"UPDATE [" + tableName + "] SET"
+"People_Call_Status = #People_Call_Status,"
+"Research_Date=#Research_Date,"
+ "tblCompanies_Area_Dialling_Code = #tblCompanies_Area_Dialling_Code,"
+ "Work_Number = #Work_Number,"
+ "building_Address = #building_Address,"
+ "[Street Address] = #[Street Address],"
+ "suburb = #suburb,"
+ "city = #city,"
+ "res_Code = #res_Code,"
+ "industry_Vertical_ID = #industry_Vertical_ID,"
+ "pO_Box = #pO_Box,"
+ "post_Office = #post_Office,"
+ "postal_Code = #postal_Code,"
+ "country_ID = #country_ID,"
+ "province_ID = #province_ID," //this line
+ "prospect = #prospect"
+ "WHERE Company_ID = #Company_ID ";
cmd.Parameters.AddWithValue("#People_Call_Status", Status_textBox1.Text);
cmd.Parameters.AddWithValue("#Research_Date", Date_textBox.Text);
cmd.Parameters.AddWithValue("#Company_Name", company_NameTextBox.Text);
cmd.Parameters.AddWithValue("#tblCompanies_Area_Dialling_Code", tblCompanies_Area_Dialling_CodeTextBox.Text);
cmd.Parameters.AddWithValue("#Work_Number", work_NumberTextBox.Text);
cmd.Parameters.AddWithValue("#building_Address", building_AddressTextBox.Text);
cmd.Parameters.AddWithValue("#[Street Address]", street_AddressTextBox.Text);
cmd.Parameters.AddWithValue("#suburb", suburbTextBox.Text);
cmd.Parameters.AddWithValue("#city", cityTextBox.Text);
cmd.Parameters.AddWithValue("#res_Code", res_CodeTextBox.Text);
cmd.Parameters.AddWithValue("#industry_Vertical_ID", industry_Vertical_IDTextBox.Text);
cmd.Parameters.AddWithValue("#pO_Box", pO_BoxTextBox.Text);
cmd.Parameters.AddWithValue("#post_Office", post_OfficeTextBox.Text);
cmd.Parameters.AddWithValue("#postal_Code", postal_CodeTextBox.Text);
cmd.Parameters.AddWithValue("#country_ID", country_IDTextBox.Text);
cmd.Parameters.AddWithValue("#province_ID", province_IDTextBox.Text);
cmd.Parameters.AddWithValue("#prospect", prospectCheckBox.Checked);
cmd.Parameters.AddWithValue("#Company_ID", company_IDTextBox.Text);
cmd.ExecuteNonQuery();
{
MessageBox.Show("Update Success!");
con.Close();
}
In SQL Server, bool is mapped as a bit datatype with 0 and 1 values.
So what you need to do is:
"', prospect = '" + prospectCheckBox.Checked ? 1 : 0
Side-Note:
Don't concatenate strings to build up your query from user data input, this is vulnerable to SQL injection. Instead, use parameterized queries or stored procedures.
What DBMS platform are you using, and can you show the DDL for the table?
I can't guarantee this will work, but instead of using AddWithValue try using the Add method with explicit types declared:
cmd.Parameters.Add(new OleDbParameter("#People_Call_Status", OleDbType.VarChar));
cmd.Parameters.Add(new OleDbParameter("#Research_Date", OleDbType.VarChar));
...
cmd.Parameters.Add(new OleDbParameter("#prospect", OleDbType.Boolean));
cmd.Parameters.Add(new OleDbParameter("#Company_ID", OleDbType.VarChar));
cmd.Parameters[0].Value = Status_textBox1.Text;
cmd.Parameters[1].Value = Date_textBox.Text;
...
cmd.Parameters[16].Value = prospectCheckBox.Checked;
cmd.Parameters[17].Value = company_IDTextBox.Text;
Also, with regards to SQL Injection, you still have a theoretical vulnerability:
cmd.CommandText = #"UPDATE [" + tableName + "] SET"
+ "People_Call_Status = #People_Call_Status,"
+ "Research_Date=#Research_Date,"
...
+ "prospect = #prospect"
+ "WHERE Company_ID = #Company_ID ";
I realize it's an obscure possibility, but if the tableName variable were to contain this string or something like it:
Table1 set foo = 'bar';
truncate table ba2;
update table3
You could see how it would compile, execute and do something other than what you had in mind. Again, I realize this is reaching, and your input does come from a combo box, but it's still a theoretical risk.

Making a reservation button

I'm making a class reservation website and having trouble with creating the button.
I would like to customer to insert two details session into two textboxes, session type "class" or "workshop" and date & time and they will be able to see that information from the DataGridView displayed.
Once they hit the "Reserve" button the button will run a query where it'll add the chosen session from Session table to Reservation table. However my code executes with no errors but does not update the "Reservation" table.
here's my code:
OleDbConnection myConnection = GetConnection();
OleDbCommand cmd = myConnection.CreateCommand();
string query = "select COUNT(*) from [Yoga-Session] where [session type] = '" + txt_type.Text + "' and duration = '" + txt_datetime.Text + "';";
OleDbCommand command = new OleDbCommand(query, myConnection);
myConnection.Open();
int rows1 = (Int32)command.ExecuteScalar();
if (rows1 >= 1)
{
cmd = new OleDbCommand("Select session_id from [yoga-session] where [session type] = '" + txt_type.Text + "' and duration = '" + txt_datetime.Text +"';",myConnection);
int classId = (Int32)command.ExecuteScalar();
cmd = new OleDbCommand("select client_id from client where name = '" + Session["[name]"] + "';", myConnection);
int clientID = (Int32)command.ExecuteScalar();
string query1 = "insert into reservation (session_id, client_id, client_name) values ('" + classId + "','" + clientID + "','" + Session["[name]"].ToString() + "');";
cmd = new OleDbCommand(query1, myConnection);
cmd.ExecuteNonQuery();
Response.Write("Reservation successful");
Response.Redirect("reservation.aspx");
myConnection.Close();
}
}
}
int classId = (Int32)cmd.ExecuteNonQuery();
int clientID = (Int32)cmd.ExecuteNonQuery();
You need to use cmd.ExecuteScalar() to get session_id and client_id values. ExecuteNonQuery returns you no of rows affected by the SQL query.
Also see what #Sherantha pointed out.
ExecuteNonQuery() is not for SELECT commands. To get a field value from SELECT command we need to use ExecuteScalar().
Try replacing;
int rows1 = (Int32)command.ExecuteScalar();
Just a small headsup before I compose my real answer (because I don't have rep to comment)
Firstly: Use Prepared Statements. They help immensely in reducing errors from typing SQL queries, as well as a way to prevent SQL Injection Attacks in real-world situations.
Secondly: While not really needed in most database types, it is recommended that a naming convention is strictly uniform in your code.
Well aside from that, I will get to the real answer now.
Looking at the code, I am assuming that classID and clientID are integers, but in your code, it looks like they are parsed as strings due to the ' ' characters. Do not use the characters when inserting integers.
EDIT: is [session type] meant to be [session_type]?
You should use query1 instead of query.
string query1 = "insert into reservation (session_id, client_id, client_name) values ('" + classId + "','" + clientID + "','" + Session["[name]"].ToString() + "');";
cmd = new OleDbCommand(query1, myConnection);// not query but query1
cmd.ExecuteNonQuery();
Response.Write("Reservation successful");
PS: Use sql data reader to select data.
cmd = new OleDbCommand("Select session_id from [yoga-session] where [session type] = '" + txt_type.Text + "' and duration = '" + txt_datetime.Text +"';",myConnection);
SqlDataReader rdr = cmd.ExecuteReader();
int classId = 0;
while (rdr.Read())
{
clientID = Convert.ToInt32(rdr["session_id"]);
}

How can i select from table where tablename is specified as SqlParameter?

I am trying to perform dynamic sql select where I am selecting from a table using a parameter.
SELECT null FROM #TableName
However I am getting error must declare table variable #TableName. I suspect this is because I am selecting from a table using a variable. I have not needed to do this before.
List<SqlParameter> sqlParams = new List<SqlParameter>()
{
new SqlParameter("TableName", "testtable"),
new SqlParameter("FieldName", "testfield"),
new SqlParameter("Find", "testfind"),
};
string sqlSelect = "SELECT null FROM #TableName
WHERE #FieldName LIKE '%' + #Find + '%' ";
DataTable dtSelect = SqlHelper.ExecuteDataset(sqlConn, CommandType.Text,
sqlSelect, 30, sqlParams.ToArray()).Tables[0];
//30 = timeout
How can I perform the above using dynamic sql? (no stored procedures please)
You cannot use parameters for things like table and column names. For those you could have a whitelist of possible values and then use string concatenation when building the SQL query.
You can't use parameters like that, so you have to build the query as a string. You could do that in SQL, but you can also just create the string in the C# code.
Make sure that the table name and field name are safe and trusted values, and doesn't come directly from an unsafe source like a web request.
string tableName = "testtable";
string fieldName = "testfield";
List<SqlParameter> sqlParams = new List<SqlParameter>() {
new SqlParameter("Find", "testfind"),
};
string sqlSelect =
"SELECT null " +
"FROM " + tableName + " " +
"WHERE " + fieldName + " LIKE '%' + #Find + '%' ";
private DataTable ExecuteDynamic(string TableName,string FieldName, string Find)
{
string sqlSelect = "SELECT * FROM " + TableName +
" WHERE " + FieldName + " LIKE '%'" + Find + "'%' ";
using (connection = new SqlConnection(Strcon))
connection.Open();
{
using (cmd = new SqlCommand(sqlSelect, connection))
{
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = 60;
adpt = new SqlDataAdapter(cmd);
dt = new DataTable();
adpt.Fill(dt);
return (dt);
}
}
}

Categories