Im trying to have my program search my database and add the results to a listview control. The listview populates with a SQL statement of:
SELECT * FROM dbo.TBL_Locations
However when I try to make it search with a where statement and add values it keeps returning nothing
String selStmt = "SELECT * FROM dbo.TBL_Locations WHERE #SearchParameter = #SearchTerm";
SqlCommand selCmd = new SqlCommand(selStmt, conn);
selCmd.Parameters.AddWithValue("#SearchParameter", SearchParameter);
selCmd.Parameters.AddWithValue("#SearchTerm", SearchTerm);
So SearchParameter would have for example "City" (searching the City column) and SearchTerm would have "Leeds" (Searching for Leeds in the City column)
however what I think is happening is it's basically trying to assign searchTerm to SearchParameter rather than replacing them with the values?
I've tried various different where statements from what I've found on google but cannot seem to get it to work.
I hope it makes sense what I am meaningş.
So you want to search more than one column name, then try like this,
StringBuilder sb = new StringBuilder();
sb.Append("SELECT * FROM dbo.TBL_Locations WHERE ");
switch (SearchParameter)
{
case "City":
sb.Append(" City = #SearchTerm");
break;
case "Stadium":
sb.Append(" Stadium = #SearchTerm");
break;
}
SqlCommand selCmd = new SqlCommand(sb.ToString(), conn);
selCmd.Parameters.AddWithValue("#SearchTerm", SearchTerm);
You can use a stored procedure like this:
CREATE PROCEDURE TBL_Locations_Select (
#City varchar(50), -- or whatever length your actual column is
#Stadium varchar(50) -- or whatever length your actual column is
)
AS
SELECT *
FROM dbo.TBL_Locations
WHERE City = CASE WHEN #City IS NULL THEN City ELSE #City END
AND Stadium = CASE WHEN #Stadium IS NULL THEN Stadium ELSE #Stadium END
This is sql injection safe and not to bad on performance.
If your City or Stadium is nullable columns you might want to do this a little different:
WHERE COALESCE(City, '') = CASE WHEN #City IS NULL THEN COALESCE(City, '') ELSE #City END
AND COALESCE(Stadium, '') = CASE WHEN #Stadium IS NULL THEN COALESCE(Stadium, '') ELSE #Stadium END
Then on your c# code you write something like this:
string City;
string Stadium;
SqlCommand selCmd = new SqlCommand("TBL_Locations_Select", conn);
selCmd.CommandType = CommandType.StoredProcedure;
selCmd.Parameters.AddWithValue("#City", (String.IsNullOrEmpty(City)) ? DBNull.Value : City ;);
selCmd.Parameters.AddWithValue("#Stadium", (String.IsNullOrEmpty(Stadium)) ? DBNull.Value : Stadium ;);
Change to:
String selStmt = "SELECT * FROM dbo.TBL_Locations WHERE City = #SearchTerm";
Where "City" is the column in the DB
Try this
String selStmt = "SELECT * FROM dbo.TBL_Locations WHERE #SearchParameter = #TextBox1.Text" AND #SearchTerm = #TextBox2.Text";
SqlCommand selCmd = new SqlCommand(selStmt, conn);
selCmd.Parameters.AddWithValue("#SearchParameter", SearchParameter);
selCmd.Parameters.AddWithValue("#SearchTerm", SearchTerm);
Related
Is it even possible to return value of string without the " " ?
I have the following string: Chb = "NOT";
Now i either want to remove the "" in C# or SQL.
so i want to have either Chb = NOT in C#
,or i want to remove the ' ' in SQL that i get in #Chb so that this:
WHERE PAR #Chb IN ('1','2','3')
isnt like this : WHERE PAR 'NOT' IN ('1','2','3')
but it is like this WHERE PAR NOT IN ('1','2','3')
I don't believe this is the right approach for this.
If you want to execute a command in SQL which comes from a C# code, then i would do:
string exists = "select * from table where var in (1,2,3)";
string notExists = "select * from table where var NOT in (1,2,3)";
if (chb != "NOT")
{
SqlCommand cmd = new SqlCommand(exists, con);
cmd.ExecuteScalar();
}
else
{
SqlCommand cmd = new SqlCommand(notExists, con);
cmd.ExecuteScalar();
}
I have written this procedure in SQL Server:
ALTER proc [dbo].[cazacliente2]
(#vbusca nvarchar(60), #bo int)
as
if #bo= 1
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where nome like #vbusca
end
if #bo = 2
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where endere like #vbusca
end
if #bo = 3
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where tel like #vbusca
end
if #bo = 4
begin
select idcliente, nome, endere, tel, pedido from Vw_Conscliente
where pedido like #vbusca
end
and this code in asp.net :
{
string valorC = "%" + TextBox1.Text + "%"; numo = DropDownList1.SelectedValue;
string valorB = valorC.Replace(" ", "%");
switch (numo)
{
case "Nome": num3 = 1; break; case "Endereço": num3 = 2; break ;
case "Telefone": num3 = 3 ; break; case "Pedido": num3 = 4; break ;
}
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "cazacliente2";
SqlParameter valor = new SqlParameter("#vbusca", SqlDbType.NVarChar);
SqlParameter num = new SqlParameter("#bo",SqlDbType.Int );
valor.Value = valorB ; num.Value = num3 ;
cmd.Parameters.Add(valor); cmd.Parameters.Add(num);
if (conex1.State == ConnectionState.Closed)
{ conex1.Open(); }
cmd.Connection = conex1;
try
{
GridView1.EmptyDataText = "Nao se" + numo.ToString() +"encontraron registros";
GridView1.DataSource = cmd.ExecuteReader();
GridView1.DataBind();
}
catch (Exception ex)
{ throw ex; }
finally
{ conex1.Close(); }
}
When I pass the string afonso pena the procedure returns all the data just fine, but when I pass in afonso 60, it returns an error, and when I pass a name that is not in the database it breaks again, it is like the part catch does not work.
When your question involves an error, it's a great idea to include the error message you see in your question. As it's difficult to debug without knowing the error message, try the following to narrow down where the problem might be.
Try restructuring your code to catch any possible errors before you try databinding your GridView:
{
/*
* put the try at the top of the block to catch exceptions
* that may occur before you bind the GridView's datasource
*/
try
{
numo = DropDownList1.SelectedValue;
string valor = "%" + TextBox1.Text.Replace(" ", "%") + "%"; // no reason to NOT one-line this
/*
* This would probably be easier to maintain if DropDownList1
* was bound to an enumeration of these values:
* DataTextField="someTextField"
* DataValueField="someCorrespondingNumericField"
* If bound that like above, your switch statement becomes:
* Integer.Parse(DropDownList1.SelectedValue, numo);
* and numo then contains 1, 2, 3, or 4 thus eliminating the need for the variable num3.
*/
switch (numo)
{
case "Nome":
num3 = 1;
break;
case "Endereço":
num3 = 2;
break;
case "Telefone":
num3 = 3;
break;
case "Pedido":
num3 = 4;
break;
}
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "cazacliente2";
// add parameters and set values all at once
cmd.Parameters.Add("#vbusca", SqlDbType.NVarChar, 60).Value = valor;
cmd.Parameters.Add("#bo",SqlDbType.Int).Value = num3;
if (conex1.State == ConnectionState.Closed)
{
conex1.Open();
}
cmd.Connection = conex1;
GridView1.EmptyDataText = "Nao se " + numo.ToString() +" encontraron registros";
GridView1.DataSource = cmd.ExecuteReader();
GridView1.DataBind();
}
catch (Exception ex)
{
throw ex;
}
finally
{
conex1.Close();
}
}
Also, your stored procedure can be written a little more cleanly:
ALTER PROCEDURE [dbo].[cazacliente2] (
#vbusca nvarchar(60)
, #bo int
)
AS
SELECT idcliente
, nome
, endere
, tel
, pedido
FROM Vw_Conscliente
WHERE CASE
WHEN #bo = 1 THEN nome
WHEN #bo = 2 THEN endere
WHEN #bo = 3 THEN tel
WHEN #bo = 4 THEN pedido
END LIKE #vbusca
I would move the wild card to the TSQL instead of the C#. That way you can test it independently.
Your definition shows a maximum length of 60.
#vbusca nvarchar(60)
Is the parameter you passing from C# to SQL greater than that? You should look at the local variable on a break point in Visual Studio to confirm this is not true.
Also, replacing spaces inside the parameter means that the logical words in side the parameter just need to match in any order. Is this what you want?
'afonso 60' matches 'afsonso when to the store to by milk that cost 60 dollars'
Check out MSDN for wild card usage:
http://technet.microsoft.com/en-us/library/ms189454.aspx
I used dynamic SQL below since it reduces the overall code size.
Sample code change:
ALTER PROC [dbo].[cazacliente2] (#vbusca nvarchar(32), #bo int) AS
BEGIN
-- Local variables
DECLARE #statement VARCHAR(MAX);
DECLARE #field VARCHAR(MAX);
DECLARE #expression VARCHAR(MAX);
-- Make the expression (exact match of #vbusca)
SET #expression = '%' + REPLACE(#vbusca,'''', '''''') + '%';
-- Optional way (match words in #vbusca in order)
-- SET #expression = '%' + REPLACE(REPLACE(#vbusca,'''', ''''''), ' ', '%') + '%'
-- Which field
SELECT #field =
CASE #bo
WHEN 1 then 'nome'
WHEN 2 then 'endere'
WHEN 3 then 'tel'
WHEN 4 then 'pedido'
ELSE 'nome'
END;
-- Make up the dynamic SQL
SET #statement = 'select idcliente, nome, endere, tel, pedido ' +
' from Vw_Conscliente where ' + #field + ' like ' + #expression;
-- Execute the SQL statement
EXEC #statement;
END;
I will be adding a caution advisory to any dynamic TSQL that I write in the future. Here is a link on how to handle injection issues.
http://technet.microsoft.com/en-us/library/ms161953(v=sql.105).aspx
Updated SP to handle issues by reducing search pattern size and handling single quotes inside the parameter.
I think this is the best solution so far, no SQL injection, does handle when invalid #bo is passed, defaults to nome.
ALTER PROCEDURE [dbo].[cazacliente2] (#vbusca nvarchar(60), #bo int)
AS
SELECT
idcliente
, nome
, endere
, tel
, pedido
FROM
Vw_Conscliente
WHERE
CASE
WHEN #bo = 1 THEN nome
WHEN #bo = 2 THEN endere
WHEN #bo = 3 THEN tel
WHEN #bo = 4 THEN pedido
ELSE nome
END LIKE #vbusca;
When I try to run this, it gives me the following error message:
Conversion failed when converting the varchar value 'category_id' to data type int.
Here's my SQL and parameter code, I supposed it should work, but it doesn't.
mycmd.CommandText="SELECT * FROM categories WHERE #db_property = #property_id";
// This contains a string "category_id", which is correct.
mycmd.Parameters.Add("#db_property", SqlDbType.VarChar).Value=db_property_field;
// This contains an Int, referring to the category_id in database. As of now, this is 1
mycmd.Parameters.Add("#property_id", SqlDbType.Int).Value=property_id;
After I'm going through this code, I run it through a Reader, and that's where I get the error message above. Been asking teacher, and excellent students in my class, no one can find a clue on, where the problem is.
You shouldn't add field name as parameter. Try to change your script to include actual field id:
mycmd.CommandText = "SELECT * FROM categories WHERE category_id = #property_id";
mycmd.Parameters.Add("#property_id", SqlDbType.Int).Value = property_id;
I'm not sure about your structure, but try the following:
mycmd.CommandText = "SELECT * FROM categories WHERE Cast(#db_property as Int) = #property_id";
Your query is matching the two variables you are passing in so it will either return all the data or none of it! On top of that you are matching a char variable with an int. SQL will try to cast the char variable to an int.
#db_property = #property_id
should your query look like this?
SELECT * FROM categories WHERE db_property = #db_property AND property_id = #property_id
If you look at your statement you are comparing the two parameters. The WHERE clause is not on a table column ("categories") and the two parameters you are passing are different data types. VarChar and Int. When that command is executed the SQL engine is trying to compare two variables of different data types.
If you run the following SQL statements straight against SQL you will receive the same error.
DECLARE #Var1 VARCHAR(100)
DECLARE #Var2 INT
SELECT #Var1 = 'Test', #Var2 = 1
SELECT * FROM dbo.categories WHERE #Var1 = #Var2
You can get solution from the following address:
http://net-informations.com/csprj/data-providers/cs-procedure-parameter.htm
For your information I Just reshape the code and use it to my needs.
Code of Stored Procedure is as follow:
Create PROCEDURE [dbo].[PmSPValidate]
#a varchar(10)
AS
BEGIN
(SELECT AcctDsc,AcctAge
FROM dbo.tblCoa
WHERE AcctNo >= #a)
END
Code of C# :
private void btnThirdTrial_Click(object sender, EventArgs e)
{
string connetionString = null;
SqlConnection connection;
SqlDataAdapter adapter;
SqlCommand command = new SqlCommand();
SqlParameter param;
DataSet ds = new DataSet();
int i = 0;
connetionString = "Data Source=FIN03;Initial Catalog=CmsTest;Integrated Security=True";
connection = new SqlConnection(connetionString);
connection.Open();
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "dbo.PmSPValidate";
param = new SqlParameter("#a",Account.Text.ToString ());
param.Direction = ParameterDirection.Input;
param.DbType = DbType.String;
command.Parameters.Add(param);
adapter = new SqlDataAdapter(command);
adapter.Fill(ds);
for (i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
{
MessageBox.Show(" Name " + ds.Tables[0].Rows[i][0].ToString() + " Age " + ds.Tables[0].Rows[i][1].ToString());
}
connection.Close();
}
I Created this Select Stored Procedure:
#SerialNumber varchar(50)
#PalletNumber varchar(50) ------> Datatype int
SELECT
,SerialNumber
, PalletNumber
FROM dbo.FG_FILLIN
WHERE (SerialNumber LIKE #SerialNumber + '%' )
AND (PalletNumber = #PalletNumber)
I change #palletnumber to varchar because Like '%' doesnt accept int.
My Data Access :
public DataSet FGSearchAll(FillinEntity fin)
{
SqlConnection conn = new SqlConnection(connStr);
SqlCommand cmd = new SqlCommand("FGSearchAll", conn);
cmd.CommandType = CommandType.StoredProcedure;
DataSet dSet = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(cmd);
cmd.Parameters.Add("#SerialNumber", SqlDbType.VarChar, 50).Value =
fin.SerialNumber;
cmd.Parameters.Add("#PalletNumber", SqlDbType.Int).Value =
fin.PalletNumber;
try
{
conn.Open();
da.Fill(dSet, "FGDATA");
conn.Close();
}
catch (SqlException)
{
throw;
}
return dSet;
}
UI:
private void SearchAll()
{
BAL obj = new BAL();
FillinEntity fin = new FillinEntity();
fin.SerialNumber = txtSearchSerial.Text ;
**fin.PalletNumber = Convert.ToInt32(txtSearchPallet.Text);**
try
{
dsdata = obj.FGSearchAll(fin);
if (dsdata.Tables[0].Rows.Count < 1)
{
MessageBox.Show("No Record Found!");
}
else
{
dgWIP.DataSource = dsdata;
dgWIP.DataMember = "FGDATA";
}
}
catch (ApplicationException ex)
{
MessageBox.Show(ex.Message);
}
}
All Things works fine if i have input Both but when i just search for Serial number and pallet has an empty value it shows an error.
Any idea?.
Thanks in regards.
This error is nothing to do with your SQL.
The error is in the line you asterisk'ed in your post.
fin.PalletNumber = Convert.ToInt32(txtSearchPallet.Text);
If txtSearchPallet.Text is empty, you are trying to convert an empty string into an integer, and this is what gives you the "Input string was not in a correct format." exception.
You need to first of all detect if the pallet number is an empty string, and assign -1 (say) to your FillInEntity instance.
e.g.
fin.PalletNumber =
(txtSearchPallet.Text == "") ? -1 : Convert.ToInt32(txtSearchPallet.Text);
This will stop the exception happening.
I would continue then as follows:
Change the line assigning the parameter value to the following
DbParameter pallet = cmd.Parameters.Add("#PalletNumber", SqlDbType.Int);
if (fin.PalletNumber == -1)
pallet.Value = DBNull.Value
else
pallet.Value = fin.PalletNumber
Change the stored proc so that #PalletNumber is of datatype int, and the where clause is
WHERE
(
SerialNumber LIKE #SerialNumber + '%'
AND
(
#PalletNumber is null
or
PalletNumber = #PalletNumber
)
)
You will have to add logic in to your Stored Procedure to check that the parameter values don't contain NULL values
You will have to do something like this:
if (#PalletNumber is Null)
begin
SELECT
,SerialNumber
, PalletNumber
FROM dbo.FG_FILLIN
WHERE (SerialNumber LIKE #SerialNumber + '%' )
end
else
begin
SELECT
,SerialNumber
, PalletNumber
FROM dbo.FG_FILLIN
WHERE (SerialNumber LIKE #SerialNumber + '%' )
AND (PalletNumber LIKE #PalletNumber + '%')
end
You need dynamic sql here or use IsNull
#PalletNumber varchar(50) = NULL -- default null
SELECT *
FROM #FG_FILLIN
WHERE (SerialNumber LIKE #SerialNumber + '%' )
AND (PalletNumber = #PalletNumber OR #PalletNumber IS NULL)
Your select also has syntax error; i.e, ',' after SELECT
I don’t think it has anything to do with the SQL. The error message
Input string was not in a correct format.
is exactly the message you get with the FormatException thrown by Convert.ToInt32() when the input string is not a number.
Therefore, instead of:
fin.PalletNumber = Convert.ToInt32(txtSearchPallet.Text);
You should perhaps try something like...
if (!int.TryParse(txtSearchPallet.Text, out fin.PalletNumber))
{
MessageBox.Show("Please enter a number between x and y.");
return;
}
This will attempt to turn the string into an integer and store the result in fin.PalletNumber. If the conversion fails, the MessageBox appears to alert the user and the operation is not attempted.
I am using the following Code to execute the SP of MySql and get the output value. I need to get the output value to my c# after SP is executed. How ? Thanks.
Code :
public static string GetInsertStatement(string DBName, string TblName, string ColName, string ColValue)
{
string strData = "";
MySqlConnection conn = new MySqlConnection(ConfigurationSettings.AppSettings["Con_Admin"]);
MySqlCommand cmd = conn.CreateCommand();
try
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "InsGen";
cmd.Parameters.Clear();
cmd.Parameters.Add("in_db", MySqlDbType.VarChar, 20);
cmd.Parameters["in_db"].Value = DBName;
cmd.Parameters.Add("in_table", MySqlDbType.VarChar, 20);
cmd.Parameters["in_table"].Value = TblName;
cmd.Parameters.Add("in_ColumnName", MySqlDbType.VarChar, 20);
cmd.Parameters["in_ColumnName"].Value = ColName;
cmd.Parameters.Add("in_ColumnValue", MySqlDbType.VarChar, 20);
cmd.Parameters["in_ColumnValue"].Value = ColValue;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
catch (System.Exception e)
{
Console.WriteLine(e.Message);
}
return strData;
}
SP :
DELIMITER $$
DROP PROCEDURE IF EXISTS `InsGen` $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `InsGen`
(
in_db varchar(20),
in_table varchar(20),
in_ColumnName varchar(20),
in_ColumnValue varchar(20)
)
BEGIN
declare Whrs varchar(500);
declare Sels varchar(500);
declare Inserts varchar(2000);
declare tablename varchar(20);
declare ColName varchar(20);
set tablename=in_table;
# Comma separated column names - used for Select
select group_concat(concat('concat(\'"\',','ifnull(',column_name,','''')',',\'"\')'))
INTO #Sels from information_schema.columns where table_schema=in_db and table_name=tablename;
# Comma separated column names - used for Group By
select group_concat('`',column_name,'`')
INTO #Whrs from information_schema.columns where table_schema=in_db and table_name=tablename;
#Main Select Statement for fetching comma separated table values
set #Inserts=concat("select concat('insert into ", in_db,".",tablename," values(',concat_ws(',',",#Sels,"),');')
from ", in_db,".",tablename, " where ", in_ColumnName, " = " , in_ColumnValue, " group by ",#Whrs, ";");
PREPARE Inserts FROM #Inserts;
select Inserts;
EXECUTE Inserts;
END $$
DELIMITER ;
Using output query parameter.
http://msdn.microsoft.com/en-us/library/59x02y99(VS.71).aspx
If I'm not mistaken instead of
cmd.ExecuteNonQuery();
there is an "ExecuteScalar" which will return a Scalar value.
The problem is that you're calling
cmd.ExecuteNonQuery();
That executes without reading back results.
Have a look at the documentation for Command, especially the methods that start with Execute, and decide which one's best for you