so this is my code
for (int i = 0; i < users_table.RowCount; ++i)
{
SQLDatabase.DatabaseRow row = users_table.GetRow(i); //get current ID.
if (userID == users_table.GetRow(i)["ID"]) //if userID is the same as it's in the row
{
row["ID"] = "0";
row["Name"] = "DELETED";
row["Username"] = "DELETED";
row["Password"] = "DELETED";
row["UserType"] = "DELETED";
row["LastLoginDate"] = "0";
row["LastLoginTime"] = "0";
users_table.Update(row);
}
}
My goal is to delete a row. Sadly I'm unable to insert NULL values etc., any idea how I could delete that row? I would like to add that I do not have .delete functions or anything in particular. I would be glad if you could tell me how to add them.
Thanks.
(This answer assumes you're using SQL Server)
You can easily execute SQL Commands using System.Data.SqlClient.
The connection string would be the connection details to your database instance. You can see some more examples of how to construct your connection string # Connection String Examples. Also, when you're deleting rows from your database you want to utilize the DELETE command not the UPDATE. More details can be found on DELETE (Transact-SQL)
public void deleteRow()
{
string connectionString = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password = myPassword; ";
string queryString = "DELETE FROM Test_Table WHERE ID = 5";
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
command.Connection.Open();
command.ExecuteNonQuery();
}
}
Related
I am very new to database queries and even more so, Oracle. I am also new to development work and, believe it or not, am creating this an for work purely out of frustration with the current process. Anyway, I am attempting to collect input from a multi-line text box and run a query. Each line corresponds to a single string that needs to be passed into the WHERE statement and the results will be dumped into a data table. Unfortunately, Oracle has still not released its developer tools for VS2019 so I am having to do this the harder way.
UPDATE # 2:
I have completely rebuilt the query since it was not running even when using known working code from another query. Below is what I have pieced together from various places on the interwebs. While debugging, it appears to parse and format the text correctly and pass it into the OracleParameter without issue. I am getting a Missing Expression error but I don't know what I am missing.
var connString =
ConfigurationManager.ConnectionStrings["dB"].ConnectionString;
string query = "SELECT col1, col2, col3, col4 FROM table WHERE col5 IN (";
using (OracleConnection conn = new OracleConnection(connString))
try
{
var input = "";
input = uniLookup.UniList;
var uniList = string.Join(",", Regex.Split(input, #"(?:\r\n|\n|\r)"));
string allParams = uniList;
string formattedParams = allParams.Replace(" ", string.Empty);
string[] splitParams = formattedParams.Split(',');
List<OracleParameter> parameters = new List<OracleParameter>();
using (OracleCommand cmd = new OracleCommand(query, conn))
{
for (int i = 0; i < splitParams.Length; i++)
{
query += #":Uni" + i + ",";
parameters.Add(new OracleParameter(":Uni" + i, splitParams[i]));
{
query = query.Substring(0, (query.Length - 1));
query += ')';
conn.Open();
using (OracleDataReader reader = cmd.ExecuteReader()) <==ERROR
{
if (!reader.HasRows)
{
while (reader.Read())
{
reader.Read();
{
MessageBox.Show(reader.GetString(1));
}
}
}
You can use IN in your where clause in this way to get rows from multiple values as:
string query = "SELECT dummyCol FROM dummytable WHERE altCol IN ("+text+");";
where you just have to change your text as text="'value1','value2','value3'"; this will not produce any syntax error.
You can convert your multi line text into same comma separated values using this :
foreach (String s in textBox1.Text.Split('\n'))
{
text +="'"+ s+"',";
}
text = text.TrimEnd(',');
this will help you achieve what you need. you can ask If there is any confusion.
Your final code will become :
public void GetData()
{
if (string.IsNullOrWhiteSpace(textbox1.Text) || textbox1.Text == "")
{
MessageBox.Show("Please Enter at least 1 Value and Try Again!");
}
else
{
System.Data.DataTable dt = new System.Data.DataTable();
// string[] lines = textbox1.Text.Split('\n');
string text = "";
foreach (String s in textBox1.Text.Split('\n'))
{
text += "'" + s + "',";
}
text = text.TrimEnd(',');
//Connection Credentials
string credentials = "Credentials";
string query = "SELECT dummyCol FROM dummytable WHERE altCol IN ("+text+");";
OracleConnection conn = new OracleConnection(credentials);
try
{
//Open The Connection
conn.Open();
using (OracleCommand cmd = new OracleCommand(query, conn))
{
//Call the Oracle Reader
using (OracleDataReader reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
MessageBox.Show("Unable to Retrieve Data");
return;
}
else if (reader.HasRows)
{
reader.Read();
DataRow row = dt.NewRow();
// create variables to accept reader data for each column
// insert data from query into each column here
dt.Rows.Add(row);
}
}
}
}
}
}
EDIT: I am not able to format my code below, if any one can fix it.
I am new to sql queries and still learning.
Table Name: CommissionSetupTable.
I want to display #Paisa if gross_amount is between the range of #FromRate and #ToRate
Below is my code:
string paisa;
private void load_commission_setup()
{
SqlCeConnection conn = null;
SqlCeCommand cmd = null;
SqlCeDataReader rdr = null;
try
{
conn =
new SqlCeConnection(
#"Data Source=|DataDirectory|\Database.sdf;Persist Security Info=False");
conn.Open();
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
gross_amount = double.Parse(purchaseBillTableDataGridView[10, rowindex].Value.ToString());
// Gross Amount is between the ranges of FromRate and ToRate.
cmd = new SqlCeCommand("SELECT Paisa FROM CommissionSetupTable WHERE='" + gross_amount.ToString() + "' BETWEEN #FromRate AND #ToRate;", conn);
rdr = cmd.ExecuteReader();
if (rdr == null)
{
}
else
{
while (rdr.Read())
{
paisa = rdr["Paisa"].ToString();
}
rdr.Close();
cmd.Dispose();
}
}
finally
{
conn.Close();
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
purchaseBillTableDataGridView[11, rowindex].Value = paisa;
}
}
The correct syntax to use here is the following
cmd = new SqlCeCommand(#"SELECT Paisa FROM CommissionSetupTable
WHERE #gross BETWEEN FromRate AND ToRate;", conn);
Notice that the two field names should not be prefixed with #, otherwise they will be considered parameters placeholders.
And now, before executing the command, add the parameter for the #gross placeholder
cmd.Parameters.Add("#gross", SqlDbType.Decimal).Value = gross_amount;
I don't know what is the exact datatype of the columns FromRate and EndRate, but
note that you should use the correct datatype for your parameter. Do not pass a string and expect the database engine do the conversion for you. (or worse concatenate your value to the rest of the sql using ToString()). This is always wrong also if sometime the database engine could understand your values.
EDIT
Also, following your comments below, it appears that this line is wrong
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
If your DataGridView has the property AllowUserToAddRow set to True then you want to use
int rowindex = purchaseBillTableDataGridView.Rows.Count - 2;
because the first line points to the empty row added to the DataGridView for inserting a new record.
Okay, I've built a SQL Server database which is being accessed and manipulated by an ASP.NET UI (which I have also developed) to allow others at work to search the DB easily. The database holds data on numerous locations where we have network equipment operating.
I have been asked to build into the UI the capability to query the database for multiple IP addresses - e.g. a user will enter into a textbox "192.168.1.0, 18.15.156.4", click enter and be presented with the results in the gridview. Multiple IP addresses will be separated with a ,.
The code below basically strips out space characters, looks for a , (to determine how many ips there are to query) and if found puts them into an array. A for loop then puts each array item into its own session variable, and from there they are ready to be queried:
protected void siteSearchButton_Click(object sender, EventArgs e)
{
//checks IP search textbox is empty
if (ipQueryTextBox.Text != null)
{
searchErrorLabel.Visible = false;
string addresses = ipQueryTextBox.Text;
//checks for any blank spaces in the addresses variable
if (addresses.Contains(" "))
{
addresses = addresses.Replace(" ", "");
}
//sceens for multiple search items by looking for a ','
if (addresses.Contains(","))
{
//declaring int variables to be used in each of the respective loops
int j = 0;
string[] IParray = addresses.Split(',');
//if i is equal to the length of the "addresses" variable, execute the for loop enclosed
foreach (string s in IParray)
{
Session["IP" + j] = IParray[j];
j = j + 1;
}
}
}
}
As the number of ips to be queried against the database is dynamic I have come to the conclusion that I will have to use C# code (which I'm okay with), but as far as what I've got so far below, I'm unsure how to go about querying the db 'x' amount of times using code presumably I'll need to use a while loop, is anyone able to offer some insight?
//****THE SQL COMMAND BELOW NEEDS ADAPTING TO ALLOW MULTIPLE QUERIES FOR EACH OF THE VALUES STORED IN IParray ---> each session variable
if()
{
//opens a new sqlconnection to read and populate edit textboxes from the Inventory database
using (SqlConnection connection = new SqlConnection("Data Source=localhost;Initial Catalog=Inventory;Integrated Security=True"))
{
//declares SQLCommand type named 'command' and assigns it a string value of SQL code
SqlCommand command =
new SqlCommand("select * from LOCATION WHERE IP_ADDRESS=#IP_ADDRESS", connection);
//outlines parameters
command.Parameters.Add("#IP_ADDRESS", System.Data.SqlDbType.VarChar);
command.Parameters["#IP_ADDRESS"].Value = Session["IP"+j];;
connection.Open();
//opens database connection
SqlDataReader read = command.ExecuteReader();
//while loop will convert each record to string value and print entry into textbox. Will continue untill it runs out of lines
while (read.Read())
{
}
read.Close();
}
}
Instead of using multiple queries, just use SQL's IN clause. It does require a little bit more work to set the query parameters though.
string[] ips = new string[] { "192.168.0.1", "192.168.0.2", "192.168.0.3" };
string[] parameters = ips.Select(
(ip, index) => "#ip" + index.ToString()
).ToArray();
string commandFormat = "SELECT * FROM LOCATION WHERE IP_ADDRESS IN ({0})";
string parameterText = string.Join(",", parameters);
string commandText = string.Format(commandFormat, parameterText);
using (SqlCommand command = new SqlCommand(commandText)) {
for(int i = 0; i < parameters.Length; i++) {
command.Parameters.AddWithValue(parameters[i], ips[i]);
}
}
In the above example, the generated command will be SELECT * FROM LOCATION WHERE IP_ADDRESS IN (#ip1,#ip2,#ip3), and the parameter values will be set accordingly.
(The above solution was very much inspired by this answer.)
First thing - why create multiple session objects when you needs just one to store the values?
I'd try to change your code like this:
if (ipQueryTextBox.Text != null)
{
searchErrorLabel.Visible = false;
string addresses = ipQueryTextBox.Text;
addresses = addresses.Replace(" ", "");
addresses = addresses.Replace(",", "','");
Session["addresses"] = addresses;
}
For the SQL part, you can now easily utilize SQL IN operator, documented here for instance: http://www.w3schools.com/sql/sql_in.asp
SqlCommand command = new SqlCommand("select * from LOCATION WHERE IP_ADDRESS IN (#IP_ADDRESSES)", connection);
command.Parameters.AddWithValue("IP_ADDRESSES", Session["addresses"]);
This should probably work, but I haven't tested it, so it may require some tweaking. Hope you get the idea.
why do you need parameters at all.
//get IP address from UI;
string IPAddress = ipQueryTextBox.Text; //e.g. "192.168.0.1,192.168.0.2,192.168.0.3"
string commandFormat = "SELECT * FROM LOCATION WHERE IP_ADDRESS IN ('" + string.Join("','", IPAddress.split(",")) + "')";
now execute the query
Thank you to everyone who has responded, here is the solution I came up with derived from the answers above:
protected void siteSearchButton_Click(object sender, EventArgs e)
{
//checks IP search textbox is empty
if (ipQueryTextBox.Text != null)
{
searchErrorLabel.Visible = false;
string addresses = ipQueryTextBox.Text;
//checks for any blank spaces in the addresses variable
if (addresses.Contains(" "))
{
addresses = addresses.Replace(" ", "");
}
//sceens for multiple search items by looking for a ','
if (addresses.Contains(","))
{
string[] IParray = addresses.Split(',');
string[] Parameters= IParray.Select((IP, index)=>"#ip"+ index.ToString()).ToArray();
string commandformat ="SELECT * FROM LOCATION WHERE IP_ADDRESS IN ({0})";
string parametertxt= string.Join(",",Parameters);
string commandtxt= string.Format(commandformat,parametertxt);
//creates an SQL connection "connection" opens the connection creates the sql command to be executed & binds and refreshes the gridview
using (SqlConnection connection = new SqlConnection("Data Source=localhost;Initial Catalog=Inventory;Integrated Security=True"))
{
SqlDataReader reader = null;
connection.Open();
SqlCommand command = new SqlCommand(commandtxt, connection);
for(int i =0; i<Parameters.Length; i++)
{
command.Parameters.AddWithValue(Parameters[i],IParray[i]);
}
reader = command.ExecuteReader();
browseSiteGridView.DataSource = reader;
browseSiteGridView.DataBind();
reader.Close();
connection.Close();
}
}
else
{
//creates an SQL connection "connection" opens the connection creates the sql command to be executed & binds and refreshes the gridview
string commandtxt="SELECT * FROM LOCATION WHERE IP_ADDRESS ='"+addresses+"'";
using (SqlConnection connection = new SqlConnection("Data Source=localhost;Initial Catalog=Inventory;Integrated Security=True"))
{
SqlDataReader reader = null;
connection.Open();
SqlCommand command = new SqlCommand(commandtxt, connection);
reader = command.ExecuteReader();
browseSiteGridView.DataSource = reader;
browseSiteGridView.DataBind();
reader.Close();
connection.Close();
}
}
}
I have this legacy code :
private void conecta()
{
if (conexao.State == ConnectionState.Closed)
conexao.Open();
}
public List<string[]> get_dados_historico_verificacao_email_WEB(string email)
{
List<string[]> historicos = new List<string[]>();
conecta();
sql =
#"SELECT *
FROM historico_verificacao_email
WHERE nm_email = '" + email + #"'
ORDER BY dt_verificacao_email DESC, hr_verificacao_email DESC";
com = new SqlCommand(sql, conexao);
SqlDataReader dr = com.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
string[] dados_historico = new string[6];
dados_historico[0] = dr["nm_email"].ToString();
dados_historico[1] = dr["dt_verificacao_email"].ToString();
dados_historico[1] = dados_historico[1].Substring(0, 10);
dados_historico[2] = dr["hr_verificacao_email"].ToString();
dados_historico[3] = dr["ds_tipo_verificacao"].ToString();
sql =
#"SELECT COUNT(e.cd_historico_verificacao_email) QT
FROM emails_lidos e
WHERE e.cd_historico_verificacao_email =
'" + dr["cd_historico_verificacao_email"].ToString() + "'";
tipo_sql = "seleção";
conecta();
com2 = new SqlCommand(sql, conexao);
SqlDataReader dr3 = com2.ExecuteReader();
while (dr3.Read())
{
//quantidade de emails lidos naquela verificação
dados_historico[4] = dr3["QT"].ToString();
}
dr3.Close();
conexao.Close();
//login
dados_historico[5] = dr["cd_login_usuario"].ToString();
historicos.Add(dados_historico);
}
dr.Close();
}
else
{
dr.Close();
}
conexao.Close();
return historicos;
}
I have created two separates commands to correct the issue, but it still continues: "There is already an open DataReader associated with this Command which must be closed first".
An additional info: the same code is working in another app.
Just add the following in your connection string:
MultipleActiveResultSets=True;
The optimal solution could be to try to transform your solution into a form where you don't need to have two readers open at a time. Ideally it could be a single query. I don't have time to do that now.
If your problem is so special that you really need to have more readers open simultaneously, and your requirements allow not older than SQL Server 2005 DB backend, then the magic word is MARS (Multiple Active Result Sets). http://msdn.microsoft.com/en-us/library/ms345109%28v=SQL.90%29.aspx. Bob Vale's linked topic's solution shows how to enable it: specify MultipleActiveResultSets=true in your connection string. I just tell this as an interesting possibility, but you should rather transform your solution.
in order to avoid the mentioned SQL injection possibility, set the parameters to the SQLCommand itself instead of embedding them into the query string. The query string should only contain the references to the parameters what you pass into the SqlCommand.
You can get such a problem when you are two different commands on same connection - especially calling the second command in a loop. That is calling the second command for each record returned from the first command. If there are some 10,000 records returned by the first command, this issue will be more likely.
I used to avoid such a scenario by making it as a single command.. The first command returns all the required data and load it into a DataTable.
Note: MARS may be a solution - but it can be risky and many people dislike it.
Reference
What does "A severe error occurred on the current command. The results, if any, should be discarded." SQL Azure error mean?
Linq-To-Sql and MARS woes - A severe error occurred on the current command. The results, if any, should be discarded
Complex GROUP BY on DataTable
I suggest creating an additional connection for the second command, would solve it. Try to combine both queries in one query. Create a subquery for the count.
while (dr3.Read())
{
dados_historico[4] = dr3["QT"].ToString(); //quantidade de emails lidos naquela verificação
}
Why override the same value again and again?
if (dr3.Read())
{
dados_historico[4] = dr3["QT"].ToString(); //quantidade de emails lidos naquela verificação
}
Would be enough.
I bet the problem is being shown in this line
SqlDataReader dr3 = com2.ExecuteReader();
I suggest that you execute the first reader and do a dr.Close(); and the iterate historicos, with another loop, performing the com2.ExecuteReader().
public List<string[]> get_dados_historico_verificacao_email_WEB(string email)
{
List<string[]> historicos = new List<string[]>();
conecta();
sql = "SELECT * FROM historico_verificacao_email WHERE nm_email = '" + email + "' ORDER BY dt_verificacao_email DESC, hr_verificacao_email DESC";
com = new SqlCommand(sql, conexao);
SqlDataReader dr = com.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
string[] dados_historico = new string[6];
dados_historico[0] = dr["nm_email"].ToString();
dados_historico[1] = dr["dt_verificacao_email"].ToString();
dados_historico[1] = dados_historico[1].Substring(0, 10);
//System.Windows.Forms.MessageBox.Show(dados_historico[1]);
dados_historico[2] = dr["hr_verificacao_email"].ToString();
dados_historico[3] = dr["ds_tipo_verificacao"].ToString();
dados_historico[5] = dr["cd_login_usuario"].ToString();
historicos.Add(dados_historico);
}
dr.Close();
sql = "SELECT COUNT(e.cd_historico_verificacao_email) QT FROM emails_lidos e WHERE e.cd_historico_verificacao_email = '" + dr["cd_historico_verificacao_email"].ToString() + "'";
tipo_sql = "seleção";
com2 = new SqlCommand(sql, conexao);
for(int i = 0 ; i < historicos.Count() ; i++)
{
SqlDataReader dr3 = com2.ExecuteReader();
while (dr3.Read())
{
historicos[i][4] = dr3["QT"].ToString(); //quantidade de emails lidos naquela verificação
}
dr3.Close();
}
}
return historicos;
Add MultipleActiveResultSets=true to the provider part of your connection string. See the example below:
<add name="DbContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=dbName;Persist Security Info=True;User ID=userName;Password=password;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
Try to combine the query, it will run much faster than executing an additional query per row.
Ik don't like the string[] you're using, i would create a class for holding the information.
public List<string[]> get_dados_historico_verificacao_email_WEB(string email)
{
List<string[]> historicos = new List<string[]>();
using (SqlConnection conexao = new SqlConnection("ConnectionString"))
{
string sql =
#"SELECT *,
( SELECT COUNT(e.cd_historico_verificacao_email)
FROM emails_lidos e
WHERE e.cd_historico_verificacao_email = a.nm_email ) QT
FROM historico_verificacao_email a
WHERE nm_email = #email
ORDER BY dt_verificacao_email DESC,
hr_verificacao_email DESC";
using (SqlCommand com = new SqlCommand(sql, conexao))
{
com.Parameters.Add("email", SqlDbType.VarChar).Value = email;
SqlDataReader dr = com.ExecuteReader();
while (dr.Read())
{
string[] dados_historico = new string[6];
dados_historico[0] = dr["nm_email"].ToString();
dados_historico[1] = dr["dt_verificacao_email"].ToString();
dados_historico[1] = dados_historico[1].Substring(0, 10);
//System.Windows.Forms.MessageBox.Show(dados_historico[1]);
dados_historico[2] = dr["hr_verificacao_email"].ToString();
dados_historico[3] = dr["ds_tipo_verificacao"].ToString();
dados_historico[4] = dr["QT"].ToString();
dados_historico[5] = dr["cd_login_usuario"].ToString();
historicos.Add(dados_historico);
}
}
}
return historicos;
}
Untested, but maybee gives some idea.
I have a database that contains a table named "User(login,password,firstname,lastname)" . And I need to make login page . I've watched some tutorials , but it didn't help . I need to check if login and password exist in the database . and then redirect(if correct) to other page . This is what I already did:
OleDbConnection con = new OleDbConnection();
public bool check()
{
con.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Volodia\Documents\WebSiteDatabase.accdb";
con.Open();
string commandstring = "SELECT login,password FROM User";
//objadapter = new SqlDataAdapter(CommandString, sqlconn.ConnectionString);
OleDbDataAdapter objadapter = new OleDbDataAdapter(commandstring, con.ConnectionString);
DataSet dataset = new DataSet();
objadapter.Fill(dataset, "User");// it shows "Syntax error in FROM clause." here
DataTable datatable = dataset.Tables[0];
for (int i = 0; i < datatable.Rows.Count; i++)
{
string unam = datatable.Rows[i]["login"].ToString();
string upwd = datatable.Rows[i]["password"].ToString();
if ((unam == TextBox1.Text)&&(upwd==TextBox2.Text))
{
return true;
}
}
return false;
}
protected void Button1_Click(object sender, EventArgs e)
{
if (check() == true)
{
Response.Redirect("WebForm2.aspx");
}
}
The word PASSWORD is a reserved keyword for MS-Access Jet SQL. If you want to use it you need to enclose it in square brackets, the same for USER
string commandstring = "SELECT login, [password] FROM [User]";
This will resolve the immediate problem of the Syntax Error but let me add some other code to show a different approach
public bool check()
{
string conString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Volodia\Documents\WebSiteDatabase.accdb";
using(OleDbConnection con = new OleDbConnection(conString)
{
con.Open();
string commandstring = "SELECT count(*) as cntUser FROM [User] " +
"WHERE login = ? AND [password] = ?";
using(OleDbCommand cmd = new OleDbCommand(commandstring, con))
{
cmd.Parameters.AddWithValue("#p1", TextBox1.Text);
cmd.Parameters.AddWithValue("#p2", TextBox2.Text);
int result = (int)cmd.ExecuteScalar();
if(result > 0)
return true;
}
}
return false;
}
First, do not use a global connection object but create and use the
connection only when needed.
Second, encapsulate the disposable objects like the connection and
the command with the using statement that will ensure a correct close
and dispose,
Third, pass the login and the password as conditions for the where
clause (more on this later)
Fourth, use the parametrized query to avoid syntax errors and sql
injection
Usually is not a good practice to store a password in clear text inside the database. You need to store only the hash of the password and recalculate this hash every time you need to check the user authenticity