Stored procedure wrong output - sql

I have this stored procedure that returns data on a selected week, as in the Company, Name, Expected Work, and Work done between the 19/10/2015 and the 25/10/2015 (per example).
I have just recently added the Expected Work line and for some odd reason the output differs from one week to another, when the value should be the same.
Company1 - Christopher - 35 - 35 | On one week can give the following on another :
Company1 - Christopher - 350 - 35
I have just realized the value isn't correct when there is a value to Work done, if there is no work recorded the Expected Work has the right value.
Here is the procedure :
ALTER procedure [dbo].[spGetWeeklyActivityByEmployee]
#startDate date
, #endDate date
as
set datefirst 1 -- Monday
select
Company.Name as [Company]
, Employee.FirstName + ' ' + Employee.LastName as [Name]
, sum(UserActivity.Cost) as [Recorder Time]
, sum(Employee.ExpectedTime) as [Expected Time] // I have added this line, not sure if it's correct
from
dbo.Employee
inner join
dbo.Company on Company.CompanyId = Employee.CompanyId
left join
dbo.UserActivity on UserActivity.Login = Employee.Login
and UserActivity.CalendarDate >= #startDate
and UserActivity.CalendarDate <= #endDate
where
(Employee.EntranceDate is null
or YEAR(Employee.EntranceDate) < YEAR(#startDate)
or (YEAR(Employee.EntranceDate) = YEAR(#startDate)
and DATEPART(WEEK, Employee.EntranceDate) <= DATEPART(WEEK, #startDate)))
and (Employee.ExitDate is null
or YEAR(Employee.ExitDate) > YEAR(#endDate)
or (YEAR(Employee.ExitDate) = YEAR(#endDate)
and DATEPART(WEEK, Employee.ExitDate) >= DATEPART(WEEK, #endDate)))
group by
Company.Name, Employee.FirstName + ' ' + Employee.LastName
return 0
Am I missing something? Is the way I retrieve Expected Time wrong?
EDIT :
Here is the part in the code where I save the information in an array :
// create and open a connection object
SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
conn.Open();
// 1. create a command object identifying
// the stored procedure
SqlCommand cmd = new SqlCommand("spGetWeeklyActivityByEmployee", 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("#startDate", wk1));
cmd.Parameters.Add(new SqlParameter("#endDate", wk2));
// execute the command
rdr = cmd.ExecuteReader();
string[] tab_company = new string[31]; // Don't mind the sizes
string[] tab_name = new string[31];
string[] tab_expectedtime = new string[31];
string[] tab_rectime = new string[31];
int counter;
counter = 0;
while (rdr.Read())
{
tab_company[counter] = rdr["Company"].ToString();
tab_name[counter] = rdr["Name"].ToString();
tab_expectedtime[counter] = rdr["Expected Time"].ToString();
tab_rectime[counter] = rdr["Recorder Time"].ToString();
counter++;
}
Perhaps the change in value comes from here?

Just take away the SUM() from Employee.ExpectedTime and add this to your GROUP BY

Related

Is there a way to set a parameter from a stored procedure to a var query?

I'm working in a .net app specifically in a validation scripted in a stored procedure. This simple validation checks if there is already a policy with the same policy number that the user is trying to insert and throws an error message.
The problem that I'm facing is of the kind
Procedure or function 'pr_Policy_CheckPolicyNumber' expects parameter '#companyID', which was not supplied.
That's because I added a new field from the same PolicyBill table named (CompanyID).
My question is if it's there a way to set the #CompanyID value directly to the function and fix that error
The stored procedure is
CREATE OR ALTER PROCEDURE [dbo].[pr_Policy_CheckPolicyNumber]
(
#policyNumber VARCHAR(50) ,
#effectiveOn DATETIME ,
#companyID BIGINT
)
AS
IF ( ( SELECT COUNT(pb.policyBillID)
FROM PolicyBill pb
WHERE pb.policyNumber = #policyNumber
AND ( #effectiveOn >= pb.effectiveOn ) and (#effectiveOn <= pb.expiresOn )
AND pb.isActive = 1
AND pb.statusID = 56
AND pb.documentTypeID = 1
AND pb.companyID = #companyID
) > 0 )
BEGIN
PRINT N'The Policy already exists';
SELECT 1
END
ELSE
BEGIN
SELECT 0
END
and the Function is:
private bool CheckPolicyNumber()
{
var result = true;
var query = $"EXEC pr_Policy_CheckPolicyNumber '{txtPolicyNumber.Text}','{deEffectiveON.Date:yyyy/MM/dd}', '#companyID'";
var dt = AhkSqlHelper.ahkExecuteDataTable(query);
result = Convert.ToBoolean(Convert.ToInt16(dt.Rows[0][0].ToString()));
return result;
}
Any help would be appreciated.
Ad mentioned in the comment, the original code is fairly dangerous and you could be open to SQL injection attacks. The best solution is parameterize your command, something like this should do the trick:
using System.Data.SqlClient;
using System.Data;
string connString = "YourConnectionString";
string spName = "pr_Policy_CheckPolicyNumber";
private bool CheckPolicyNumber(string policyNumber, DateTime effectiveOn, long companyID)
{
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(spName, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter parameter1 = new SqlParameter("#policyNumber ", policyNumber);
cmd.Parameters.Add(parameter1);
SqlParameter parameter2 = new SqlParameter("#effectiveOn ", effectiveOn);
cmd.Parameters.Add(parameter2);
SqlParameter parameter3 = new SqlParameter("#companyID ", companyID);
cmd.Parameters.Add(parameter3);
var result = cmd.ExecuteScalar()
return (bool)result;
}
}
}

SQL statement where clause by two dates

I am trying to write a Sql statement which filter the records based on two date variables entered by users. Here is my Sql statement:
public List<DistributionPacking> filterByDeliveryDate()
{
List<DistributionPacking> dateList = new List<DistributionPacking>();
using (var connection = new SqlConnection(FoodBankDB.connectionString)) // get your connection string from the other class here
{
SqlCommand command = new SqlCommand("SELECT d.id, d.packingDate, d.deliveryDate, b.name FROM dbo.Distributions d " +
"INNER JOIN dbo.Beneficiaries b ON d.beneficiary = b.id WHERE d.deliveryDate BETWEEN #fromDate AND #toDate", connection);
command.Parameters.AddWithValue("#fromDate", startDate);
command.Parameters.AddWithValue("#toDate", endDate);
connection.Open();
using (var dr = command.ExecuteReader())
{
while (dr.Read())
{
string id = dr["id"].ToString();
DateTime packingDate = DateTime.Parse(dr["packingDate"].ToString());
DateTime deliveryDate = DateTime.Parse(dr["deliveryDate"].ToString());
string name = dr["name"].ToString();
dateList.Add(new DistributionPacking(id, packingDate, deliveryDate, name));
}
}
}
However, it told me that Conversion failed when converting date and/or time from character string although my data type for packingDate and deliveryDate is DateTime. I wonder why is it so.
Thanks in advance.
Try something like this ...
SELECT d.id, d.packingDate, d.deliveryDate, b.name
FROM dbo.Distributions d INNER JOIN dbo.Beneficiaries b
ON d.beneficiary = b.id
WHERE d.deliveryDate
BETWEEN CAST(#fromDate AS DATETIME) AND CAST(#toDate AS DATETIME)

Get the value from Output parameter C#

hi i'm try to create sp in sql with output value
this is the code
ALTER PROCEDURE [dbo].[usp_SelectHospital_IfExiste_Department]
#HospitalDepartmentID INT,
#IfExiste INT OUTPUT
AS
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
IF NOT EXISTS (SELECT c.DeptID FROM Clinic c WHERE DeptID=#HospitalDepartmentID )
BEGIN
SET #IfExiste=0
SELECT
[HospitalDepartmentID],
[NAME]
FROM
[dbo].[Hospital_Department]
WHERE
[HospitalDepartmentID] = #HospitalDepartmentID
END
ELSE
BEGIN
SET #IfExiste=1
SELECT
[HospitalDepartmentID],
[NAME]
FROM
[dbo].[Hospital_Department]
WHERE
[HospitalDepartmentID] = #HospitalDepartmentID
END
and the C# code
public static Hospital_Department GetDepartmentInfo(int ID,int OutIfExist)
{
SqlCommand cmd;
SqlDataReader dr;
Hospital_Department HD = new Hospital_Department();
using (cmd = new SqlCommand("usp_SelectHospital_IfExiste_Department", ProjectCon.GetCon()))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#HospitalDepartmentID", ID);
//cmd.Parameters.Add("#IfExiste",SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Parameters.Add("#IfExiste",SqlDbType.Int);
cmd.Parameters["#IfExiste"].Direction = ParameterDirection.Output;
dr = cmd.ExecuteReader();
while (dr.Read())
{
HD.NAME = dr["NAME"].ToString();
HD.HospitalDepartmentID = Convert.ToInt32(dr["HospitalDepartmentID"]);
}
OutIfExist = Convert.ToInt32(cmd.Parameters["#IfExiste"].Value);
return HD;
}
}
when i try to get the output value is always null
and i run the stored procedure in sql Was run and return the value
so plz tell me what's wrong in my code
thx
Maybe this question has useful info:
According to, http://msdn.microsoft.com/en-us/library/ms971497, you must close the datareader before you process the output parameters.
Hope it helps.

How to get flat record set back from stored procedure in Dapper.Net

I've got a project running on SQL Server 2005. I have a stored procedure that accepts some input parameters, has 2 output parameters and also returns a result set from a select statement inside.
The data is not intending to be returned back as objects just a simple dto class 'Foo' which does not have a primary key.
I've tried to use Dapper.Net with the below code, but I get as far as the exception error returned
When using the multi-mapping APIs ensure you set the splitOn param if you have keys other than Id
Code:
var p = new DynamicParameters();
p.Add("#Code", code);
p.Add("#MessageControlId", getMessageControlId);
p.Add("#SuccessCode", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("#ErrorDescription", dbType: DbType.String, direction: ParameterDirection.Output, size: 255);
var result = this.db.Query(sql: "up_MessageProcessed_get", param: p, commandType: CommandType.StoredProcedure);
Should I be able to do this with Dapper.Net? Should I calling something else to get a simple resultset back?
As requested, here is a shell of the procedure,
it will set the returnvalues and also return 1 resultset.
CREATE PROCEDURE [dbo].[up_MessageProcessed_get]
#Code varchar(10),
#MessageControlID varchar(22),
#SuccessCode int OUTPUT,
#ErrorDescription varchar(255) OUTPUT
AS
BEGIN
Select 2 as MessageProcessID, 38349348 as StartNum, 3874900 as EndNum, GETDATE() as StartDate, GETDATE() as EndDate
SET #SuccessCode = 0
SET #ErrorDescription = 'Completed successfully'
END
This isn't so much an "answer" as a "needs more context", but: with the code as posted, it works fine (below). I suspect the issue here is specific to something inside the stored procedure - something peculiar it is doing:
public void TestIssue17648290()
{
var p = new DynamicParameters();
int code = 1, getMessageControlId = 2;
p.Add("#Code", code);
p.Add("#MessageControlId", getMessageControlId);
p.Add("#SuccessCode", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("#ErrorDescription", dbType: DbType.String, direction: ParameterDirection.Output, size: 255);
connection.Execute(#"CREATE PROCEDURE #up_MessageProcessed_get
#Code varchar(10),
#MessageControlID varchar(22),
#SuccessCode int OUTPUT,
#ErrorDescription varchar(255) OUTPUT
AS
BEGIN
Select 2 as MessageProcessID, 38349348 as StartNum, 3874900 as EndNum, GETDATE() as StartDate, GETDATE() as EndDate
SET #SuccessCode = 0
SET #ErrorDescription = 'Completed successfully'
END");
var result = connection.Query(sql: "#up_MessageProcessed_get", param: p, commandType: CommandType.StoredProcedure);
var row = result.Single();
((int)row.MessageProcessID).IsEqualTo(2);
((int)row.StartNum).IsEqualTo(38349348);
((int)row.EndNum).IsEqualTo(3874900);
DateTime startDate = row.StartDate, endDate = row.EndDate;
p.Get<int>("SuccessCode").IsEqualTo(0);
p.Get<string>("ErrorDescription").IsEqualTo("Completed successfully");
}
which outputs:
Running TestIssue17648290 - OK!
(which is to say: that works fine)

How Do I get value from sql search based on the start and end dates?

I have a Personnel Roles Table where employees are assigned daily roles or roles with specific start and end dates.
Managers have asked for a sort of manpower plan table which lists an employee’s daily role and this how I generate the table
private string CreateHTMLTable(Int32 month)
{
StringBuilder strBuilder = new StringBuilder();
System.Data.DataTable dtAllStaff = new System.Data.DataTable();
//get all staff
PersonelApplication.Classes.PersonelClass PersonnelClass = new PersonelClass();
dtAllStaff = PersonnelClass.GetAllPersonel();
//create manpower data table
System.Data.DataTable dtManPowerDataTable = new System.Data.DataTable();
//create montlhy dt
//get number of days in month
int daysInMonth = DateTime.DaysInMonth(DateTime.Now.Year, month);
//get first day in month
DateTime firstDayInMonth = new DateTime(DateTime.Now.Year, month, 1);
//get last day in month
DateTime lastDayInMonth = new DateTime();
lastDayInMonth = firstDayInMonth.AddMonths(1).AddDays(-1);
//start table
strBuilder.Append("<table>");
//create header based on number of days in the month
//append tr strat
strBuilder.Append("<tr>");
//add name header for personnle
strBuilder.Append("<th>");
strBuilder.Append("Staff");
strBuilder.Append("</th>");
for (int i = 1; i <= lastDayInMonth.Day; i++)
{
strBuilder.Append("<th>");
strBuilder.Append(i.ToString() + "/" + month.ToString());
strBuilder.Append("</th>");
}
//append tr end to header row
strBuilder.Append("</tr>");
System.Data.SqlClient.SqlConnection sqlConn = new System.Data.SqlClient.SqlConnection();
sqlConn.ConnectionString = ConnectionClass.CreateConnection.getConnectionString();
using (sqlConn = ConnectionClass.CreateConnection.publicGetConn())
{
sqlConn.ConnectionString = ConnectionClass.CreateConnection.getConnectionString();
try
{
sqlConn.Open();
if (sqlConn.State == ConnectionState.Open)
{
foreach (DataRow row in dtAllStaff.Rows)
{
string personnelName = "";
string personnelCode = "";
Int32 personnelID = 0; ;
personnelCode = row[1].ToString();
strBuilder.Append("<tr>");
strBuilder.Append("<td>");
strBuilder.Append(personnelCode);
strBuilder.Append("</td>");
for (int i = 1; i <= lastDayInMonth.Day; i++)
{
//here get the each employee's planned role as well
//as actual role
}
strBuilder.Append("</tr>");
}
}
}
catch (Exception ex)
{
//pouplate later
}
finally
{
}
}
//end table
strBuilder.Append("</table>");
return strBuilder.ToString();
}
My issue is the SQL function which will return the employees role for a particular day.
--actual end date for this role is '08-18-2012'
declare #sdate date
set #sdate= '08-14-2012'
SELECT
CONVERT(date,startdate,101)
,CONVERT(date,EndDate,101)
,StartDate
,EndDate
,fk_PersonelID
,fk_RoleID
FROM [dbo].JobRolesTable
where #sdate between StartDate and EndDate
and fk_PersonelID = 40
But If I do a search for the next day which is the '08-15-2012’,I get nada
Bascially I want to return an employee’s role on any day of the month and ‘na’ if there’s none
I don’t want to use a cursor for this but is there another way I can achieve this
DECLARE #sdate DATE = '20120814';
SELECT
CONVERT(DATE,StartDate,101) -- what is the purpose of 101 here?
,CONVERT(DATE,EndDate,101) -- what is the purpose of 101 here?
,StartDate
,EndDate
,fk_PersonelID
,fk_RoleID
FROM [dbo].JobRolesTable
WHERE #sdate >= StartDate
AND #sdate < DATEADD(DAY, 1, EndDate)
AND fk_PersonelID = 40;
You are probably populating your parameters incorrectly.
If your query is of the form
SELECT *
FROM Table
WHERE (#SearchDate BETWEEN #StartDate AND #EndDate) AND Id=#Id
(which yours appears to be), then it will return the correct values from the db as long as the dates are being specified correctly.
Can you show the code where you're actually attempting to use the SqlConnection that you're opening in the posted code?