simplifying non-parametrized mysql queries - c#

I have a problem with mySql query below
SELECT name, hospitalID, currentAvgRating, rank
FROM ( SELECT name,hospitalID,currentAvgRating,city,
#curRank := #curRank + 1 AS rank
FROM hospitals h, ( SELECT #curRank := 0) r
ORDER BY currentAvgRating DESC
) toplist
WHERE toplist.hospitalID = #hospitalID
and city = #city
This query I am using to find the rank of particular item & it is working properly. But while runining in program I get Fatal errors of Parameter '#curRank' must be defined. But that is mysql syntax then how can I get it's parameters?
UPDATE
string str = "SELECT name, hospitalID, currentAvgRating, rank FROM (SELECT name,hospitalID,currentAvgRating,city,#curRank := #curRank + 1 AS rank FROM hospitals h, (SELECT #curRank := 0) r ORDER BY currentAvgRating DESC) toplist WHERE toplist.hospitalID = #hospitalID and city = #city";
con.Open();
MySqlCommand cmd = new MySqlCommand(str, con);
cmd.Parameters.AddWithValue("#hospitalID", generalID.Text);
cmd.Parameters.AddWithValue("#city", cityName.Text);
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
con.Close();

You can get the rank for a particular hospital/city pair without a rank. Here is a close approximation to your query:
select count(*) + 1 as ranking
from hospitals h cross join
(select h.currentAvgRating
from hospitals h
where h.hospitalID = #hospitalID and h.city = #city
) hh
where h.currentAvgRating > hh.currentAvgRating;
Unlike your code, this gives all hospitals with the same rating, the same ranking.
If you don't want to change the code, then refer to this answer. Actually, I'll quote the relevant part:
I have to add
;Allow User Variables=True
to the connection string

Your SQL is correct I think there are conflect with C# command parameter and mySQL parameter
try this modification of SQL code like this
SELECT name, hospitalID, currentAvgRating, rank
FROM ( SELECT name,hospitalID,currentAvgRating,city,
#curRank := #curRank + 1 AS rank
FROM hospitals h, ( SELECT #curRank := 0) r
ORDER BY currentAvgRating DESC
) toplist
WHERE toplist.hospitalID = ?hospitalID
and city = ?city
you c# like this
string str = <Example Above>;
con.Open();
MySqlCommand cmd = new MySqlCommand(str, con);
cmd.Parameters.AddWithValue("?hospitalID", generalID.Text);
cmd.Parameters.AddWithValue("?city", cityName.Text);
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
con.Close();
Just changeing the C# command parameter using ? than using #

Related

How to use two queries to find result on the basis of first query

I have two tables Repair_master and New_Equipment_info, with the query shown here, I am able to retrieve all the latest date record of maint. by grouping RID and fill the data grid.
SELECT
t1.RID
,t1.RDATE
,t1.EQ_ID
,new_equipment_info.Equipment_Name
,new_equipment_info.Complete_specification
,t1.DEPT
,t1.REPAIR_MAINT
,t1.ACTION_TAKEN
,t1.SAPRES
,t1.ATT_BY
,t1.[STATUS]
,t1.RNO
FROM
Equipment.dbo.REPAIR_MASTER t1
INNER JOIN
Equipment.dbo.new_EQUIPMENT_INFO
ON t1.EQ_ID = New_Equipment_info.Equipment_Id
INNER JOIN
(
SELECT
Eq_ID
,max(RDate) as MaxDate
FROM
Equipment.dbo.REPAIR_MASTER
group by
Eq_ID
) tm
ON t1.EQ_ID = tm.EQ_ID
and t1.RDATE = tm.MaxDate
WHERE
t1.Repair_Maint = 'maint.'
ORDER BY
t1.RDATE DESC
But I want to know the number of days from the last date filtered from query and current date.
Like this
DATEDIFF(day, MaxDate, GETDATE()) AS Difference)
Kindly advise
Further I want to enter number of days in text box and click button and show only those records having a difference greater than the value entered.
private void btnOverDue_Click(object sender, EventArgs e)
{
using (SqlConnection con = new SqlConnection(connString))
{
string p = "SELECT t1.[RID],t1.[RDATE],t1.[EQ_ID],new_equipment_info.Equipment_Name,new_equipment_info.Complete_specification," +
"t1.[DEPT],t1.[REPAIR_MAINT],t1.[ACTION_TAKEN],t1.[SAPRES],t1.[ATT_BY],t1.[STATUS],t1.[RNO]FROM([Equipment].[dbo].[REPAIR_MASTER] t1 inner join[Equipment].[dbo].new_EQUIPMENT_INFO ON " +
"t1.EQ_ID = New_Equipment_info.Equipment_Id inner join (select Eq_ID, max(RDate) as MaxDate FROM [Equipment].[dbo].[REPAIR_MASTER] group by Eq_ID) tm on t1.EQ_ID=tm.EQ_ID and t1.RDATE =tm.MaxDate)" +
"where t1.Repair_Maint='maint.' ORDER BY t1.RDATE desc";
SqlCommand cmd = new SqlCommand(p, con);
SqlDataAdapter dataadapter = new SqlDataAdapter(p, con);
DataSet ds = new DataSet();
dataadapter.Fill(ds, "Repair_master");
EquipGrid.DataSource = ds;
EquipGrid.DataMember = "Repair_master";
}
}

Select Query Parameter from C# in a stored procedure

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

Stored procedure returning result

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();
}

Update Each Exisiting Row of SQL Server Table Using Loop

I'm trying to update a certain column for each row in my SQL Server table, using ASP.NET, C#.
When this code is executed, I want the OrderNo of the first row in the column to be = 1. From then on, I want the OrderNo to increment by 1 for the other existing rows in the table.
At the moment, I can update the OrderNo of one row, however I can't get a loop to properly read through all the rows & increment as I would like.
Here is the structure of my table
And below is my C#:
con.Open();
SqlCommand cmdUpdateOrderNo;
cmdUpdateOrderNo = new SqlCommand("UPDATE tblImages SET [OrderNo]=#O WHERE [OrderNo] = 2;", con);
cmdUpdateOrderNo.Parameters.AddWithValue("#O", 4);
cmdUpdateOrderNo.ExecuteNonQuery();
Here is the reason I need to update the OrderNo:
protected void Timer1_Tick(object sender, EventArgs e)
{
int i = (int)ViewState["ImageDisplayed"];
i = i + 1;
ViewState["ImageDisplayed"] = i;
DataRow imageDataRow = ((DataSet)ViewState["ImageData"]).Tables["image"].Select().FirstOrDefault(x => x["order"].ToString() == i.ToString());
if (imageDataRow != null)
{
Image1.ImageUrl = "~/MyImages/" + imageDataRow["name"].ToString();
lblImageName.Text = imageDataRow["name"].ToString();
lblImageOrder.Text = imageDataRow["order"].ToString();
lblImageDesc.Text = imageDataRow["Desc"].ToString();
}
else
{
SetImageUrl();
}
}
private void SetImageUrl()
{
DataSet ds = new DataSet();//Creating a dataset
SqlDataAdapter da = new SqlDataAdapter("SELECT Name, [Order], [Desc] FROM tblImages", con);
da.Fill(ds, "image");
ViewState["ImageData"] = ds;//storing the dataset in a ViewState variable
ViewState["ImageDisplayed"] = 1;//storing order number of the image currently displayed
DataRow imageDataRow = ds.Tables["image"].Select().FirstOrDefault(x => x["order"].ToString() == "1");
Image1.ImageUrl = "~/MyImages/" + imageDataRow["name"].ToString();
lblImageName.Text = imageDataRow["name"].ToString();
lblImageOrder.Text = imageDataRow["order"].ToString();
lblImageDesc.Text = imageDataRow["Desc"].ToString();
}
I agree with #Jamiec on this that it seems like a bad idea, but you don't need a loop if it's really what you want to do. Here's an example using a CTE and a Window Function.
Example
WITH T AS
( SELECT
*,
ROW_NUMBER() OVER (ORDER BY ID) as RN
FROM YourTable
)
/* this shows you the results of the CTE,
specifically the ROW_NUMBER()
which will replace the OrderNo in the code below */
SELECT * FROM T
Runing This WIll Update Your Table
WITH T AS
( SELECT
*,
ROW_NUMBER() OVER (ORDER BY ID) as RN
FROM YourTable
)
UPDATE T
SET OrderNo = RN
When dealing with SQL you almost never want to be writing loops.
Try changing your command to this
; with cte as
(
select *, row_number() over (order by ID) as rn
from tblImages
)
update tblImages
set OrderNo = rn
from cte

input parameter to mysql syntax on C#

I try to input value but #numVal doest not work ( on the line begin with arr[10] )
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
MySqlConnection conDatabase = new MySqlConnection("Data Source=localhost;" +
"Persist Security Info=yes;" +
"UserId=tee; PWD=t5794849; database=ph3;");
conDatabase.Open();
// MySqlCommand cmdDatabase = new MySqlCommand("DROP TABLE IF EXISTS `q_mem_sur`; create table q_mem_sur as SELECT Count(*) As rowa, member.Ssurname, Sum(Case When ((member.status = '1')) Then 1 Else 0 End) As Status11 From member Group By member.Ssurname Order By rowa Desc;", conDatabase);
Console.WriteLine("Enter username");
string input = Console.ReadLine();
try
{
int numVal = Convert.ToInt16(input);
}
catch (FormatException )
{
Console.WriteLine("Input string is not a sequence of digits.");
}
catch (OverflowException )
{
Console.WriteLine("The number cannot fit in an Int32.");
}
string[] arr = new string[11];
arr[0] = "UPDATE `member` SET `amphurecode`= SUBSTRING(member.own,3,4)";
arr[1] = "UPDATE `member` SET `provincecode`= SUBSTRING(member.own,3,2)";
arr[2] = "DROP TABLE IF EXISTS `q_mem_tim`; create table q_mem_tim as SELECT member.idmember, member.own, member.provincecode, province.PROVINCE_NAME, member.amphurecode, amphur.AMPHUR_NAME, member.novote, member.Sname, member.Ssurname, member.Hno, member.Moo, member.Sex, member.tambol, member.dateofbirth, member.migratedate, Year( Current_Date( ) ) - Year( member.dateofbirth ) AS y, DATEDIFF('2011-08-01',(migratedate)) AS d FROM member LEFT JOIN amphur ON ( member.amphurecode = amphur.AMPHUR_CODE ) LEFT JOIN province ON member.provincecode = province.PROVINCE_CODE";
arr[3] = "DROP TABLE IF EXISTS `q_mem_sur`; create table q_mem_sur as SELECT Count(*) As rowa, member.Ssurname, Sum(Case When ((member.status = '1')) Then 1 Else 0 End) As Status11 From member Group By member.Ssurname Order By rowa Desc";
arr[4] = "DROP TABLE IF EXISTS `q_mem_hno` ; create table q_mem_hno as select member.Hno, member.Moo, member.tambol, COUNT( member.Hno ) AS cntHno, COUNT(DISTINCT member.Ssurname) as NoSur FROM member GROUP BY member.Hno, member.Moo, member.tambol ORDER BY cntHno DESC ";
arr[5] = "DROP TABLE IF EXISTS `q_pro_ori`; create table q_pro_ori as Select member.provincecode, count(*) As cnt From member Group By member.provincecode Order By cnt Desc ";
arr[6] = "DROP TABLE IF EXISTS `q_am_ori`; create table q_am_ori as Select member.amphurecode, member.provincecode, count(*) As cnt From member Group By member.amphurecode, member.provincecode Order By cnt Desc ";
arr[7] = "DROP TABLE IF EXISTS `Sur_Hno_`; create table Sur_Hno_ as SELECT count( * ) , Ssurname, q_mem_tim.Hno, q_mem_tim.Moo, q_mem_tim.tambol FROM q_mem_tim GROUP BY q_mem_tim.Ssurname, q_mem_tim.Hno, q_mem_tim.Moo, q_mem_tim.tambol ORDER BY count( * ) DESC";
arr[8] = "DROP TABLE IF EXISTS `q_dup_own`; create table q_dup_own as SELECT Count(*) as n ,member.own FROM member GROUP BY member.own order by n DESC ";
// arr[9] = "drop table if exists q_mem_birth; create table q_mem_birth as SELECT member.idmember, member.own, member.provincecode, province.PROVINCE_NAME, member.amphurecode, amphur.AMPHUR_NAME, member.Sname, member.Ssurname, member.Hno, member.Moo, member.Sex, member.tambol, member.dateofbirth, member.migratedate, member.fathercode , member.mathercode, Year( Current_Date( ) ) - Year( member.dateofbirth ) AS y, DATEDIFF('2011-08-01',(migratedate)) AS d ,member.inputstaf FROM member LEFT JOIN amphur ON ( member.amphurecode = amphur.AMPHUR_CODE ) LEFT JOIN province ON member.provincecode = province.PROVINCE_CODE WHERE DAYOFYEAR(member.dateofbirth)-DAYOFYEAR(NOW()) < 30 and DAYOFYEAR(member.dateofbirth)-DAYOFYEAR(NOW()) > -1 order by DAYOFYEAR(member.dateofbirth)";
arr[9] = "ALTER TABLE `q_mem_tim` ADD `agec` VARCHAR( 10 ) NULL ";
// arr[10] = "UPDATE q_mem_birth SET agec = CASE WHEN y < 10 THEN 'ด' WHEN y > 10 and y < 20 and Sex='ญ' THEN 'วญ' WHEN y > 10 and y < 20 and Sex='ช' THEN 'วช' ELSE 'ผญ' END";
arr[10] = "drop table if exists q_mem_birth; create table q_mem_birth as SELECT q_mem_tim.idmember,q_mem_tim.own,q_mem_tim.PROVINCE_NAME,q_mem_tim.AMPHUR_NAME,q_mem_tim.novote,q_mem_tim.Sname,q_mem_tim.Ssurname,q_mem_tim.Hno,q_mem_tim.Moo,q_mem_tim.Sex,q_mem_tim.tambol,q_mem_tim.dateofbirth,q_mem_tim.migratedate,q_mem_tim.y,q_mem_tim.d,q_mem_tim.agec FROM q_mem_tim where q_mem_tim.dateofbirth is not null and q_mem_tim.dateofbirth != '00000000' and day(q_mem_tim.dateofbirth) != '00' and day(q_mem_tim.dateofbirth) > 0 and day(q_mem_tim.dateofbirth) < 11 and month(q_mem_tim.dateofbirth) != '00' and month(q_mem_tim.dateofbirth) = #numVal order by tambol,Moo, month(dateofbirth),day(dateofbirth) ";
foreach (string s in arr)
{
Console.WriteLine(s);
MySqlCommand cmdDbase = new MySqlCommand((s), conDatabase);
cmdDbase.CommandTimeout = 500;
cmdDbase.ExecuteNonQuery();
}
conDatabase.Close();
}
}
}
1)Truncate the tables; don't drop them and remake them because when you drop them you have to do the indexes and add the Primary Keys again.
using(var cm = _dbConnection.CreateCommand())
{
cm.CommandText = #"Truncate Table Table";
cm.CommandType = CommandType.Text;
cm.ExecuteNonQuery();
}
2)Don't forget the # symbol; it helps with anything SQL:
using(var cm = _dbConnection.CreateCommand())
{
cm.CommandText = #"Select *
From table
Where Id = #Id";
cm.CommandType = CommandType.Text;
cm.Parameter.AddWithValue("Id", id);
cm.ExecuteNonQuery();
}
I know you're not doing it this way and you're using a string array (just put a foreach loop outside the using statement and replace the cm.CommandText value with the string's value) but with the examples it should help you or at least give you some ideas.
You need to add a MySqlParameter to the command named numVal.

Categories

Resources