At the moment I am trying to query a broken database in c#. The recently introduced error is that when data is input in a particular way, a value in a column is defaulted to 0, which is problematic for me, as I have no control over what the user does or what the dba does.
To get around this, I have found another path to the data I need to output to the user. Problem is there is I have the requirement from my supervisor to support the old method in the event of the column coming up as a non-zero number.
I am trying to do this with either a case or an if command, but I not that great with sql, so I am not 100% sure where I am going wrong or how to go about it properly/efficiently. These are the commands in their current states:
SqlCommand caseCmd = new SqlCommand(
"SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, TC.DOCLE, TC.ICPC, TC.ICD10, TERMCODE =" +
" CASE H.ITEMCODE WHEN 0" +
" THEN TN.TERMID" +
" ELSE H.ITEMCODE END" +
" FROM " + _databaseName + ".dbo.PASTHISTORY H" +
" INNER JOIN " + _drugDatabaseName + ".dbo.TERMNAMES TN ON TN.TERMNAME = H.ITEMTEXT" +
" INNER JOIN " + _drugDatabaseName + ".dbo.TERMCODES TC ON TC.TERMID = TERMCODE" +
" INNER JOIN " + _drugDatabaseName + ".dbo.CONDITIONS C ON C.TERMID = TERMCODE" +
" WHERE H.INTERNALID = #patientid" +
" AND H.RECORDSTATUS = 1" +
" AND ((H.CREATED >= #mindate) OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= #mindate)))" +
" AND TC.RECORDSTATUS = 1",
Connection);
caseCmd.Parameters.AddWithValue("#patientid", int.Parse(patientId));
caseCmd.Parameters.AddWithValue("#mindate", minEnteredDate);
// Current error:
// When using 'TC.TERMID = TERMCODE', I get the error 'The conversion of the varchar value
// "3951000119103 " overflowed an int column'.
// This is alleviated by using either TN.TERMID OR H.ITEMCODE
SqlCommand ifCmd = new SqlCommand(
"IF (H.ITEMCODE = 0)" +
" SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, TC.DOCLE, TC.ICPC, TC.ICD10, TN.TERMID" +
" FROM " + _databaseName + ".dbo.PASTHISTORY H" +
" INNER JOIN " + _drugDatabaseName + ".dbo.TERMNAMES TN ON TN.TERMNAME = H.ITEMTEXT" +
" INNER JOIN " + _drugDatabaseName + ".dbo.TERMCODES TC ON TC.TERMID = TN.TERMID" +
" INNER JOIN " + _drugDatabaseName + ".dbo.CONDITIONS C ON C.TERMID = TN.TERMID" +
" WHERE H.INTERNALID = #patientid" +
" AND H.RECORDSTATUS = 1" +
" AND ((H.CREATED >= #mindate) OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= #mindate)))" +
" AND TC.RECORDSTATUS = 1" +
" ELSE IF (H.ITEMCODE <> 0)" +
" SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, H.ITEMCODE, TC.DOCLE, TC.ICPC, TC.ICD10" +
" FROM " + _databaseName + ".dbo.PASTHISTORY H" +
" INNER JOIN " + _drugDatabaseName + ".dbo.TERMCODES TC ON TC.TERMID = H.ITEMCODE" +
" INNER JOIN " + _drugDatabaseName + ".dbo.CONDITIONS C ON C.TERMID = H.ITEMCODE" +
" WHERE H.INTERNALID = #patientid" +
" AND H.RECORDSTATUS = 1" +
" AND ((H.CREATED >= #mindate) OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= #mindate)))" +
" AND TC.RECORDSTATUS = 1",
Connection);
ifCmd.Parameters.AddWithValue("#patientid", int.Parse(patientId));
ifCmd.Parameters.AddWithValue("#mindate", minEnteredDate);
// Current error:
// Getting two lines both saying 'The multi-part identifier "H.ITEMCODE" could not be bound.'
// I trust this is because of the IF and ELSE IF statements.
// Starting to think IF isn't the answer for me.
// Use either
SqlDataReader rdr = caseCmd.ExecuteReader();
// or
// SqlDataReader rdr = ifCmd.ExecuteReader();
Is this even remotely feasible or should I look into just making two sql commands for both alternatives and search through them both?
For clarity I took SQL out of C# string and used CTE. Basically, you can first patch the data and then use it for the lookups:
WITH PatchedHistory AS (
SELECT
H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT
, COALESCE(TN.TERMID, H.ITEMCODE) AS ITEMCODE --< TERMID with ITEMCODE fall-back
FROM _databaseName.dbo.PASTHISTORY H
LEFT JOIN _drugDatabaseName.dbo.TERMNAMES TN
ON H.ITEMCODE = 0 --< Lookup only if ITEMCODE is 0
AND TN.TERMNAME = H.ITEMTEXT
WHERE H.INTERNALID = #patientid --< Apply most of the filtering here
AND H.RECORDSTATUS = 1
AND ((H.CREATED >= #mindate) --< Suspicious condition
OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= #mindate))
)
)
SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, H.ITEMCODE
, TC.DOCLE, TC.ICPC, TC.ICD10 --< Add the rest of the data
FROM PatchedHistory H
INNER JOIN _drugDatabaseName.dbo.TERMCODES TC
ON TC.TERMID = H.ITEMCODE --< Join on the "patched" ITEMCODE
INNER JOIN _drugDatabaseName.dbo.CONDITIONS C
ON C.TERMID = H.ITEMCODE --< Join on the "patched" ITEMCODE
WHERE TC.RECORDSTATUS = 1
Also this condition looks suspicious:
AND ((H.CREATED >= #mindate)
OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= #mindate))
)
technically it is equivalent to just
AND ((H.CREATED >= #mindate) OR (H.UPDATED >= #mindate))
It looks like the intention was
AND COALESCE(H.UPDATED, H.CREATED) >= #mindate
Related
An error appear when i want to execute my SQL statement in C# application, which it's:
No value given for one or more required parameters.
I'm using c# with MS access database.
This is my code:
string string2 = "";
if (radButton2 != null)
{
string2 = " and signaal1.info='" + radButton2.Text + "' ";
}
else
string2 = " and signaal1.info='0' ";
if (radButton3 != null)
{
string2 += " and situation.info='" + radButton3.Text + "' ";
}
OleDbCommand cmd = new OleDbCommand("SELECT actionz.info, relationz.id AS actionz FROM ((((relationz LEFT OUTER JOIN conditions ON relationz.conditions_id = conditions.id) LEFT OUTER JOIN situation ON relationz.situation_id = situation.id) LEFT OUTER JOIN car_type ON relationz.car_id = car_type.id) LEFT OUTER JOIN actionz ON relationz.action_id = actionz.id) LEFT OUTER JOIN signal AS signaal1 ON relationz.signal_id = signaal1.id where car_type.info='" + radButton1.Text + "' " + string2 + " ORDER BY conditions.id ASC", objConn);
//cmd.Parameters.AddWithValue("#car_type", radButton1.Text);
OleDbDataReader dataReader = cmd.ExecuteReader();
Typo:
" ...info='" + radButton1.Text + "' " + string2 + " ORDER BY ..."
should be
" ...info='" + radButton1.Text + string2 + "' ORDER BY ..."
or if you need the space between the values:
" ...info='" + radButton1.Text + " " + string2 + "' ORDER BY ..."
Open to Injection though as mentioned.
I am making a query to 3 Mysql tables:
Sql = "SELECT " +
" u.iUserID, " +
" u.szPlayerName, " +
" u.szPlayerSurname, " +
" u.iPreferredPos, " +
" u.iAltPos, " +
" u.charType, " +
" c.szClubPrefix, "+
" tblteam.szTeamName " +
"FROM " +
" tblteam" +
" INNER JOIN tblusers u ON (tblteam.iTeamID = u.iTeamID) " +
" INNER JOIN tblclubs c ON (u.iClubID = c.iClubID) " +
"WHERE " +
"c.szClubPrefix = 'CLM' OR u.iClubID2 =' 2 ' AND " +
"u.bActive = 1 " +
"AND u.charType= 'c'" +
"ORDER BY " +
" tblteam.szTeamName DESC, " +
" u.szPlayerSurname;";
my problem is that; this query only returns the data where it match c.szClubPrefix = 'CLM' and not where it match u.iClubID2 =' 2 ' please anyone can Help me what I am doing wrong here?
Thanks for your help.
Add parenthesis with respect to your preferences
"(c.szClubPrefix = 'CLM' OR u.iClubID2 =' 2 ') AND " +
"u.bActive = 1 " +
"AND u.charType= 'c'"
wrap in parenthesis
(c.szClubPrefix = 'CLM' OR u.iClubID2 ='2')
and remove the whitespace before and after 2.
Note that dealing with numbers in MySQL you don't need the '
e.g.
iClubID2 = 2
instead of
iClubID2 ='2'
your where clause looks like this:
WHERE c.szClubPrefix = 'CLM' OR u.iClubID2 =' 2 ' AND u.bActive = 1 AND u.charType= 'c'
and it equivalence:
WHERE c.szClubPrefix = 'CLM' OR ( u.iClubID2 =' 2 ' AND u.bActive = 1 AND u.charType= 'c' )
so, u.iClubID2 =' 2 ' is one of those 3 conditions must be all true.
I'm transferring information from one Access DB to another using C#. Using the following code generates an error but by putting the query in Access using the same values, I get no error. Can anyone see what is going on?
string sqlInfaction = "INSERT INTO AquiredInfractions" +
"(AgentID, DateID, InfractionID, STime, Durration, Exception) " +
"SELECT " +
"#ID AS AgentID, (SELECT D.DateID FROM DateCodes AS D WHERE D.DateValue = #DT) AS DateID, " +
"I.InfractionID, #ST AS STime, #DR AS Durration, #E AS Exception " +
"FROM " +
"InfractionTypes AS I " +
"INNER JOIN " +
"Groupings AS G " +
"ON I.GroupingID = G.GroupingID " +
"WHERE " +
"G.GroupingTitle = #NAME " +
"AND " +
"I.MinDur <= #DR1 AND I.MaxDur >= #DR2;";
OleDbCommand InfCmd = null;
Then the setup:
string conString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\New.Employee\Documents\UserMan2.accdb";
conn = new OleDbConnection(conString);
InfCmd = new OleDbCommand(sqlInfaction, conn);
InfCmd.Parameters.Add("#ID", OleDbType.Integer);
InfCmd.Parameters.Add("#DT", OleDbType.Date);
InfCmd.Parameters.Add("#ST", OleDbType.SmallInt);
InfCmd.Parameters.Add("#DR", OleDbType.SmallInt);
InfCmd.Parameters.Add("#E", OleDbType.Boolean);
InfCmd.Parameters.Add("#NAME", OleDbType.VarWChar);
InfCmd.Parameters.Add("#DR1", OleDbType.SmallInt);
InfCmd.Parameters.Add("#DR2", OleDbType.SmallInt);
And in the transfer function:
InfCmd.Parameters["#ID"].Value = inf.AgentID;
InfCmd.Parameters["#DT"].Value = inf.date;
InfCmd.Parameters["#ST"].Value = inf.startTime;
InfCmd.Parameters["#DR"].Value = inf.durration;
InfCmd.Parameters["#E"].Value = inf.exception;
InfCmd.Parameters["#NAME"].Value = inf.infract;
InfCmd.Parameters["#DR1"].Value = inf.durration;
InfCmd.Parameters["#DR2"].Value = inf.durration;
InfCmd.ExecuteNonQuery();
In testing, I stepped through the running code, using the values that are put into the above parameters to test the query in Access.
The Value of sqlInfaction via quickwatch:
sqlInfaction "INSERT INTO AquiredInfractions(AgentID, DateID, InfractionID, STime, Durration, Exception)
SELECT #ID AS AgentID, (SELECT D.DateID FROM DateCodes AS D WHERE D.DateValue = #DT) AS DateID,
I.InfractionID, #ST AS STime, #DR AS Durration, #E AS Exception FROM InfractionTypes AS I
INNER JOIN Groupings AS G ON I.GroupingID = G.GroupingID WHERE G.GroupingTitle = #NAME
AND I.MinDur <= #DR1 AND I.MaxDur >= #DR2;" string
The exception gives the following:
Message: Syntax error in INSERT INTO statement.
Error Code: -2147217900
If there is something specific from the exception thrown, let me know but that is the entire message.
After playing around, I found the answer to be missing [] around Exception. The correct query reads:
string sqlInfaction = "INSERT INTO AquiredInfractions" +
"(AgentID, DateID, InfractionID, STime, Durration, [Exception]) " +
"SELECT " +
"#ID AS AgentID, (SELECT D.DateID FROM DateCodes AS D WHERE D.DateValue = #DT) AS DateID, " +
"I.InfractionID, #ST AS STime, #DR AS Durration, #E AS [Exception] " +
"FROM " +
"InfractionTypes AS I " +
"INNER JOIN " +
"Groupings AS G " +
"ON I.GroupingID = G.GroupingID " +
"WHERE " +
"G.GroupingTitle = #NAME " +
"AND " +
"I.MinDur <= #DR1 AND I.MaxDur >= #DR2;";
I am newbie to c# and I want to send a text file with a header and footer using a sql query.
I have an sql results in datagridview and then saved as text file. but everytime i run this query, i should get an header and footer from the sql query. So I am thinking of creating 2 buttons for headers and footers and when i click these it gets the value from sql to datagridview and it copies to textfile and the same for footer just appending different text to the samefile. I want any suggestions can i do like that.
private void btnGetData_Click(object sender, EventArgs e)
{
this.btnGetData.Enabled = false;
Application.DoEvents();
string stringSql = " SELECT distinct " +
"'" + comboBox6.Text + "' as RecordType" +
" , left([CPC No] +' ',30) " +
" , space(1983) " +
",'" + comboBox6.Text + " 'as RecordType" +
, left(t.t_reference + ' ' ,24 ) as ClaimantReference " +
" , left([Claim Number] +' ',30) " +
" , " + comboBox4.Text + " as CourtCode" +
" ,left(ta_title +' ',30) as Title " +
" ,left(ta_surname +' ',30) as Surname " +
", space(180), bat.PCN_Charge as ClaimAmount " +
",[Court Fee] " +
",[Solictors Fees]" +
", (bat.PCN_Charge + [Court Fee]) as TotalAmount" +
",[POC1]" +
",'" + textBox2.Text + "' as RequestType" +
//",'" + comboBox1.Text + "' as RecordType" +
",'" + textBox3.Text + "' as TotalCourtFee" +
",'" + textBox4.Text + "' as TotalClaimAmount" +
" , space(1966) " +
" FROM tickets t " +
" LEFT OUTER JOIN " +
"( " +
" SELECT ticket_addresses.ta_system_ref, ta_title, ta_othername, ta_surname, ta_house_number, ta_address_1, ta_address_2, " +
" ta_address_3, ta_address_4, ta_post_code, ta_telephone, ta_organisation " +
" FROM ticket_addresses " +
" INNER JOIN " +
" ( " +
" SELECT ticket_addresses.ta_system_ref, MAX(ta_address_code) AS ta_address_code " +
" FROM ticket_addresses " +
" GROUP BY ta_system_ref " +
" ) ad " +
" ON (ticket_addresses.ta_system_ref=ad.ta_system_ref AND ticket_addresses.ta_address_code=ad.ta_address_code) " +
")ta " +
"ON (t.t_number=ta.ta_system_ref) " +
" " +
" Inner JOIN " +
" ticket_hold_record b " +
" ON ( t.t_number = b.thr_system_ref) " +
" " +
"Inner JOIN " +
"Rpt_PCNBalance_ALLTickets bat " +
"ON (t.t_number = bat.t_number) " +
" " +
"Inner JOIN " +
"hold_reasons ch " +
"ON (b.thr_hold_type = ch.hr_code) " +
" " +
"Inner JOIN " +
" [VCS].[dbo].[Courtfees] cf " +
" ON (bat.Payments >= cf. [Min ClaimAmount]) and (bat.Payments <= cf.[Max Claim Amount]) " +
" " +
"Inner JOIN " +
" [VCS].[dbo].[sites] s " +
" ON (t.t_contract = s.Contract) " +
" " +
"Inner JOIN " +
" [VCS].[dbo].[claim info] cc " +
" ON (cc.Code COLLATE DATABASE_DEFAULT = t.t_offence_code COLLATE DATABASE_DEFAULT) " +
" and t.t_reference IN {where} ";
//Generate list of Ticket IDS for SQL Where Clause
string whereClause = "";
string[] tempArray = new string[this.txt.Lines.Length];
tempArray = this.txt.Lines;
if (this.txt.Lines.Length == 0)
{
return;
}
for (int counter = 0; counter <= tempArray.Length-1; counter++)
{
if (tempArray[counter].Trim().Length > 0)
{
whereClause = whereClause + "'" + tempArray[counter] + "'" + ", ";
}
}
whereClause = whereClause.TrimEnd(' ', ',');
whereClause = "(" + whereClause + ")";
stringSql = stringSql.Replace("{where}", whereClause);
myDataset = new DataSet("SQL");
SqlConnection myConn = new SqlConnection();
SqlCommand myCommand = new SqlCommand();
myCommand.CommandType = CommandType.Text;
myCommand.CommandText = stringSql;
myCommand.Connection = myConn;
SqlDataAdapter myAdapter = new SqlDataAdapter();
myAdapter.SelectCommand = myCommand;
myAdapter.Fill(myDataset);
this.dataGridView1.DataSource = myDataset.Tables[0];
for (int counter = 0; counter < myDataset.Tables[0].Columns.Count; counter++)
{
this.dataGridView1.Columns[counter].SortMode = DataGridViewColumnSortMode.NotSortable;
}
this.dataGridView1.Refresh();
myConn.Close(); this.btnGetData.Enabled = true;
this.btnSave.Enabled = true;
Application.DoEvents();
}
I would like to do an if statement within my query, but I'm not sure how. I want to perform:
join asoc2 in Personnels
on comp.Secondary_associate equals asoc2.Dpinitials
if there is a Second_Person data available. Any ideas how to do this? Let me know if there's an easier way. Here's my complete query:
(from sc in Data
join comp in Companies
on sc.Company equals comp.Company
join anl in Personnels
on sc.SalesP_initials equals anl.Dpinitials
join asoc1 in Personnels
on comp.First_associate equals asoc1.Dpinitials
join asoc2 in Personnels
on comp.Second_Person equals asoc2.Dpinitials
select new {
MyCompany = sc.Company,
ReleaseDate = sc.Release_date,
WebHeadline = sc.Short_subject,
EmailTo =
anl.Last_name + ", " + anl.First_name + " <" + anl.Email_address.Trim() + ">; "
+
asoc1.Last_name + ", " + asoc1.First_name + " <" + asoc1.Email_address.Trim() + ">; "
+
asoc2.Last_name + ", " + asoc2.First_name + " <" + asoc2.Email_address.Trim() + ">"
}).FirstOrDefault ()
Right now, it just displays null because *comp.Second_Person* doesn't exist.
You can use "where" in linq to filter your data