no update on sql server database. No errors just no results - c#

//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);

Related

How to use SELECT + parameter + FROM in SQL database?

I want to know if it is possible to create a query like that:
SELECT :parameterA, :paramaterB
FROM *someTable*;
The idea is to use some structure like that instead of making some sort of string or something like that.
I´m working with SQL database and a C# project in Visual Studio 2019.
So far I have this code:
public List<V_Requerimientos> GetData(int idEmpresa, string columns)
{
List<V_Requerimientos> result = null;
try
{
var dyParam = new OracleDynamicParameters();
dyParam.Add("idEmpresa", OracleDbType.Int32, ParameterDirection.Input, value: idEmpresa);
var conn = this.GetConnection();
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
if (conn.State == ConnectionState.Open)
{
string query = "SELECT " + columns + "FROM V_REQUERIMIENTOS " +
"WHERE EMPR_CODIGO = :idEmpresa AND ETAR_CODIGO <> 4";
result= conn.Query<V_Requerimientos>(query, dyParam).ToList();
conn.Close();
}
}
catch (Exception e)
{
throw e;
}
return result;
}
where idEmpresa is the PK of the object selected in the front, and columns is a string which contains the columns I want to select for that object.
I was wondering if there is anyway for replace columns for parameters sent to the method instead of using the concatenated query as I have at the moment.
SQL parameters are used to specify value in the where clause. You would not use parameters for column names. Your query should look more like this.
string colA = "Customer Id";
string colB = "Customer Name";
string sql = $"Select [{colA}], [{colB}] from table";

ODBC parametrized query with unknown number of values?

I want to select several values from database (ODBC datasource). The table is this simple:
| name | value |
+------+-------+
| abcd | 12345 |
Say I want to select values where name is name1, name2 and name3:
SELECT name, value FROM my_table WHERE name="name1" OR name="name2" OR name="name3"
Now I could generate this command:
public string MakeCommand(List<string> names) {
string command = "SELECT name, value FROM my_table WHERE ";
bool first = true;
foreach(string name in names) {
if(first)
first = false;
else
command+=" OR ";
command+="name=\""+name+"\"";
}
}
I hope it's not necessary to emphasize that this would be very bad way to access the database.
So how can I make this a parametrized ODBC command, as described here?
Well, the simplest solution is probably to concatenate a parameter to the sql for each value in your list, and then add this value as a parameter to the OdbcCommand.
using(var command = new OdbcCommand())
{
string sql = "SELECT name, value FROM my_table WHERE name IN(";
for(int i=0; i < names.Count; i++) {
sql = $"{sql} #{i},";
command.Parameters.Add($"#{i}", OdbcType.VarChar).Value = names[i];
}
command.CommandText = sql.TrimEnd(",") +");";
command.Connection = con;
// fill a data set or execute a data reader here....
}
There is no elegant solution to this problem. You can use the IN clause but, still you need to build the parameters one by one. So instead of returning a string you can return the OdbcCommand prepared with all the parameters required by your list of names. Just need to add the connection and execute (or pass also the connection and prepare everything here)
public OdbcCommand MakeCommand(List<string> names, OdbcConnection con) {
List<OdbcParameter> parameters = new List<OdbcParameter>();
List<string> placeholders = new List<string>();
foreach(string name in names) {
OdbcParameter p = new OdbcParameter("?", OdbcType.NVarChar);
p.Value = name;
parameters.Add(p);
placeholders.Add("?")
}
string command = "SELECT name, value FROM my_table WHERE name IN(";
command = command + string.Join(",", placeholders.ToArray()) + ")";
OdbcCommand cmd = new OdbcCommand();
cmd.CommandText = command;
cmd.Connection = con;
cmd.Parameters.AddRange(parameters.ToArray());
return cmd;
}
If you still have problems, then it could be something linked to the parameters DataType. NVarChar, VarChar, Text, String. Some db could react differently to this type. What database are you testing this code against?

C# confirm table row has been deleted from database

I've written a method which will try and delete a row from a db table based on a primary key id. The problem i have is that the try block is always returning "Success" even if a record has already been deleted / or it doesn't exist.
public string delete_visit(int id)
{
string deleteResponse = null;
string cnn = ConfigurationManager.ConnectionStrings[connname].ConnectionString;
using (SqlConnection connection = new SqlConnection(cnn))
{
string SQL = string.Empty;
SQL = "DELETE FROM [" + dbname + "].[dbo].[" + tbname + "] WHERE VisitorNumber = #IDNumber ";
using (SqlCommand command = new SqlCommand(SQL, connection))
{
command.Parameters.Add("#IDNumber", SqlDbType.Int);
command.Parameters["#IDNumber"].Value = id;
try
{
connection.Open();
command.ExecuteNonQuery();
deleteResponse = "Success";
}
catch (Exception ex)
{
deleteResponse = "There was a problem deleting the visit from the database. Error message: " + ex.Message;
}
}
}
return deleteResponse;
}
I want to be able to tell if the row was affected. I can do this in SQL Server Management Studio like so:
DELETE FROM Visits
WHERE VisitorNumber=88;
IF ##ROWCOUNT = 0
PRINT 'Warning: No rows were updated';
So i want to know how do i plug in the ##ROWCOUNT bit into my c# so that i can tell if the row was deleted?
thanks
ExecuteNonQuery() returns an int, indicating how many rows were affected.
So:
int rowsAffected = command.ExecuteNonQuery();
if (rowsAffected == 0)
{
deleteResponse = "No rows affected";
}
The problem is that this number can be influenced based on what the query actually does. Executing triggers or calling stored procedures could mess with the output, changing the affected number of rows. If you really must, then first execute a query where you check that the record with the given ID exists.

How to create dynamic parameters in SQL Server stored procedure

I have a form that generate inputs dynamically, then I get their values and generate command parameters dynamically.
SqlConnection con = new SqlConnection(cs);
SqlCommand cmd =new SqlCommand("insert_op",con);
cmd.CommandType = CommandType.StoredProcedure;
for (int i = 0; i < Request.Form.Count; i++)
{
if (Request.Form["frm_option" + (i + 1)] != null)
{
cmd.Parameters.AddWithValue("#op" + i, Request.Form["frm_option" + (i + 1)]);
}
}
try
{
using (con)
{
con.Open();
cmd.ExecuteNonQuery();
}
}
catch
{
}
How can I pass these dynamic parameters to SQL Server stored procedure and how should stored procedure be?
First of all, this isn't the right design.
To achieve your goal you need to pass multiple values in SQL statment as follows
SQL
INSERT INTO tbl_options(op_name) VALUES (value1),(value2),...(nthValue)
Code
Your code will be something like this
string command = "INSERT INTO tbl_options(op_name) VALUES";
for (int i = 0; i < Request.Form.Count; i++)
{
if (Request.Form["frm_option" + (i + 1)] != null)
{
command += "(#op" + i + "),";
cmd.Parameters.AddWithValue("#op" + i, Request.Form["frm_option" + (i + 1)]);
}
}
If you want to "insert each parameter into separate row" then perhaps it is better to use table variable as a stored prosedure parameter?
Your User Defined Table Type and stored procedure might look like:
create type dbo.ValueTableType as table (Value varchar(255))
GO
create procedure dbo.InsertValues
#Values dbo.ValueTableType readonly
as
begin
insert into dbo.YourTable (Value)
select Value from #Values;
end
See this ADO.NET example of how to initialize and pass a table parameter to stored procedure https://stackoverflow.com/a/10409710/623190
You can provide defaults for every field in the table, so any parameters you do not pass in will get the default. Here I demonstrate defaults of NULL.
CREATE PROCEDURE [dbo].[sproc_tbl_options_Insert]
#op_name nvarchar(50) = NULL,
#op_somethingelse nvarchar(5) = NULL,
#op_number int = NULL
AS
BEGIN
INSERT INTO [tbl_options] (op_name, op_somethingelse, op_number)
VALUES (#op_name, #op_somethingelse, #op_number);
END

Perform an update on a SQL table based on passed parameter

This program was already written and I need to add to it an update SQL statement to update another table based on #IN. After declaring the SQL command how do I get it to excute, can I use the same SQLConnection as other sql command? WHat this program does is it parses in a file to a list called individuals and from that I just want to update the fields in SQL. The first SQL was already written in an seems to execute correctly now I need to do the UpdtHasInv SQL and actually get the code to perform the update is where I need help.
Heres what I have so far:
static void InsertCustomData(Collection<Individuals> individuals)
{
#region
string insertsql = "";
insertsql = #"Insert into IND (IND_ID, ITEM_NAME, INDL_ITEM_VALUE, XPTIM)
select IND_ID, '{0}' as Item, '{1}' as val, (current timestamp - curtime)"
FROM IND
where IN = #IN";
// this is SQL I added for update
**UpdtHasInv = #"UPDATE Ind
SET HAS_I = -1
WHERE IN = #IN";**
#endregion
using (DB2Connection conn = DB2Helper.getConnection())
{
DB2Command cmd = conn.CreateCommand();
cmd.CommandTimeout = 600;
cmd.Parameters.Add("#IN", "");
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
foreach (Individuals individual in individuals)
{
cmd.Parameters["#IN"].Value = individual.In;
foreach (CustomData customData in individual.CustomData)
{
cmd.CommandText = string.Format(insertIndsql, customData.Data.Key, customData.Data.Value);
Could I just write : 'cmd.CommandText = UpdtIsInv;' after these lines:
foreach (Individuals individual in individuals)
{
cmd.Parameters["#IN"].Value = individual.in
You could simply append your UPDATE after the INSERT using a semicolon.
insertIndsql = #"
INSERT INTO IND (IND_ID, ITEM_NAME, INDL_ITEM_VALUE, XPTIMESTAMP)
SELECT INDIVIDUAL_ID, '{0}' as Item, '{1}' as val, (current timestamp - curtime)
FROM IND
WHERE TIN = #TIN;
UPDATE DB2INST1.Individual
SET HAS_INVESTMENT = -1
WHERE TIN = #TIN;";
When executed, both statements will be executed as part of the same command.

Categories