statement for npgsql using parameter - c#

I pass the parameters in the sql query using the driver npgsql:
SqlCommand = new NpgsqlCommand();
....
SqlCommand.CommandText = "SELECT id,name FROM table1 WHERE field1=:param2 ORDER BY name;";
SqlCommand.Parameters.AddWithValue("param2", 1);
This query executed correctly and issued the necessary data, but as soon as I add parameter to the sql in the section "select"
SqlCommand.CommandText = "SELECT id,name :param1 FROM table1 WHERE field1=:param2 ORDER BY name;";
SqlCommand.Parameters.AddWithValue("param1", ",field1");
SqlCommand.Parameters.AddWithValue("param2", 1);
it gives me some kind of nonsense. In theory this request to the server is to be treated as
SELECT id,name,field1 FROM table1 WHERE field1=1 ORDER BY name;
but it did not happen.
This raises the question: is there a way to dynamically insert a list of fields using suchlike parameters?

Unfortunately, Npgsql doesn't have support for what you are trying to do. NpgsqlParameter values are supposed to be only used as parameter values in the where clause.
In order to add field names dynamically as you intend, you will have to create the query manually by using string concatenation.
I hope it helps.

Rewrite you CommandText and add this:
foreach (NpgsqlParameter item in _Command.Parameters)
{
comm.Parameters.AddWithValue(item.ParameterName, item.Value);
}
And solve your problem..

Related

How to use writing N for insert query in .NET C#?

In SQL Server
update incident_info
set description = N'ဆေးလိပ်'
where incidentid = 5
This query is correct in SQL Server and shows myanmar font correctly in the database.
I want to write correct query as above in below insert query.
sqlUtil.SqlDataUpdate(false, ("INSERT INTO Incident_Info (incidentid, incidentdate, incidenttime, description, Salesmen_id, name, phone, email, address, cost, currency, solution, status)" +
"VALUES (#incidentid, #incidentdate, #incidenttime, N'+#description+', #salesmenid, N'+#name+', #phone, #email, N'+#address+', #cost, #currency, N'+#solution+', #status)"), SysController.dicParams);
You do NOT need to prefix your SQL parameter names with a N prefix - that's useless, and probably results in an error. The N prefix is only needed when specifying a Unicode string literal in a raw SQL code snippet.
In your case, what you need to ensure is that the code that does the actual insert into SQL Server properly defines your parameters as SqlDbType.NVarChar. So in your sqlUtil class, somewhere, you have a method SqlDataUpdate that parses and executes that SQL statement you send in.
Inside there, you must ensure that code something like this is used:
using (SqlConnection conn = new SqlConnection(-your-connection-string-here-))
using (SqlCommand insertCmd = new SqlCommand(sqlQuery, conn))
{
// here, you need to ensure you define your string parameters correctly
insertCmd.Parameters.Add("#description", SqlDbType.NVarChar, 100);
.....
// and then you need to set the values - since .NET strings are inherently Unicode, no special treatment is needed
insertCmd.Parameters["#description"].Value = SysController.dicParams.......
.....
// open, execute, close
conn.Open();
int rowsInserted = insertCmd.ExecuteNonQuery();
conn.Close();
}
This must be done inside your sqlUtil class - you cannot influence this from the "outside" by simply adding a N prefix to your parameter names...

C# Select Query Failed with no errors

I'm having trouble with a simple SELECT query, I cannot see why it isn't working.
Here is the code:
conn.Open();
string GetPayrollQuery = "SELECT PayrollNo FROM [Employee] WHERE (FirstName + ' ' + LastName) = #Name";
OleDbCommand GetPayroll = new OleDbCommand(GetPayrollQuery, conn);
GetPayroll.Parameters.AddWithValue("#Name", OleDbType.VarChar).Value = cbbEmployees.Text;
var GotPayroll = GetPayroll.ExecuteNonQuery();
MessageBox.Show(GotPayroll.ToString());
return Convert.ToInt32(GotPayroll);
The code runs fine however it isn't extracting the data. Can anyone see why this would be?
I bet #name is coming as "MikeSmith" instead of "Mike Smith".
3 things:
try to open SQL profiler and check what you are executing on database
check database collation, is it case sensitive?
remove executenonquery (it's must used with update, delete, not select) and try executescalar (if one result for one row is exptected, otherwise try to fill a datatable or use datareader)
Make sure the same query runs in SQL using those parameter values.
Change GetPayroll.ExecuteNonQuery() to GetPayroll.ExecuteScalar() so to return a single result.
Change GetPayroll.Parameters.AddWithValue("#Name", OleDbType.VarChar).Value = cbbEmployees.Text; to GetPayroll.Parameters.AddWithValue("#Name", cbbEmployees.Text);
Use cbbEmployees.SelectedText. Fixes the problem.

Why does String.Format work but SqlCommand.Parameters.Add not?

I have a Project table with two columns -- ProjectId and ProjectName -- and am writing a function that constructs and executes a SqlCommand to query the database for the ids of a Project with a given name. This command works, but is vulnerable to SQL Injection:
string sqlCommand = String.Format("SELECT {0} FROM {1} WHERE {2} = {3}",
attributeParam, tableParam, idParam, surroundWithSingleQuotes(idValue));
SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
DataTable attributes = new DataTable();
adapter.Fill(attributes);
...
}
attributeParam, tableParam, idParam, and idValue are all strings. For example, they might be "ProjectId", "Project", "ProjectName", and "MyFirstProject", respectively. surroundWithSingleQuotes surrounds a string with '', so surroundWithSingleQuotes(idValue) == "'MyFirstProject'". I am trying to write this function as general as possible since I might want to get all of a given attribute from a table in the future.
Although the above String.Format works, this doesn't:
string sqlCommand = String.Format("SELECT #attributeparam FROM {0} WHERE " +
"#idparam = #idvalue", tableParam);
command.Parameters.Add(new SqlParameter("#attributeparam", attributeParam));
command.Parameters.Add(new SqlParameter("#idparam", idParam));
command.Parameters.Add(new SqlParameter("#idvalue",
surroundWithSingleQuotes(idValue)));
SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
DataTable attributes = new DataTable();
adapter.Fill(attributes);
...
}
I'm not sure why. I get no error message, but when I fill my DataTable using a SqlDataAdapter, the DataTable contains nothing. Here are various approaches I've taken, to no avail:
Following this answer and Microsoft's documentation, using AddWithValue or using Parameters.Add and SqlParameter.Value.
Selectively replacing {0}, {1}, {2}, and {3}in String.Format with either the actual value or the parameter string.
In other places in my code, I've used parametrized queries (although with just one parameter) no problem.
Basically parameters in SQL only work for values - not identifiers of columns or tables. In your example, only the final parameter represents a value.
If you need to be dynamic in terms of your column and table names, you'll need to build that part of the SQL yourself. Be very careful for all the normal reasons associated with SQL injection attacks. Ideally, only allow a known whitelist of table and column values. If you need to be more general, I'd suggest performing very restrictive validation, and quote the identifiers to avoid conflicts with keywords (or prohibit those entirely, ideally).
Keep using SQL parameters for values, of course.
This is a valid statement:
SELECT * FROM SomeTable WHERE SomeColumn=#param
Whereas this is not:
SELECT * FROM #param
This means that you can use parameters for values and not for table names, view names, column names etc.

Query updates all of my data instead of only the one I want

How do I make it so that my query only update the data I want?
Here's the current code
string query = string.Format("update Customer set title='{0}',[Name]='{1}'",titleComboBox2.Text,nameTextBox2.Text,"where ID="+idTextBox+"");
Apparently the last part of the query isn't working. Why it is that?
Because you didn't use any index argument as {2} for your third argument which is WHERE part.
That's why your query will be contain only update Customer set title='{0}',[Name]='{1}' part this will be update for your all rows since it doesn't have any filter.
Fun fact, you could see this as query if you would debug your code.
But more important
You should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
Let's assume you use ADO.NET;
using(var con = new SqlConnection(conString))
using(var cmd = con.CreateCommand())
{
cmd.CommandText = #"update Customer set title = #title, [Name] = #name
where ID = #id";
cmd.Paramter.Add("#title", SqlDbType.NVarChar).Value = titleComboBox2.Text;
cmd.Paramter.Add("#name", SqlDbType.NVarChar).Value = nameTextBox2.Text;
cmd.Paramter.Add("#id", SqlDbType.Int).Value = int.Parse(idTextBox.Text);
// I assumed your column types.
con.Open();
cmd.ExecuteNonQuery();
}
Currently your query does not use WHERE clause, because it is ignored by string.Format. You have 3 placeholder parameters, and you are using only {0} and {1}, so WHERE part is never added to the SQL query. Change your query to include WHERE clause, e.g. like this:
string query = string.Format("update Customer set title='{0}',[Name]='{1}' {2}",titleComboBox2.Text,nameTextBox2.Text,"where ID="+idTextBox.Text+"");
However, there is one very serious flaw in your code - it is vulnerable to SQL injection attack. There are hundreds of articles about it online, make sure to read about what that is and how to update your code accordingly (hint - parametrize queries)

How to add a "select all" value to a parametrized query in C# and MS SQL

I have the following code:
As you can see, i need to pass a parameter to Field2, but i also need that parameter to be ablo to handle the ""all values" option, for example, if i assign "foo" to the parameter, the query will return every record where Field2 = "foo"... but i also want to be able to pass a wildcard, or something to tell that parameter to give all values as result.
MyDataset dataset = new MyDataset();
SqlConnection objConnection = new SqlConnection(_connectionstring);
SqlDataAdapter objDataAdapter = new SqlDataAdapter();
objDataAdapter.SelectCommand = new SqlCommand();
objDataAdapter.SelectCommand.Connection = objConnection;
objDataAdapter.SelectCommand.CommandText =
"SELECT Field1, Field2, Field3 FROM Table WHERE (Field2 = #Field2)";
objDataAdapter.SelectCommand.CommandType = CommandType.Text;
objDataAdapter.SelectCommand.Parameters.AddWithValue("#Field2", txtBoxField2.Text);
objDataAdapter.Fill(dataset.Table);
this.DataContext = dataset.Table.DefaultView;
Thank you in advance.
One way to do this is to use nullable parameters:
SELECT Field1, Field2, Field3
FROM Table
WHERE (#Field2 IS NULL OR Field2 = #Field2)
but you need to be aware that this can lead to incorrectly cached query plans in some circumstances where there are many parameters. If you are using SQL Server 2005+, this can be mitigated to a large ectent using OPTIMIZE FOR.
Also, make sure your statistics are up to date.
If you're building up the SQL like that within your C# code, then just put an if condition in your C# logic to not include the WHERE clause in the instance you want to return all records. This would create a different SQL statement, so would be OK for performance/execution plan-wise.
If you're going to be using a sproc, you could try this approach:
IF (#Field2 = 'SomeWildcardValue')
SELECT Field1, Field2, Field3 FROM SomeTable
ELSE
SELECT Field1, Field2, Field3 FROM SomeTable WHERE Field2 = #Field2
Or even, keep them completely separate, create one sproc to return ALL, and one to return based on Field2 search. Although if you have a larger number of parameters, this can soon mount up!
In general I would use the nullable parameter method in an SP. Based on your code though, why don't you build the SQL commandtext based on what the user has entered? For example, only add a where clause to the SQL if the user has entered something into the text box, otherwise, just a simple select.

Categories