I'm using SQL Server 2008, with a C# front end. I'm trying to pass a SQL string from C# to SQL Server, and there are 2 fields in my WHERE statement that sometimes might contain NULL values. I've got this code on my Page Load in the code-behind (this is for a report that will be placed in a datagrid):
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection sqlconnectionStatus = new SqlConnection(str);
string DDL_Value = Convert.ToString(Request.QueryString["DDL_Val"]);
string Val_Value = Convert.ToString(Request.QueryString["Val_Val"]);
string Trk_Value = Convert.ToString(Request.QueryString["Trk_Val"]);
string StDt_Value = Convert.ToString(Request.QueryString["StDt_Val"]);
string EnDt_Value = Convert.ToString(Request.QueryString["EnDt_Val"]);
string BTN_Value;
// Because the date is stored as an INT, you have to request the string and then
// convert it to an INT
string StDT_Vals = Request.QueryString["StDt_Val"].ToString();
string EnDT_Vals = Request.QueryString["EnDt_Val"].ToString();
string sqlquery;
sqlquery = "Select DISTINCT PL.PROC_NM as Agent_Name, CCM.UNIQUE_CLAIM_ID as Unique_ID, CCM.CLAIM_ID as Claim_Number, ";
sqlquery = sqlquery + "CCM.SOCSEC as Employee_Last_Digit, CCM.DATE_IMPORTED as Import_Date, CCM.Orig_Open_Date as Original_Review_Date, ";
sqlquery = sqlquery + "AGL.ACCT_GRP as Account_Name, AL.ACCT_NUM as Account_Number, CCM.CDBBEN as Benefit_Option, CCM.BENEFIT_TYPE1 as Benefit_Type1, ";
sqlquery = sqlquery + "CCM.BENEFIT_TYPE2 as Benefit_Type2, CCM.BENEFIT_TYPE3 as Benefit_Type3, CCM.Cmplt as Review_Validated, CCM.Vldtn_Cmmnts as Validation_Comments, ";
sqlquery = sqlquery + "CCM.Gtkpr_Cmmnts as Gatekeeper_Comments, TS.StatusText as Tracking_Status ";
sqlquery = sqlquery + "from ClosedClaims_MERGE CCM ";
sqlquery = sqlquery + "LEFT JOIN PROC_LIST PL ON CCM.Spare = PL.LOGIN ";
sqlquery = sqlquery + "LEFT JOIN ACCT_LIST AL ON AL.ACCT_NUM = CCM.CDBACC ";
sqlquery = sqlquery + "LEFT JOIN ACCT_GRP_LIST AGL ON AGL.ACCT_GRP_PK = AL.ACCT_GRP_FK ";
sqlquery = sqlquery + "LEFT JOIN TrackingStatus TS ON TS.StatusCode = CCM.TrackingStatus ";
sqlquery = sqlquery + "WHERE CCM.Spare LIKE '" + DDL_Value + "' AND CCM.Cmplt LIKE '" + Val_Value + "' AND CCM.TrackingStatus IN (" + Trk_Value + ") AND CCM.DATE_IMPORTED >= '" + StDt_Value + "' AND CCM.DATE_IMPORTED <= '" + EnDt_Value + "'";
}
The code is sound, it works perfectly fine if a value is selected for all report parameters. The problem is CCM.Spare and CCM.Cmplt can have specific values chosen from a dropdown, or they can be left blank. If left blank, then they need to pull ALL values, whether they're NULL or not. When I leave one (or both) blank, that's where the SQL fails.
I tried checking for blanks and setting the variable equal to '%', but that obviously isn't working; it will only pick up records where there is a value in the field.
I want to do this with one statement if possible before I go cludging it with some If/Then/Else loops.
Is this possible?
try this, I just included the code for the first criteria.
As recommended above, don't concatenate your parameters; the second option is the best way to do it:
sqlquery = sqlquery +
"WHERE CCM.Spare " + (DDL_Value == null ? "IS NULL" : "LIKE '" + DDL_Value + "'") + " AND ...";
sqlquery = sqlquery +
"WHERE CCM.Spare " + (DDL_Value == null ? "IS NULL" : "LIKE #par1") + " AND ...";
Additionaly to increase the speed of your query you could do:
sqlquery = sqlquery +
"WHERE " + (DDL_Value != null ? "CCM.Spare LIKE #par1 AND " : "") + "...";
this will ignore the whole criteria on CCM.Spare if your parameter is null.
If you want all possible values of CCM.Spare and CCM.Cmplt, you simply need to leave off the predicate. Build a separate query (preferable using parametrized queries, as marc_s points out) that omits the WHERE clause referencing the empty dropdown value.
Related
I am looking to perform a search on multiple columns from an access database in C#.
The data is built in rows with each column either holding relevant data or "*" as a wildcard.
So as a rough example:
If i had data that was (, indicates new cell)
Ford, Fiesta, *, 1998
then if i had a value...
Ford, Fiesta, Petrol, 1998
it would find and display the row of data.
Currently I am trying:
string sql = "SELECT * FROM [mydatabase]
WHERE Manufacturer ='" + textBox1.Text +
"' OR Manufacturer='*' AND Model ='" + textBox2.Text +
"' OR Model='*' AND Fuel ='" + textBox3.Text +
"' OR Fuel='*' AND Year='" + textBox4.Text + "' OR Year='*'";
But this is bringing up all values rather than filtering them down. Is there a way of using and if/else within the query instead of OR?
If you want to use a wild card, I would just exclude it from the where clauses.
Alternateively, if you want to search all columns as one string you could add them all to a new column in the select list.
for example:
public void GetCars(string manufacturer, string model, string fuel, DateTime? year, string searchString)
{
string query = #"
SELECT *,
ISNULL([Manufacturer],'') + ' ' + ISNULL([Model],'') + ' ' ISNULL([Fuel],'') + ' ' ISNULL('Year', '') AS [SearchString]
FROM [MyDatabase]
WHERE [Manufacturer]=#Manufacturer ";
if (!String.IsNullOrEmpty(model))
query += #"AND [Model]=#Model ";
if (!String.IsNullOrEmpty(fuel))
query += "AND [Fuel]=#Fuel ";
if (year.HasValue)
query += "AND [Year]=#Year ";
if (!String.IsNullOrEmpty(searchString))
query += #"AND [SearchString] Like '%#SearchString%' ";
using (SqlCommand sqlCommand = new SqlCommand(query))
{
sqlCommand.Parameters.AddWithValue("#Manufacturer", manufacturer);
if (!String.IsNullOrEmpty(model))
sqlCommand.Parameters.AddWithValue("#Model", model);
if (!String.IsNullOrEmpty(fuel))
sqlCommand.Parameters.AddWithValue("#Fuel", fuel);
if (year.HasValue)
sqlCommand.Parameters.AddWithValue("#Year", year.Value);
if (!String.IsNullOrEmpty(searchString))
sqlCommand.Parameters.AddWithValue("#SearchString", searchString);
//Execute to data table etc
}
}
Instead of Manufacturer ='" + textBox1.Text + "' OR Manufacturer='*', you can use coalesce, which is sort of an if/else:
string sql = "... Manufacturer = coalesce('" + textBox1.Text + "', '*') ...";
In that way, you only need ands, and not mixed with or. This is probably giving the problem now, since the ors cause the and not to be evaluated.
You can also add parenthesis around the and, so the or will be applied only inside the parenthesis:
string sql = "... where (Manufacturer ='" + textBox1.Text + "' OR Manufacturer='*') and ...";
Note you should use parameterized queries, so you would get something like this:
command.CommandText = "select * from ... where Manufacturer = coalesce(#mgr, '*') and ...";
command.Parameters.Add(new SqlParameter("mgr", textBox1.Text));
I am executing a MS Access Query through c#. Below is the query
String SelWHQuery = "SELECT DateDiff('n',INTime,OUTTime)\\60 & '.' & Format(DateDiff('n',[INTime],[OUTTime]) Mod 60,'00') AS Workedhours" +
"' WHERE EMPID = '" + Eno +
"'AND RDate=# "+ DateTime.Now.Date.ToString("yy-MM-dd") +
"# FROM INOUTPunching";
which is giving below error
{"The SELECT statement includes a reserved word or an argument name that is misspelled or missing, or the punctuation is incorrect."}
I need to know:
Why is this not working?
Is there any simplier method?
You should place the FROM clause before the WHERE clause. That is the problem with your query. And you have an extra single quote which should be removed. This is the query you should write:
String SelWHQuery = "SELECT DateDiff('n',INTime,OUTTime)\\60 & '.' & Format(DateDiff('n',[INTime],[OUTTime]) Mod 60,'00') AS Workedhours FROM INOUTPunching " +
" WHERE EMPID = '" + Eno +
"'AND RDate=# "+ DateTime.Now.Date.ToString("yy-MM-dd") + "#";
And about a simpler method: no, this is the simplest method but it is prone to SQL injection attacks. Replace it with a parameterized query (assuming you have an OldDbCommand name cmd):
String SelWHQuery = "SELECT DateDiff('n',INTime,OUTTime)\\60 & '.' & Format(DateDiff('n',[INTime],[OUTTime]) Mod 60,'00') AS Workedhours FROM INOUTPunching " +
" WHERE EMPID = #EmpId AND RDate=# "+ DateTime.Now.Date.ToString("yy-MM-dd") + "#";
cmd.CommandType = CommandType.Text;
cmd.CommandText = SelWHQuery;
cmd.Parameters.AddWithValue("#EmpId", Eno);
am writing a c# code in which am trying to update 4 of the 10 columns of the table. Here is my function type in which am sending arguments for the query:
public int checkout_visitor(int check_inn, int checkout, String time_out, String date_out, String cnic)
Now what happens is that i call this function somewhere in my program providing values in argument:
checkout_visitor(chk_in,chk_out,t_out,dt_out,idcardnum);
The query am using to update my columns is given by:
String query2 = " UPDATE visit_detail SET[check_in] = " + check_inn + "[check_out] = " + checkout + "[time_out] = " + time_out + "[date_out] =" + date_out + "where visit_detail.v_id = "+ v_idd;
Given me exception incorrect syntax near chkout. Where am i wrong?? is the syntax correct? how do i correct it?
code:
public int checkout_visitor(int check_inn, int checkout, String time_out, String date_out, String cnic)
{
try
{
connection.Open();
String query = "select v_id from visitor where visitor.cnic=" + cnic;
command = connection.CreateCommand();
command.CommandText = query;
visitor_id = command.ExecuteScalar().ToString();
int v_idd = Int32.Parse(visitor_id);
String query2 = " UPDATE visit_detail SET[check_in] = " + check_inn + "[check_out] = " + checkout + "[time_out] = " + time_out + "[date_out] =" + date_out + "where visit_detail.v_id = " + v_idd;
//String query2 = "UPDATE visit_detail SET [check_in] = " + check_inn + ",[check_out] = " + checkout + ",[time_out] = " + time_out + ",[date_out] =" + date_out + " where visit_detail.v_id = " + v_idd;
command = connection.CreateCommand();
command.CommandText = query2;
int result = command.ExecuteNonQuery();
connection.Close();
return result;
}
catch (Exception e)
{
return -1;
}
}
Problem :
1.you are not seperating the Parameters properly using comma , .
2.you are not giving the sapace between SET and check_in parameter.
Try This:
String query2 = "UPDATE visit_detail SET [check_in] = " + check_inn + ",[check_out] = " + checkout + ",[time_out] = '" + time_out + "',[date_out] ='" + date_out + "' where visit_detail.v_id = "+ v_idd;
Do you see the resulting query? It seems to me you're missing some comma, but you should print (and post) the resulting query to have a better understanding of the issue.
You are missing ',' between the column names.
Its like Update Table Set col1=3,col2='test'
The problem is that query2 string will be something along the lines:
UPDATE visit_detail SET[check_in] = " 1[check_out] = 2[time_out] = some time[date_out] =some datewhere visit_detail.v_id = 5
So you can already see that there's datewhere that is incorect, there are also no ' characters around string parameters, and no commas between parameters.
Quick fix to that would be:
String query2 = String.Format("UPDATE visit_detail SET [check_in]={0}, [check_out]={1}, [time_out]='{2}', [date_out]='{3}' where visit_detail.v_id={4};", check_inn, checkout, time_out, date_out, v_idd);
But this is still not valid. If time_out contains ' characters, you'll again receive an error.
What you should really use is this:
SqlCommand.Parameters
This is a proper way of passing paramters to your command, all the problems will be taken care of for you.
I'm experiencing difficulties filtering a set of data between two DateTime values.
For example: Retrieve all records From: 24/04/2013 3:54 PM; To: 24/04/2013 4:30 PM.
I'm programming in C# and using OLE DB to pull data from a Access Database.
The 'To' and 'From' DateTime values are retrieved from DateTimePicker controls on a GUI.
I'm trying to query data in 'receiveDateTime' field of my data source - it is stored in DateTime format in Access.
My code appears as follows:
string SQLQuery = "SELECT EmailID, ServerName, receiveDateTime, Type, status, received, processed"
+ "FROM EmailTable, EmailTypesTable, ServerTable, StatusTable"
+ "WHERE EmailTypesTable.emailTypeID = EmailTypesTable.EmailType "
+ "AND ServerTable.ServerID = EmailTable.serverID "
+ "AND StatusTable.statusID = EmailTable.statusID "
+ "AND EmailTable.receiveDateTime BETWEEN "
+ fromDateTime.Value.ToString("g") + "AND " + toDateTime.Value.ToString("g")";
loadDataGrid(SQLQuery);
Any solutions or advice would be much appreciate.
Thanks,
Allan.
1- It seems you forgot the single quotes between the date values:
string SQLQuery = "SELECT EmailID, ServerName, receiveDateTime, Type, status, received, processed"
+ "FROM EmailTable, EmailTypesTable, ServerTable, StatusTable"
+ "WHERE EmailTypesTable.emailTypeID = EmailTypesTable.EmailType "
+ "AND ServerTable.ServerID = EmailTable.serverID "
+ "AND StatusTable.statusID = EmailTable.statusID "
+ "AND EmailTable.receiveDateTime BETWEEN '"
+ fromDateTime.Value.ToString("g") + "' AND '" + toDateTime.Value.ToString("g") +"' ";
2- It would be better if you use parameterized parameters too:
SqlConnection con = new SqlConnection(MyconnectionString);
con.Open();
string SQLQuery = "SELECT EmailID, ServerName, receiveDateTime, Type, status, received, processed"
+ "FROM EmailTable, EmailTypesTable, ServerTable, StatusTable"
+ "WHERE EmailTypesTable.emailTypeID = EmailTypesTable.EmailType "
+ "AND ServerTable.ServerID = EmailTable.serverID "
+ "AND StatusTable.statusID = EmailTable.statusID "
+ "AND EmailTable.receiveDateTime BETWEEN #dateFrom AND #dateTo";
SqlCommand cmd = new SqlCommand(SQLQuery );
cmd.Parameters.AddWithValue("#dateFrom", fromDateTime.Value.ToString("g"));
cmd.Parameters.AddWithValue("#dateTo", toDateTime.Value.ToString("g"));
SqlDataReader reader = cmd.ExecuteReader();
//...
You could have guessed the issue by trying to execute this query directly in your database
(I have used SQLConnection, SQLCommand... here, you will need to change that part based on the connection you are using.)
For anyone that encounters this problem in future when comparing DateTime value, passing the C# DateTime as an OLE Automation date to the database works!
In order to access this value you use the ToOADate() method.
For example:
SqlConnection con = new SqlConnection(MyconnectionString);
con.Open();
string SQLQuery = "SELECT EmailID, receiveDateTime "
+ "WHERE EmailTable.receiveDateTime "
+ "BETWEEN #dateFrom AND #dateTo";
SqlCommand cmd = new SqlCommand(SQLQuery );
cmd.Parameters.AddWithValue("#dateFrom", fromDateTime.Value.ToOADate());
cmd.Parameters.AddWithValue("#dateTo", toDateTime.Value.ToOADate());
It is quite strange, because although the DateTime values appear in general DateTime Format in the DataGrid, the database must read them as such:
General DateTime Format: 26/04/2013 9:47 AM
OLE Automation Date: 41390.4082198032
Thanks for pointing me in the right direction noobob!
Okay, so in the past few weeks I've probably written about 40 select statements. So, I know how to do it. And I've just written another one, but this time I need to use ComboBox values to match against, and it keeps resulting in the names of the column (the right column, mind you), instead of what's inside the column.
string st = "SELECT '" + txtchange.Text + "'
FROM mysql_9269_dbase." + pages.Text + "";
MySql.Data.MySqlClient.MySqlCommand cd = new MySql.Data.MySqlClient.MySqlCommand(st, msc);
cd.CommandType = CommandType.Text;
MySql.Data.MySqlClient.MySqlDataReader msdr = cd.ExecuteReader();
while(msdr.Read())
{
txt.Text = msdr[0].ToString();
}
Now, why is it returning the column name instead of the content of that column?
Lose the single quotes.
Change
"SELECT '" + txtchange.Text + "' "
to
"SELECT " + txtchange.Text + " "
In sql you can do it like this.
string query = "Execute("+"'SELECT " + txtchange.Text + " FROM mysql_9269_dbase." + pages.Text + "')";