I am trying to get the result from a select command:
string strName = dtTable.Rows[i][myName].ToString();
string selectBrand = "SELECT [brand] FROM [myTable] WHERE [myName] = '" + strName + "'";
SqlCommand sqlCmdSelectBrand = new SqlCommand(selectBrand , sqlConn);
sqlCmdSelectBrand .Connection.Open();
sqlCmdSelectBrand .ExecuteNonQuery();
string newBrand = Convert.ToString(sqlCmdSelectBrand .ExecuteScalar());
sqlCmdSelectBrand .Connection.Close();
The select works, I have executed it in SQL Studio, but it does not assign to my variable on the second to last line. Nothing gets assigned to that variable when I debug it...
Any advice?
Your approach to read data returned from a SELECT query is (in this particular context) a bit wrong. Usually you call ExecuteReader of the SqlCommand instance to get back your data.
string strName = dtTable.Rows[i][myName].ToString();
string selectBrand = "SELECT [brand] FROM [myTable] WHERE [myName] = #name";
using(SqlCommand sqlCmdSelectBrand = new SqlCommand(selectBrand , sqlConn))
{
sqlCmdSelectBrand.Parameters.Add(
new SqlParameter("#name", SqlDbType.NVarChar)).Value = strName;
sqlCmdSelectBrand .Connection.Open();
using(SqlDataReader reader = sqlCmdSelectBrand.ExecuteReader())
{
if(reader.HasRows)
{
reader.Read();
string newBrand = reader.GetString(reader.GetOrdinal("Brand"));
..... work with the string newBrand....
}
else
// Message for data not found...
sqlCmdSelectBrand .Connection.Close();
}
}
In your context, the call to ExecuteNonQuery is not required because it doesn't return anything from a SELECT query. The call to ExecuteScalar should work if you have at least one record that match to the WHERE condition
Notice also that you should always use a parameterized query when building an sql command text. Also if you think to have full control of the inputs, concatenating string is the open door to Sql Injection
Related
This is my code, and I want to be able to search for a name, and then pull from the database the name, status, member_id into the textboxes in my form.
I got the name to work but how do I get the other columns and parse the output into the textboxes with the additional columns (member_id, status)? Let's say the other textboxes have the standard name such as textbox2, 3, 4...
string connetionString = null;
SqlConnection connection;
SqlCommand command;
string sql = null;
string sql1 = null;
SqlDataReader dataReader;
connetionString = "Data Source=......"
sql = "SELECT NAME FROM Test_Employee WHERE Name LIKE '" + textBox1.Text.ToString() + "%'";
connection = new SqlConnection(connetionString);
{
connection.Open();
command = new SqlCommand(sql, connection);
dataReader = command.ExecuteReader();
while (dataReader.Read())
{
textBox9.Text = dataReader[0].ToString();
textBox7.Text = dataReader[0].ToString();
}
connection.Close();
}
Are the fields Member_Id and Status also in the table Test_Employee? You can add them in your Select statement and get them from your SqlReader, like the code below (assuming you are using c#7 and below). You may copy and paste this code.
var connectionString = "";
var sql = #"SELECT TOP 1 Name, Member_Id, Status
FROM Test_Employee
WHERE Name LIKE #name + '%'";
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.Add("name", SqlDbType.NVarChar, 100).Value = textBox1.Text.ToString();
connection.Open();
var reader = command.ExecuteReader();
if (reader.Read())
{
textBox9.Text = dataReader["Name"].ToString();
textBox7.Text = dataReader["Name"].ToString();
textBox2.Text = dataReader["Member_Id"].ToString();
textBox3.Text = dataReader["Status"].ToString();
}
}
You will notice that instead of including the Textbox1.Text's value in your Select statement, it is added as a parameter in the SQLCommand object's Parameters. In this way your query is protected from SQL Injection. If you want to learn more, you can search c# sqlcommand parameters and why it is very important to build data access code this way.
Also, notice that I added Top 1 in your Select statement, and instead of using while, I am using if. This is because a textbox can only hold 1 result at a time in a comprehensible way. If you meant to show multiple results clearly, you need to use a different control other than a TextBox.
The using statements allow you to dispose the connection, so you don't have to call connection.Close().
I am inserting a data row into my SQL Server database and then I want to query the data to get the unique identifier from the inserted row but my SqlDataReader is returning an empty dataset. I am thinking it maybe that the transaction hasn't been committed or something like that but I am not sure. I do not get an error.
Here is my code:
try
{
strQuery = "INSERT INTO clientnames VALUES(NEWID(),'" + txtACLastName.Text + "','" + txtACFirstName.Text + "'," + 1 + ")";
using (SqlCommand sqlInsertCmd = new SqlCommand(strQuery, sqlConn))
{
intQueryResult = sqlInsertCmd.ExecuteNonQuery();
if (intQueryResult == 0)
{
blnSuccess = false;
goto InsertClientNamesError;
}
else
{
blnSuccess = true;
}
sqlInsertCmd.Dispose();
}
if (blnSuccess)
{
strQuery = "select clientID from clientnames where firstname = '" + txtACFirstName.Text + "' and lastname = '" + txtACLastName.Text + "'";
using (SqlCommand sqlSelectCmd = new SqlCommand(strQuery, sqlConn))
{
SqlDataReader sqlDataRead = sqlSelectCmd.ExecuteReader();
while (sqlDataRead.Read())
{
strClientID = sqlDataRead.ToString();
}
sqlDataRead.Close();
sqlSelectCmd.Dispose();
}
}
}
catch (Exception exQuery)
{
System.Windows.MessageBox.Show("InsertClientNames: Error, " + exQuery.Message + ", has occurred.");
}
You are not getting the desired result because perhaps the SqlConnection is not opened explicitly (just a guess hard to tell without having full code). But this link shows you how to read from reader --> https://msdn.microsoft.com/en-us/library/haa3afyz(v=vs.110).aspx
But I suggest that you Please do not do it this way. Reason is you are making Two round trips to the DB Server when only one would have done the job for you IF you were using stored procedures. Also you are exposing yourselves to SQL Injection attacks as you are not parameterizing your queries.
Stored procedure:
CREATE PROCEDURE dbo.INS_clientnames
(
#FirstName varchar(100),
#LastName varchar(100),
#NewID int out
)
AS
BEGIN
Declare #Err int
set #NewID = NewID() -- Get the New ID and store it in the variable ( #NewID ) that the SP will return back to the caller
INSERT INTO clientnames values (#NewID , #FirstName , #LastName)
SET #Err = ##ERROR
IF #Error <> 0 -- Check If there was an error
Begin
SET #NewID = -1 -- Indicates that there was an error. You could log this into a Log Table with further details like error id and name.
END
RETURN
END
C# code to execute the above stored procedure and get the NewID:
using(SqlConnection conn = new SqlConnection(connectionString ))
{
using(SqlCommand cmd = new SqlCommand("dbo.INS_clientnames", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
// set up the parameters that the Stored Procedure expects
cmd.Parameters.Add("#FirstName", SqlDbType.VarChar, 100);
cmd.Parameters.Add("#LastName" , SqlDbType.VarChar, 100);
cmd.Parameters.Add("#NewId" , SqlDbType.Int).Direction = ParameterDirection.Output;
// set parameter values that your code will send to the SP as parameter values
cmd.Parameters["#FirstName"].Value = txtACFirstName.Text ;
cmd.Parameters["#LastName"].Value = txtACLastName.Text ;
// open connection and execute stored procedure
conn.Open();
cmd.ExecuteNonQuery();
// read output value from #NewId
int NewID = Convert.ToInt32(cmd.Parameters["#NewId"].Value);
}
}
Add the following line to your stored procedure that inserts the record
SELECT SCOPE_IDENTITY()
This will return the last identity value inserted in that table.
And use cmd.ExecuteScalar() instead of ExecuteNonQuery()
ExecuteScalar() executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored. [More info][1]
I see two approaches to do this:
either you generate the new GUID on the client side in your C# code and pass it into the query - then you already know what the new id is going to be, so you don't need to do a second query to get it:
you create your GUID on the server side and return it to the caller using the OUTPUT clause in your query
Approach #1:
// define connection string and query
string connStr = "--your connection string here--";
string query = "INSERT INTO dbo.Clients(ClientID, FirstName, LastName) VALUES(#ID, #First, #Last);";
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand(query, conn))
{
// create the GUID in C# - this is the ID - no need to go get it again - this *IS* the id
Guid id = Guid.NewGuid();
// set the parameters
cmd.Parameters.Add("#ID", SqlDbType.UniqueIdentifier).Value = id;
cmd.Parameters.Add("#First", SqlDbType.VarChar, 50).Value = "Peter";
cmd.Parameters.Add("#Last", SqlDbType.VarChar, 50).Value = "Miller";
// open connection, execute query, close connection
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
Approach #2:
// define connection string and query
string connStr = "--your connection string here--";
// query has an "OUTPUT" clause to return a newly inserted piece of data
// back to the caller, just as if a SELECT had been issued
string query = "INSERT INTO dbo.Clients(ClientID, FirstName, LastName) OUTPUT Inserted.ClientID VALUES(NEWID(), #First, #Last);";
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand(query, conn))
{
// set the parameters - note: you do *NOT* send in a GUID value - the NEWID() will create one automatically, on the server
cmd.Parameters.Add("#First", SqlDbType.VarChar, 50).Value = "Frank";
cmd.Parameters.Add("#Last", SqlDbType.VarChar, 50).Value = "Brown";
// open connection
conn.Open();
// execute query and get back one row, one column - the value in the "OUTPUT" clause
object output = cmd.ExecuteScalar();
Guid newId;
if (Guid.TryParse(output.ToString(), out newId))
{
//
}
conn.Close();
}
string que = "SELECT Name FROM StudentInfo where StudentNo=textBox1.Text ";
Every time I run this it always says that
"The multi-part identifier "textBox1.Text" could not be bound".
How do I fix this?
You need to make the query include the value from the textbox. SQL Server doesn't know anything about your textbox - you've just provided the text textBox1.Text as if it refers to something that SQL Server knows about. However, you shouldn't include the value from your textbox in the SQL itself...
Instead, you should parameterize your SQL, and set the parameter from your textbox as a value to be sent alongside the SQL when you execute the query:
// Assuming an open connection...
int studentNo = int.Parse(textBox1.Text);
string sql = "SELECT Name FROM StudentInfo where StudentNo=#student_no";
using (var command = new SqlCommand(conn, sql))
{
command.Parameters.Add("#student_no", SqlDbType.Int).Value = studentNo;
// Execute the command as normal
}
This assumes that the type of StudentNo in your database is Int, of course - adjust accordingly (along with what you do with textBox1.Text - I'm currently parsing it as an int).
You should always parameterize your SQL rather than trying include the value within the SQL itself, for three important reasons:
It protects against SQL Injection Attacks
It avoids unnecessary conversions, and gives you more control over the conversions you do need
It typically makes it easier to read the SQL (as there isn't string concatenation code etc involved) so you can find issues with that more simply
You should be parameterizing your query:
string que = "SELECT Name FROM StudentInfo WHERE StudentNo = #StudentNo"
using (SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["connection"].ConnectionString))
{
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.Add("#StudentNo", SqlDbType.VarChar, 50).Value = textBox1.Text;
//If StudentNo is Int
//command.Parameters.Add("#StudentNo", SqlDbType.Int).Value = (int) textBox1.Text;
connection.Open();
string veri = Convert.ToString(command.ExecuteScalar());
return veri;
}
}
Use this :
string strQuery = "SELECT Name FROM StudentInfo where StudentNo= #studentno";
SqlCommand cmd = new SqlCommand(strQuery);
cmd.Parameters.AddWithValue("#studentno", textBox1.Text.Trim());
I really dont understand your question but the query should be
string que = "SELECT Name FROM StudentInfo where StudentNo= '" + textBox1.Text + "';";
If the StudentNo is Varchar in the DB. or else
string que = "SELECT Name FROM StudentInfo where StudentNo=" + textBox1.Text + ";";
Where as you should go for parameterized query like this
using (SqlCommand command = new SqlCommand(
"SELECT Name FROM StudentInfo where StudentNo=#No", connection))
{
command.Parameters.Add(new SqlParameter("No", textBox1.Text));
SqlDataReader reader = command.ExecuteReader();
}
Here is my Query:
string Select = "Update DC set Password = '" + txtPass.Text + "' WHERE ID ="+Convert.ToInt32(cbxDocs.SelectedIndex + 1);
con = new OleDbConnection();
this.readconfile = new ReadConfigFile();
con.ConnectionString = this.readconfile.ConfigString(ConfigFiles.ProjectConfigFile);
con.Open();
cmd = new OleDbCommand(Select, con);
cmd.Connection = con;
cmd.ExecuteNonQuery();
con.Close();
I don't know what is wrong but it gives me an error message that "Syntax error in UPDATE STATEMENT".
I have two fields in my table 'DC' ID and Password, nothing else.
PASSWORD is reserve word enclose it in square brackets like [Password], so your query should start like:
"Update DC set [Password]....
Consider using parameterized query, this will save you from Sql Injection
I think u don't need the ' on ur query and Password is reserved in almost every ddb.
And you could use parameters to avoid the concat with the +
Ex.
string pass = TxtPass.Text;
int s = cbxDocs.SelectedIndex+1;
string Select = "Update DC set Password = #a WHERE ID = #o";
OleDbCommand cmd = new OleDbCommand(Select, conn);
cmd.Paramaters.AddWithValue("#a", pass);
cmd.Parameters.AddWithValue("#o", s);
//everything else....
I have this SQL that works if i just execute on Oracle SQL Developer:
SELECT * FROM MYTABLE
WHERE LOWER(TRANSLATE(DESCRIPTION, 'âáàãêéèîíìôóòõûúùç', 'aaaaeeeiiioooouuuc'))
LIKE LOWER(TRANSLATE('%são paulo%', 'âáàãêéèîíìôóòõûúùç', 'aaaaeeeiiioooouuuc'))
But when is execute on C# code, wont work. The result always is 0.
string translate = "'âáàãêéèîíìôóòõûúùç', 'aaaaeeeiiioooouuuc'";
string query = string.Format("SELECT * FROM {0}
WHERE LOWER(TRANSLATE(DESCSITE, {2}))
LIKE LOWER(TRANSLATE({1}, {2}))",
TABLE, string.Format("'%{0}%'", str.ToLower()), translate);
UPDATE
This is how show in the breakpoint:
SELECT * FROM PROD
WHERE TRANSLATE(LOWER(DESCSITE), 'âáàãêéèîíìôóòõûúùç', 'aaaaeeeiiioooouuuc')
LIKE TRANSLATE(LOWER('%macarrão%'), 'âáàãêéèîíìôóòõûúùç', 'aaaaeeeiiioooouuuc')
And the same problem. Works on Oracle SQL Developer bu wont on C# code.
UPDATE
I tried this, but but in this case is not working to.
string query = string.Format("SELECT * FROM {0}
WHERE LOWER(TRANSLATE(DESCSITE, {1}))
LIKE LOWER(TRANSLATE(:DESCSITE, {1}))", TABLE, translate);
List<OracleParameter> parameters = new List<OracleParameter>();
parameters.Add(new OracleParameter(":DESCSITE", string.Format("'%{0}%'", str)));
If I only try this, i know tha will work, but I have to check the others things.
string query = string.Format(#"SELECT * FROM {0} WHERE CODIPROD = :CODIPROD", TABLE);
List<OracleParameter> parameters = new List<OracleParameter>();
parameters.Add(new OracleParameter(":CODIPROD", id));
UPDATE
I'm using for retun:
OracleCommand command;
command.ExecuteReader();
UPDATE
I tried put Unicode=True on the ConnectionString but nothing
UPDATE
This is how I execute the query. Everything works fine with characters without accents:
OracleConnection connection = new OracleConnection();
connection.Open();
OracleTransaction transaction;
transaction = connection.BeginTransaction();
OracleCommand command;
command = connection.CreateCommand();
command.Transaction = transaction;
command.CommandText = commandText;
OracleParameter parameter;
command.Parameters.Add(parameter);
reader = command.ExecuteReader();
while (reader.Read())
{
// Get data
}
So, the last try (yesterday 5 pm) I made this:
String x = "SELECT * FROM PROD WHERE TRANSLATE(LOWER(DESCSITE), 'âáàãêéèîíìôóòõûúùç', 'aaaaeeeiiioooouuuc') LIKE LOWER(TRANSLATE('%"+str+"%', 'âáàãêéèîíìôóòõûúùç', 'aaaaeeeiiioooouuuc'))";
And works fine. But this way I know that is not right.
You are calling the functions in the wrong order. The TRANSLATE function is case-sensitive. Therefore you must make the strings lower case before translating.
SELECT * FROM {0}
WHERE TRANSLATE(LOWER(DESCSITE), {2}) LIKE TRANSLATE({1}, {2})
Also, the second LOWER is superfluous, since you do with str.ToLower() already.
UPDATE
It is still not clear how you really execute the query. Here is an example of how it can be done
string connectionString = "...";
string query = "...";
using (var connection = new OracleConnection(connectionString)) {
var command = new OracleCommand(query);
command.Parameters.Add(":DESCSITE", OracleType.NVarChar);
connection.Open();
using (OracleDataReader reader = command.ExecuteReader()) {
int descSiteOrdinal = reader.GetOrdinal("DESCSITE");
while (reader.Read()) {
Console.WriteLine(reader.GetString(descSiteOrdinal));
}
}
}
I've resolved it adding this in my connectionString like this (Unicode=true;):
protected string conexionOraclePruebas = #"Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=xxx)(HOST=xxx)(PORT=xxx)))(CONNECT_DATA=(SERVER=xxx)(SERVICE_NAME=xxx)));"
+ " User Id=xxx;Password=xxx;Min Pool Size=x;Connection Lifetime=x; "
+ " Unicode=true;";
My query was:
query += " AND translate(UPPER(" + field + "), 'ÁÉÍÓÚÀÈÌÒÙÃÊÎÕÛÂÄËÏÖÔÜÇÑ', 'AEIOUAEIOUAEIOUAAEIOOUCN') "
+"LIKE translate(UPPER('%" + this.value.ToString() + "%'), 'ÁÉÍÓÚÀÈÌÒÙÃÊÎÕÛÂÄËÏÖÔÜÇÑ', 'AEIOUAEIOUAEIOUAAEIOOUCN')";