I've been developing a stored procedure in order to get a register from a table so I built the following query to achieve this:
ALTER procedure [dbo].[procedure_odd]
#codSeccion int,
#NomDoce varchar(500),
#codMate varchar(500)
as
begin
declare #hora varchar(50);
set #hora = (
select b.man_nomhor
from ra_hpl_horarios_planificacion a
inner join ra_man_grp_hor b on a.hpl_codman = b.man_codigo
where a.hpl_codcil = 100
and a.hpl_codemp = (select emp_codigo from pla_emp_empleado
where emp_nombres_apellidos = #NomDoce)
and a.hpl_codmat = #codMate
and a.hpl_descripcion = #codSeccion)
return #hora
end
I've tested this query (ONLY the query not the stored procedure with the query) in my SQL Server console and it works just fine. The problem is when I call it from C# it doesn't work no matter what I try! Also I tried to develop a stored procedure with output parameter but with no result.
Also I've tried this other way(which works so good and fine!):
select b.man_nomhor
from ra_hpl_horarios_planificacion a
inner join ra_man_grp_hor b on a.hpl_codman = b.man_codigo
where a.hpl_codcil = 100
and a.hpl_codemp =
(select emp_codigo from pla_emp_empleado
where emp_nombres_apellidos = 'julio escobar')
and a.hpl_codmat = 'FONO-I'
and a.hpl_descripcion = 1;
Here is my code on C# (My 11000 solution):
public String horarios(int Seccion, string NomDocent, string CodMate)
{
cn.Open();
cmd.Connection = cn;
cmd.CommandText = "select b.man_nomhor from ra_hpl_horarios_planificacion
a inner join ra_man_grp_hor b on a.hpl_codman = b.man_codigo where
a.hpl_codcil = 100 and a.hpl_codemp =(select emp_codigo from
pla_emp_empleado where emp_nombres_apellidos = '" + NomDocent +
"') and a.hpl_codmat = '" + CodMate + "' and a.hpl_descripcion = '" + Seccion + "'";
dr = cmd.ExecuteReader();
if (dr.HasRows)
{
if (dr.Read())
{
msj = dr[0].ToString();
}
}
cn.Close();
return msj;
}
When I run my Visual Studio it doesn't show any error at all but in the variable MSJ it set an empty STRING like this MSJ = "";
This must be really easy but it just that (believe) I've tried so hard to get to the solution with bno results, please help!
It looks like Seccion (and thus a.hpl_descripcion) are integers, but your query is placing apostrophes around it like a literal.
Try removing the apostrophes:
... + "' and a.hpl_descripcion = " + Seccion;
If that's indeed the issue, parameterizing your query can eliminate these kinds of mistakes:
cmd.CommandText = "... and a.hpl_codemp =(select emp_codigo from pla_emp_empleado where emp_nombres_apellidos = #NomDocent) and a.hpl_codmat = #CodMate and a.hpl_descripcion = #Seccion";
cmd.AddParameterWithValue("#NomDocent", NomDocent);
cmd.AddParameterWithValue("#CodMate", CodMate);
cmd.AddParameterWithValue("#Seccion, Seccion);
dr = cmd.ExecuteReader();
Few things:
if you want this to be a stored procedure, be sure to set command.CommandType = CommandType.StoredProcedure.
you do not need to call return or set a variable to return the text you have. instead, just have a select statement return the one field:
ALTER procedure [dbo].[procedure_odd]
#codSeccion int,
#NomDoce varchar(500),
#codMate varchar(500)
as
begin
select top 1 b.man_nomhor from ra_hpl_horarios_planificacion a inner join
ra_man_grp_hor b on a.hpl_codman = b.man_codigo where a.hpl_codcil = 100
and a.hpl_codemp = (select emp_codigo from pla_emp_empleado
where emp_nombres_apellidos = #NomDoce) and a.hpl_codmat = #codMate and
a.hpl_descripcion = #codSeccion)
END
once this is done, just execute the stored procedure with a dataReader, that will return your value. if you need more information, I can edit my answer to clarify.
Related
I am getting a index out of range error when trying to get a string value from a datareader. The column USER_ROLE which is the only column from a INNER JOIN condition. It was working and for some reason has now started throwing this index out of range error. I've verified the actual stored procedure works via SSMS and the column is being returned.
Below is the code for the stored procedure
ALTER PROCEDURE [dbo].[usp_GetUsersLogonInformation]
(
-- inactive = 0, active = 1, all = 2
#active int = 2
)
AS
BEGIN
DECLARE #whereClauseNeeded bit = 1
DECLARE #whereClause nvarchar(100) = concat(' WHERE usr.ACTIVE = ', #active)
DECLARE #sqlCmd nvarchar(max)= 'SELECT
usr.USER_PK,
usr.PRINCIPAL_ID,
usr.AA_USER_FK,
usr.FIRST_NAME,
usr.LAST_NAME,
usr.[USER_NAME],
usr.EMAIL_ADDRESS,
usr.ACTIVE,
usr.LV_USER_ROLE_FK,
lvur.USER_ROLE,
usr.CREATED_BY,
usr.CREATED_SYSDATE
FROM dbo.USERS usr
INNER JOIN dbo.LV_USER_ROLES lvur ON lvur.LV_USER_ROLE_PK = usr.LV_USER_ROLE_FK'
IF #active = 0 OR #active = 1
BEGIN
set #sqlCmd = concat(#sqlCmd, #whereClause)
END
EXEC sp_executesql #sqlCmd
END
the c# code retrieving the data
using (SqlConnection dbConn = theVoiceSqlHelpers.GetDbConnection())
{
using (SqlCommand sqlCmd = new SqlCommand(USP_GET_USER_INFO, dbConn))
{
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("#whereClause",string.Format("USER_NAME = \'{0}\'", txbxUserName.Text));
SqlDataReader dr = sqlCmd.ExecuteReader();
while (dr.Read())
{
user = new Tbl_Users();
user.USER_PK = dr.GetInt32(dr.GetOrdinal("USER_PK"));
user.PRINCIPAL_ID = dr.GetInt32(dr.GetOrdinal("PRINCIPAL_ID"));
user.AA_USER_FK = dr.GetInt32(dr.GetOrdinal("AA_USER_FK"));
user.FIRST_NAME = dr.GetString(dr.GetOrdinal("FIRST_NAME"));
user.LAST_NAME = dr.GetString(dr.GetOrdinal("LAST_NAME"));
user.USER_NAME = dr.GetString(dr.GetOrdinal("USER_NAME"));
user.EMAIL_ADDRESS = dr.GetString(dr.GetOrdinal("EMAIL_ADDRESS"));
user.ACTIVE = dr.GetBoolean(dr.GetOrdinal("ACTIVE"));
user.LV_USER_ROLE_FK = dr.GetInt32(dr.GetOrdinal("LV_USER_ROLE_FK"));
user.USER_ROLE = dr.GetString(dr.GetOrdinal("USER_ROLE"));
user.CREATED_BY = dr.GetString(dr.GetOrdinal("CREATED_BY"));
user.CREATED_SYSDATE = dr.GetDateTime(dr.GetOrdinal("CREATED_SYSDATE"));
}
dr.Close();
}
}
I have ensure the column name is correct however I am now stuck at this new found exception.
Has anyone seen this behavior before. My apologies if I am overlooking and obvious but could use an extra set of eyes on this.
LV_USER_ROLES Table
USERS Table
Charlieface's comment resolved the exception. In this database there is 2 similiar named usp's and I was calling the wrong one.
How does a SQL Server query select from parameter? I just want to make it simple set select column based on my C# code. Is it possible?
Here is my stored procedure:
ALTER PROCEDURE [dbo].[GetMembersDetailGenerateChanceTop10000]
#EventId nvarchar(255),
#PeriodId nvarchar(255),
#QueryParam nvarchar(1000)
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT TOP 10000 #QueryParam
FROM ign..Chance_Generated cg
INNER JOIN ign..Contact c ON cg.ContactID = c.ContactId
LEFT JOIN ign..CustomerAddress ca ON ca.parentid = cg.contactid
LEFT JOIN ign..new_cardlevelconfig cl ON cl.new_cardlevelconfigid = c.new_cardlevel
LEFT JOIN ign..new_country co ON co.new_countryid = c.new_country
LEFT JOIN ign..new_province po ON po.new_provinceId = c.new_Province
LEFT JOIN ign..StringMap sm ON sm.AttributeValue = c.new_IDType
LEFT JOIN ign..new_city cy ON cy.new_cityId = c.new_CityCounty
LEFT JOIN ign..new_transactionheader th ON cg.New_Name COLLATE DATABASE_DEFAULT = th.new_name COLLATE DATABASE_DEFAULT
WHERE cg.EventId = #EventId
AND (ca.AddressNumber = '1' OR ca.AddressNumber IS NULL)
AND (sm.AttributeName IS NULL OR sm.AttributeName = 'new_idtype')
AND cg.periodId = #PeriodId
QueryParam, EventId, PeriodId will be filled from C# code.
Here is my C# code:
private List<GenerateModel> getDataTopFromStoreProcedure(string EventId, string PeriodId)
{
// query select parameter
string QueryParam = #"cg.Chance_Number, th.new_name as [th name], dateadd(HOUR,7,th.createdon) as [th createdon],
c.new_Initial, c.FirstName, c.LastName";
string ConnString = GenerateChance.Properties.Settings.Default["DB_ConnectionString"].ToString();
using (SqlConnection conn = new SqlConnection(ConnString))
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = GetMembersDetailGenerateChanceTop10000;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0; //no limit
cmd.Parameters.Clear();
cmd.Parameters.Add(new SqlParameter("QueryParam", QueryParam));
cmd.Parameters.Add(new SqlParameter("EventId", EventId));
cmd.Parameters.Add(new SqlParameter("PeriodId", PeriodId));
cmd.Connection = conn;
if (conn.State == ConnectionState.Open)
conn.Close();
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
list.Add(new GenerateModel
{
ChanceNumber = reader["Chance_Number"].ToString(), //System.IndexOutOfRangeException Error
Receipt = reader["th name"].ToString(),
Date = reader["th createdon"].ToString(),
Initial = reader["new_Initial"].ToString(),
FirstName = reader["FirstName"].ToString(),
LastName = reader["LastName"].ToString(),
});
}
reader.Close();
}
}
return list;
}
I am confused as to how to implement his method because I want to get return of all select results in object model but I always get error
System.IndexOutOfRangeException : Chance_Number.
Honestly why do I use query select parameter is because I want to get value from checkedListBox1 that already I defined before by using this code get all checkedListBox1 value to determine select query.
string QueryParam = "cg.Chance_Number";//auto get chance_number as select mandatory
for (int i = 0; i < checkedListBox1.CheckedItems.Count; i++)
{
QueryParam += ", " + ((clsItemList)checkedListBox1.CheckedItems[i]).Value;
}
You have to use constructor with proper length for parameters as given below, to avoid the issue.Read more on SQLParameter
public SqlParameter (string parameterName, System.Data.SqlDbType dbType, int size);
cmd.Parameters.Add(new SqlParameter("QueryParam", SqlDbType.NVarChar,1000)).Value = QueryParam;
You need to make few more changes:
The way you have defined the procedure is wrong. You have to define the procedure as dynamic sql for the #queryparam to get concatenated to the SELECT query as given below:
DECLARE #selectStmt NVARCHAR(MAX) = ''
DECLARE #sqldefinition NVARCHAR(4000) = '#EventId nvarchar(255), #PeriodId nvarchar(255)'
SET #selectStmt += 'select distinct top 10000 ' + #QueryParam +
'from ign..Chance_Generated cg
inner join ign..Contact c on cg.ContactID = c.ContactId
left join ign..CustomerAddress ca on ca.parentid = cg.contactid
left join ign..new_cardlevelconfig cl on cl.new_cardlevelconfigid = c.new_cardlevel
left join ign..new_country co on co.new_countryid = c.new_country
left join ign..new_province po on po.new_provinceId = c.new_Province
left join ign..StringMap sm on sm.AttributeValue = c.new_IDType
left join ign..new_city cy on cy.new_cityId = c.new_CityCounty
left join ign..new_transactionheader th on cg.New_Name COLLATE DATABASE_DEFAULT = th.new_name COLLATE DATABASE_DEFAULT
where cg.EventId= '''+ #EventId +''' and (ca.AddressNumber = ''1'' or ca.AddressNumber is null) and (sm.AttributeName is null or sm.AttributeName = ''new_idtype'')
and cg.periodId = ''' + #PeriodId + ''';'
EXEC #sp_executesql #selectStmt, #sqldefinition, #EventId , #PeriodId
``
- Always refer the tables with proper schema in the query
ign.SchemaName.new_country
ign.SchemaName.new_province
I am creating a stored procedure to produce a list of items. The stored procedure returns a result and a return value. In my application that I am calling the stored procedures return the return value. How do I make it return the result?
This is my procedure:
CREATE PROCEDURE [AQB_RMS].[p_SO2EmailOverDue]
AS
(SELECT
CONVERT(CHAR(10), CheckDate, 101) AS ZSPDate,
Manufacturer, Model, SerialNumber, LocationName
FROM
[AQB_RMS].[SO2_Zsp] so
INNER JOIN
AQB_MON.[AQB_RMS].[Device] dev ON dev.DeviceID = so.DeviceID
INNER JOIN
AQB_MON.[AQB_RMS].[DeviceLocation] dl ON dev.DeviceID = dl.DeviceID
INNER JOIN
AQB_MON.[AQB_RMS].[Location] loc ON dl.LocationID = loc.LocationID
INNER JOIN
[AQB_RMS].[ManufacturerModel] mm ON dev.ManufacturerModelID = mm.ManufacturerModelID
INNER JOIN
[AQB_RMS].[Manufacturer] man ON mm.ManufacturerID = man.ManufacturerID
WHERE
CheckDate = (SELECT MAX(CheckDate) FROM [AQB_RMS].[SO2_Zsp]
WHERE DeviceID = so.DeviceID)
AND dl.EndDate IS NULL
AND (SELECT DATEDIFF(day, so.CheckDate, GetDate()) AS DayCount) > 14)
ORDER BY
CheckDate
RETURN
GO
The following is the return when I execute the stored procedure in SQL Server 2012
I am using the stored procedure to provide the results for the body of an email. I am using c#
static string Body()
{
//create a connection to the database
string ConnString = ConfigurationManager.ConnectionStrings["avdatauser"].ConnectionString;
StringBuilder sb = new StringBuilder();
using (SqlConnection con = new SqlConnection(ConnString))
{
con.Open();
SqlCommand cmd = new SqlCommand("AQB_RMS.p_SO2EmailNearDue", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
sb.Append("<strong>SO2 Analyzer ZSP due</strong>");
sb.Append("<br>");
sb.Append("<br>");
sb.Append("What do you want to say here to show these are the ones with a ZSP that are near due");
sb.Append("<br>");
sb.Append("<br>");
sb.Append(" " + cmd + " ");
con.Close();
}
return sb.ToString();
}
Issue
We are in the process of changing a database name on our server, but the database is huge and we want to create a small application that will loop through all databases, and then all the tables in the databases and then all the columns in the tables for text that matches "LIVE".
Code
I started creating code but i feel like this way in clunky and is returning an error.
using (SqlConnection connection = new SqlConnection(#"data source="SERVER NAME";integrated security=false;uid="USER";password="PASSWORD";"))
{
connection.Open();
SqlCommand command = new SqlCommand(#"SELECT * FROM sys.databases", connection);
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
_databases.Add(string.Format("{0}", reader["name"]));
}
}
finally
{
reader.Close();
}
foreach (var database in _databases)
{
using (SqlConnection tableconnection = new SqlConnection(string.Format(#"data source="SERVER NAME";initial catalog=" + database + ";integrated security=false;uid="USERNAME";password="PASSWORD";")))
{
tableconnection.Open();
SqlCommand tablecommand = new SqlCommand(#"SELECT * FROM information_schema.tables", tableconnection);
SqlDataReader readertable = tablecommand.ExecuteReader();
try
{
while (readertable.Read())
{
_tables.Add(string.Format("{0}", readertable["TABLE_NAME"]));
}
}
finally
{
readertable.Close();
}
foreach (var tables in _tables)
{
SqlCommand columncommand = new SqlCommand(string.Format(#"SELECT * FROM INFORMATION_SCHEMA.COLUMNS where TABLE_Name=" + tables, tableconnection));
SqlDataReader readercolumn = columncommand.ExecuteReader();
try
{
while (readercolumn.Read())
{
_columns.Add(string.Format("{0}", readercolumn["COLUMN_NAME"]));
}
}
finally
{
readercolumn.Close();
}
}
}
}
}
As you can see I am unsure if this is the best way to do it. The code errors on:
SqlDataReader readercolumn = columncommand.ExecuteReader();
and the error is:
Additional information: ExecuteReader: Connection property has not been initialized.
Does anyone know what is going wrong or a simple way to do this?
You can use this for your problem :). :
CREATE PROCEDURE dbo.SearchAllDatabases
#SearchTerm NVARCHAR(255) = NULL
AS
BEGIN
SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
IF #SearchTerm IS NULL OR #SearchTerm NOT LIKE N'%[^%^_]%'
BEGIN
RAISERROR(N'Please enter a valid search term.', 11, 1);
RETURN;
END
CREATE TABLE #results
(
[database] SYSNAME,
[schema] SYSNAME,
[table] SYSNAME,
[column] SYSNAME,
ExampleValue NVARCHAR(1000)
);
DECLARE
#DatabaseCommands NVARCHAR(MAX) = N'',
#ColumnCommands NVARCHAR(MAX) = N'';
SELECT #DatabaseCommands = #DatabaseCommands + N'
EXEC ' + QUOTENAME(name) + '.sys.sp_executesql
#ColumnCommands, N''#SearchTerm NVARCHAR(MAX)'', #SearchTerm;'
FROM sys.databases
WHERE database_id > 4 -- non-system databases
AND[state] = 0-- online
AND user_access = 0; -- multi-user
SET #ColumnCommands = N'DECLARE #q NCHAR(1),
#SearchCommands NVARCHAR(MAX);
SELECT #q = NCHAR(39),
#SearchCommands = N''DECLARE #VSearchTerm VARCHAR(255) = #SearchTerm;'';
SELECT #SearchCommands = #SearchCommands + CHAR(10) + N''
SELECT TOP(1)
[db] = DB_NAME(),
[schema] = N'' + #q + s.name + #q + '',
[table] = N'' + #q + t.name + #q + '',
[column] = N'' + #q + c.name + #q + '',
ExampleValue = LEFT('' + QUOTENAME(c.name) + '', 1000)
FROM '' + QUOTENAME(s.name) + ''.'' + QUOTENAME(t.name) + ''
WHERE '' + QUOTENAME(c.name) + N'' LIKE #'' + CASE
WHEN c.system_type_id IN(35, 167, 175) THEN ''V''
ELSE '''' END + ''SearchTerm;''
FROM sys.schemas AS s
INNER JOIN sys.tables AS t
ON s.[schema_id] = t.[schema_id]
INNER JOIN sys.columns AS c
ON t.[object_id] = c.[object_id]
WHERE c.system_type_id IN (35, 99, 167, 175, 231, 239)
AND c.max_length >= LEN(#SearchTerm);
PRINT #SearchCommands;
EXEC sys.sp_executesql #SearchCommands,
N''#SearchTerm NVARCHAR(255)'', #SearchTerm;';
INSERT #Results
(
[database],
[schema],
[table],
[column],
ExampleValue
)
EXEC[master].sys.sp_executesql #DatabaseCommands,
N'#ColumnCommands NVARCHAR(MAX), #SearchTerm NVARCHAR(255)',
#ColumnCommands, #SearchTerm;
SELECT[Searched for] = #SearchTerm;
SELECT[database],[schema],[table],[column],ExampleValue
FROM #Results
ORDER BY[database],[schema],[table],[column];
END
GO
And use it like this :
exec SearchAllDatabases #SearchTerm = '%value%'
Or execute this stored procedure from your code.
using (SqlConnection connection = new SqlConnection(#"data source="SERVER NAME";integrated security=false;uid="USER";password="PASSWORD";"))
{
conn.Open();
// 1. create a command object identifying the stored procedure
SqlCommand cmd = new SqlCommand("SearchAllDatabases", conn);
// 2. set the command object so it knows to execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add parameter to command, which will be passed to the stored procedure
cmd.Parameters.Add(new SqlParameter("#SearchTerm", value));
cmd.ExecuteNonQuery();
}
Your code
SqlCommand columncommand = new SqlCommand(string.Format(#"SELECT * FROM INFORMATION_SCHEMA.COLUMNS where TABLE_Name=" + tables, tableconnection));
The end of the statement has )), putting table connection as a parameter for string.Format, which you dont use, so either, move it or...
You should have:
SqlCommand columncommand = new SqlCommand(#"SELECT * FROM INFORMATION_SCHEMA.COLUMNS where TABLE_Name=" + tables, tableconnection);
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;