I am using SQL Server database and there's a column named Cell(VARCHAR) data type. While reading using reader.Read() I get the Conversion error. Can anyone kindly explain the reason for the error?
This is my code:
string myConnection = dbController.connectionString;
string query1 = "SELECT ID, Name from Manager Where Cell = " + managerNo.Text;
using (var conn = new SqlConnection(myConnection))
using (var cmd = new SqlCommand(query1, conn))
{
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
managerID = reader.GetString(0);
mgrID.Text = managerID;
managerNames.Text = reader.GetString(1);
}
conn.Close();
}
I am reading the value from a textbox (managerNo). I have tested the query on SQL Server Management Studio as well:
select Name, DOB
from Contact
where Cell = 1233453411
When I use Cell = 1233453411 without the value as string I get the conversion error, however using Cell = '1233453411' as a string the result is fetched.
Whats the reason for this and how to solve this issue.
Thanks.
This is a comparison between two different types, a string and an integer:
where Cell = 1233453411
SQL Server has to decide which type to use. It decides on the more restrictive type, which is the number. So, the string gets converted to a number.
Say, you have a cell phone in New York with a number like: 917-555-5555. Well, that becomes a number like 9,175,555,555 and this exceeds the value of the maximum integer. Hence, you would get a conversion overflow.
The moral: Always use similar types when making comparisons.
EDIT:
What should you do? Don't store telephone numbers as numbers; they should be stored as strings (for instance, leading zeroes can be important).
If could do a quick-and-dirty and put single quotes around the value of the parameter. But, what you should really do is change your SQL code to use a parameter with a string type. It is bad programming to just stuff values (particularly user input) into a query string.
Your code is working fine in SQL Server 2008 R2. (Below is tested code)
private void button1_Click(object sender, EventArgs e)
{
string str = "Server=.\\SQL2008R2;Database=Practice;User ID=sa;Password=123;Trusted_Connection=True;Connection Timeout=0";
string query1 = "SELECT * from tblTest Where Cell = " + textBox1.Text;
using (var conn = new SqlConnection(str))
using (var cmd = new SqlCommand(query1, conn))
{
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
string aa = reader.GetString(0);
}
conn.Close();
}
Otherwise using can change you query like in below format.
string query1 = "SELECT * from tblTest Where Cell = '" + textBox1.Text + "' ";
Thanks
Related
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 am trying to store each row of a access database, based on column Veh_ID. The found data may or may not be based on multiple rows. The code I am currently using can copy single row but if there are multiple results I can only get the first result. Can anyone please help me on this? I am noob when it comes to database. I tried to search Google but no one seems to be needing what I need. Here's the code I'm using:
string cmd1 = "SELECT * FROM Veh_checkup WHERE Veh_ID = " + veh_idd + "";
OleDbCommand cmd = new OleDbCommand(cmd1, con);
OleDbDataReader read = cmd.ExecuteReader();
read.Read();
veh_id=null;
int i=0;
foreach (var a in read)
{
try
{
veh_id = veh_id + " " + read[i].ToString();
}
catch { }
i++;
}
There are a few things I would point out, some specific to your question, some not:
USE PARAMETERISED QUERIES
Use OleDbDataReader.Read() to move to the next record.
Use a StringBuilder to concatenate strings in a loop, using string = string + "something" will create a new string on the heap with each iteration
Use using blocks on Disposable objects
catch { } is not good practice. You will never know an error occurred. At the very least you should log the error somewhere so you know you need to fix something.
OleDbDataReader[i] will get the data from column i for the current record being read, not the data from row i
Don't use SELECT * in production code, especially if you are only using 1 column. It is unnecessary data retrieval from the database and also unnecessary network traffic.
USE PARAMETERISED QUERIES
Okay, I know I included using parameterised queries twice, but that is how strongly I feel about it!
With the above changes made, your full code will become something like:
static string GetStringData(string vehID)
{
StringBuilder builder = new StringBuilder();
string cmd1 = "SELECT Column1 FROM Veh_checkup WHERE Veh_ID = #VehID";
using (OleDbConnection con = new OleDbConnection("YourConnectionString"))
using (OleDbCommand cmd = new OleDbCommand(cmd1, con))
{
con.Open();
cmd.Parameters.AddWithValue("#VehID", vehID);
using (OleDbDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
builder.Append(" " + reader.GetString(0));
}
}
}
return builder.ToString();
}
You are using the datareader in a wrong way. Instead of calling it once like you do, you have to call the datareader in a while loop like this:
while(theDataReader.Read())
{
// do your stuff in a loop now
}
So using this approach in your code would look something like this:
string cmd1 = "SELECT * FROM Veh_checkup WHERE Veh_ID = " + veh_idd + "";
OleDbCommand cmd = new OleDbCommand(cmd1, con);
OleDbDataReader read = cmd.ExecuteReader();
veh_id=null;
con.Open();
while(read.Read()) //your reader
{
try
{
veh_id = veh_id + " " + read[i].ToString();
}
catch { }
}
I'm trying to populate a text box with a forename and surname using the code below:
using (OleDbConnection connName = new OleDbConnection(strCon))
{
String sqlName = "SELECT forename, Surname FROM customer WHERE [customerID]=" + txtCustomerID.Text;
// Create a command to use to call the database.
OleDbCommand commandname = new OleDbCommand(sqlName, connName);
connName.Open();
// Create a reader containing the results
using (OleDbDataReader readerName = commandname.ExecuteReader())
{
readerName.Read(); // Advance to the first row.
txtName.Text = readerName[0].ToString();
}
connName.Close();
}
However I'm getting the error: OleDbException was unhandled.
"no required values for one of more required parameters"
at the ExecuteReader and I'm not sure how to go about fixing this.
EDIT: this code below is nearly the exact same bar for the information in the query but this exception is not coming up for it.
string strCon = Properties.Settings.Default.PID2dbConnectionString;
using (OleDbConnection conn = new OleDbConnection(strCon))
{
String sqlPoints = "SELECT points FROM customer WHERE [customerID]=" + txtCustomerID.Text;
conn.Open();
// Create a command to use to call the database.
OleDbCommand command = new OleDbCommand(sqlPoints, conn);
// Create a reader containing the results
using (OleDbDataReader reader = command.ExecuteReader())
{
reader.Read(); // Advance to the first row.
txtPoints.Text = reader[0].ToString(); // Read the contents of the first column
}
conn.Close();
}
The usual reason for this is a null or empty string i.e. txtCustomerID.Text has no value so the query being sent to the server is:
SELECT forename, Surname FROM customer WHERE [customerID]=
You can avoid errors like this and SQL Injection, use strongly typed parameters and avoid data truncation using parameterised queries (I have assumed customer ID is an int field)
using (OleDbConnection connName = new OleDbConnection(strCon))
{
String sqlName = "SELECT forename, Surname FROM customer WHERE customerID = #CustomerID";
// Create a command to use to call the database.
using (OleDbCommand commandname = new OleDbCommand(sqlName, connName))
{
//Check the input is valid
int customerID = 0;
if (!int.TryParse(txtCustomerID.Text, out customerID))
{
txtName.Text = "Customer ID Text box is not an integer";
return;
}
connName.Open();
// Add the parameter to the command
commandname.Parameters.Add("#CustomerID", OleDbType.Integer).Value = customerID;
// Create a reader containing the results
using (OleDbDataReader readerName = commandname.ExecuteReader())
{
readerName.Read(); // Advance to the first row.
txtName.Text = readerName[0].ToString();
}
connName.Close();
}
}
You have to encode parameters used in string queries.
String sqlName = String.Format("SELECT forname, Surname FROM customer WHERE customerID={0}",txtCustomerID.Text);
But I advice you against using SQL queries hard-coded in strings. Its easy way for SQL Injection attack. You should use parammeters instead.
I have the fol code
string user = "new user";
DataSet myDS = new DataSet();
string sql = string.Format("Select Counter,Occupants From Rooms where Room = '{0}'",room);
SqlDataAdapter dAdapt = new SqlDataAdapter(sql, cnn);
dAdapt.Fill(myDS, "Rooms");
foreach (DataTable dt in myDS.Tables)
{
int var =(int) dt.Rows[0].ItemArray[0];
var--;
dt.Rows[0].ItemArray[0] = var;
String occups = dt.Rows[0].ItemArray[1].ToString();
occups += user;
dt.Rows[0].ItemArray[1] = occups;
}
dAdapt.Update(myDS,"Rooms");
I'm retrieving a single row with two columns-- Counter(small int type) and Occupants(text type). I get an error saying that the data types text and var char are incompatible in the equal to operator But the error is pointed to the line dAdapt.Fill(myDS, "Rooms"); which is weird. What's wrong here? And I'm pretty sure that the db connection is open as I've checked it by printing the connection status.
This won't work anyway unless you have specified an Update-Command for the DataAdaper.
I would not load the record into memory to update it. Meanwhile it could have been changed from another transaction. It's inefficient anyway. Instead i would use a single update-command:
string updateSql = #"
UPDATE ROOMS SET
Counter = Counter + 1,
Occupants = Occupants + ',' + #newUser
WHERE
Room = #Room";
using(var con = new SqlConnection(connectionString))
using (var updateCommand = new SqlCommand(updateSql, con))
{
updateCommand.Parameters.AddWithValue("#newUser", user);
updateCommand.Parameters.AddWithValue("#Room", room);
con.Open();
updateCommand.ExecuteNonQuery();
}
The problem is in your select, because you can use the syntax, that Room = 'something', because text is not compatible with =.
Use LIKE instead of equal sign (=).
Fixed query should look like:
SELECT Counter,Occupants FROM Rooms WHERE Room LIKE '{0}'
But I recommand to use SqlParameters instead of string.Format, because it is not secure.