How to pass multiple parameters into a mysql stored procedure - mysql

I have a stored procedure that I am working on that is returning an invalid return when I try to pass parameters to it compared to when I run it with hard-coded values.
Procedure with hard coded values:
BEGIN
SELECT COUNT(DISTINCT ItemID)
FROM (
SELECT *
FROM sandbox_inventoryitempurchase
WHERE OrgID = '2781823'
AND PurchaseMonth>'2015-03-01'
) as DistinctCount;
END
When run, this returns: 16 which is correct.
Procedure with two input parameters:
BEGIN
SELECT COUNT(DISTINCT ItemID)
FROM (
SELECT *
FROM sandbox_inventoryitempurchase
WHERE OrgID = orgid
AND PurchaseMonth>sincedate
) as DistinctCount;
END
The input parameters are defined as:
IN userid integer,IN orgid integer,IN sincedate date
When run, this returns: 334 which is not correct.
I am new to stored procedures and would appreciate any assistance offered regarding what I am doing wrong and what I need to do to resolve?
Thanks...

add "#" before your parameters:
BEGIN
SELECT COUNT(DISTINCT ItemID)
FROM (
SELECT *
FROM sandbox_inventoryitempurchase
WHERE OrgID = #orgid
AND PurchaseMonth>#sincedate
) as DistinctCount;
END
a fast turtorial will be: Write-a-Stored-Procedure-in-SQL
(see how to use parameters at the end of this page...)

Try using input parameters that are not the same name as your columns.
Change:
BEGIN
SELECT COUNT(DISTINCT ItemID)
FROM (
SELECT *
FROM sandbox_inventoryitempurchase
WHERE OrgID = orgid
AND PurchaseMonth>sincedate
) as DistinctCount;
END
To:
BEGIN
SELECT COUNT(DISTINCT ItemID)
FROM (
SELECT *
FROM sandbox_inventoryitempurchase
WHERE OrgID = p_orgid
AND PurchaseMonth > p_sincedate
) as DistinctCount;
END
And pass IN p_orgid integer,IN p_sincedate date
The parser may be seeing WHERE OrgID = orgid and that evaluates to true for every record since it evaluates as an identity (comparing against itself).

Param Name and field name must be different!
BEGIN
SELECT COUNT(DISTINCT ItemID)
FROM (
SELECT *
FROM sandbox_inventoryitempurchase
WHERE OrgID = p_orgid
AND PurchaseMonth > p_sincedate
) as DistinctCount;
END

Related

How stored procedure output instead of rows count?

My stored procedure always returns 0. I tried unique data and duplicated but the insert is done with success but the return value is always the same #new_identity = 0
CREATE PROCEDURE [dbo].[spAddAuthor]
#Author tyAuthor READONLY,
#new_identity INT = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON;
-- check if the author exists
IF NOT EXISTS (SELECT Id_Author FROM dbo.Authors
WHERE (dbo.Authors.Username = (SELECT Username FROM #Author)
OR dbo.Authors.phone = (SELECT phone FROM #Author)
OR dbo.Authors.email = (SELECT email FROM #Author)))
BEGIN
INSERT INTO dbo.Authors (Username, sexe, email, phone, address)
SELECT [Username], [sexe], [email], [phone], [address]
FROM #Author
-- output the new row
SELECT #new_identity = ##IDENTITY;
END
ELSE
BEGIN
-- get the author Id if already exists
SELECT #new_identity = (SELECT TOP 1 Id_Author
FROM dbo.Authors
WHERE (dbo.Authors.Username = (SELECT Username FROM #Author)
OR dbo.Authors.phone = (SELECT phone FROM #Author)
OR dbo.Authors.email = (SELECT email FROM #Author)))
END
END
I found that in the declaration of the parameters I put null beside the output and that what caused the problem.
#new_identity INT = NULL OUTPUT
but I don't understand why, I thought the 'null' was like the default value, or when you try to make the parameter optional you add null as default value.
can someone explain, please?

MySQL Unknown column in 'order clause'

I have one procedure in my MySQL Database.
My procedure working fine. But currently I have to set order by tblUserKeyStatus.createdDate inside IF (opt=1) condition and when I set order by, It gives me the following error
Error Code: 1054. Unknown column 'tblUserKeyStatus.createdDate' in 'order clause
My Stored Procedure is given below
CREATE PROCEDURE proc_GetStatus(IN _userId varchar(64) , IN _qtr int, IN opt int)
BEGIN
IF (opt = 1) then
SELECT tblKeyStatus.*,'pending' AS `Status`,'' as scheduleDate,
' ' as doneDate,' ' as result FROM tblUserKeyStatus,tblKeyStatus WHERE tblKeyStatus.trimId not in
(SELECT trimId from tblUserKeyStatus WHERE userId=_userId)
union
SELECT tblKeyStatus.*,tblUserKeyStatus.`Status` AS `Status`,tblUserKeyStatus.scheduleDate,
tblUserKeyStatus.doneDate,tblUserKeyStatus.result FROM tblKeyStatus,tblUserKeyStatus WHERE
tblUserKeyStatus.trimId=tblKeyStatus.trimId and tblUserKeyStatus.userId=_userId
order by tblUserKeyStatus.createdDate;
Else
SELECT * from tblKeyStatus WHERE qtr=_qtr;
End if;
END
ORDER BY is applied to the whole query specified in the UNION operation, so that the entire result set returned by UNION is ordered.
Try to select createdDate field in both subqueries, so that it is accessible to ORDER BY:
SELECT tblUserKeyStatus.createdDate,
tblKeyStatus.*,'pending' AS `Status`,
'' as scheduleDate,
' ' as doneDate,
' ' as result
FROM tblUserKeyStatus, tblKeyStatus
WHERE tblKeyStatus.trimId not in (SELECT trimId
from tblUserKeyStatus
WHERE userId=_userId)
UNION
SELECT tblUserKeyStatus.createdDate,
tblKeyStatus.*,
tblUserKeyStatus.`Status` AS `Status`,
tblUserKeyStatus.scheduleDate,
tblUserKeyStatus.doneDate,tblUserKeyStatus.result
FROM tblKeyStatus,tblUserKeyStatus
WHERE tblUserKeyStatus.trimId=tblKeyStatus.trimId and
tblUserKeyStatus.userId=_userId
ORDER BY createdDate;
You also have to remove the tblUserKeyStatus name prefix.
Try having braces for select
CREATE PROCEDURE proc_GetStatus(IN _userId varchar(64) , IN _qtr int, IN opt int)
BEGIN
IF (opt = 1) then
SELECT tblKeyStatus.*,'pending' AS `Status`,'' as scheduleDate,
' ' as doneDate,' ' as result FROM tblUserKeyStatus,tblKeyStatus WHERE tblKeyStatus.trimId not in
((SELECT trimId from tblUserKeyStatus WHERE userId=_userId)
union
(SELECT tblKeyStatus.*,tblUserKeyStatus.`Status` AS `Status`,tblUserKeyStatus.scheduleDate,
tblUserKeyStatus.doneDate,tblUserKeyStatus.result FROM tblKeyStatus,tblUserKeyStatus WHERE
tblUserKeyStatus.trimId=tblKeyStatus.trimId and tblUserKeyStatus.userId=_userId
order by createdDate));
Else
SELECT * from tblKeyStatus WHERE qtr=_qtr;
End if;
END

Select inside function not working as expected

I have created a function to encapsulate a select on PL/SQL.
But the result I get from using the function is different that the one I get from using the select on it's own.
CREATE OR REPLACE FUNCTION fecha_ultimo_trasiego(fermentacion IN VARCHAR2)
RETURN DATE
IS fecha DATE;
BEGIN
SELECT (
SELECT fecha
FROM (
SELECT t.id, t.fecha
FROM TrasiegoAux t
WHERE t.fermentacion=fermentacion
ORDER BY t.fecha desc
)
WHERE ROWNUM=1
) INTO fecha FROM DUAL;
RETURN(fecha);
END;
Is there something wrong on the declaration of my function? Right now it always returns the same value no matter what parameter it gets as input.
The expected output is the date of the last Trasiego (the max date of the table).
This is my structure:
CREATE TABLE Fermentacion(
id VARCHAR2(36)
);
CREATE TABLE Trasiego(
id VARCHAR2(36),
fecha DATE not null,
fermentacion VARCHAR2(36) REFERENCES Fermentacion,
temperatura NUMBER(8) not null,
litrosFinal NUMBER(8) not null,
PRIMARY KEY(id, fermentacion)
);
create or replace view TrasiegoAux as select id, fecha, fermentacion from Trasiego;
Here is some data:
Insert into FERMENTACION (ID) values ('4');
Insert into FERMENTACION (ID) values ('9');
Insert into TRASIEGO (ID,FERMENTACION,TEMPERATURA,LITROSFINAL,FECHA) values ('1','4',20,190,to_date('04-OCT-16','DD-MON-RR'));
Insert into TRASIEGO (ID,FERMENTACION,TEMPERATURA,LITROSFINAL,EMPLEADOLABORATORIO,FECHA) values ('2','4',20,180,to_date('11-OCT-16','DD-MON-RR'));
Insert into TRASIEGO (ID,FERMENTACION,TEMPERATURA,LITROSFINAL,FECHA) values ('3','9',20,190,to_date('04-OCT-16','DD-MON-RR'));
Given that data I would expect that this:
DECLARE
fecha date;
BEGIN
fecha :=fecha_ultimo_trasiego(4);
DBMS_OUTPUT.PUT_LINE(fecha); //'11-OCT-16'
fecha :=fecha_ultimo_trasiego(4);
DBMS_OUTPUT.PUT_LINE(fecha); //'04-OCT-16'
END;
It's most likely to be because you're passing in the parameter with the same name as the column. That's not a good idea, as it causes all sorts of strangeness.
You can either amend the parameter name, e.g.:
CREATE OR REPLACE FUNCTION fecha_ultimo_trasiego(p_fermentacion IN VARCHAR2)
...
WHERE t.fermentacion = p_fermentacion
...
or you could qualify the parameter name in the query:
CREATE OR REPLACE FUNCTION fecha_ultimo_trasiego(fermentacion IN VARCHAR2)
...
WHERE t.fermentacion = fecha_ultimo_trasiego.fermentacion
...
You need to give the parameter a different name to any of the columns in TrasiegoAux, or else prefix it with the function name, e.g.
WHERE t.fermentacion = fecha_ultimo_trasiego.fermentacion
or else (after renaming the parameter):
WHERE t.fermentacion = p_fermentacion
Edit: Boneist beat me to it.
You could probably simplify the code a bit, though, as the select ... from dual wrapper doesn't seem to be needed:
create or replace function fecha_ultimo_trasiego
( p_fermentacion in trasiegoaux.fermentacion%type )
return date
as
l_fecha date;
begin
select fecha into l_fecha
from ( select t.fecha
from trasiegoaux t
where t.fermentacion = p_fermentacion
order by t.fecha desc )
where rownum = 1;
return l_fecha;
end;

must declare scalar variable for #User_Id and for Activity

While I am execution the following procedure I get these errors:
Must declare the scalar variable "#USer_Id".
Must declare the scalar variable "#Activity".
Can anybody help me how to fix these errors?
Here is the view creation is mandatory and the conditions are initially the view table data should be retrieved based upon the User_Id, given Timestamp rage i.e. start_time and end_time parameters and after getting the result, we have get the data based upon the Activity
The code which I wrote
create procedure Proc1
#User_Id varchar(50),
#start_time bigint,
#end_time bigint,
#view_name varchar(50),
#Activity varchar(30)
as
begin
exec('create view view_name
as
select
Asset_Id, Activity, User_Id, Event_Description, Timestamp
from
(SELECT
[j30c_editorial_id] AS Asset_Id,
[j30c_action] As Activity,
[j30c_description] As Event_Description,
[j30c_user_name] As User_Id,
[j30c_date] As Timestamp
FROM
[sandboxmbdb].[dbo].[j30t_changelog]
UNION ALL
SELECT
[Asset_Id],
[j30c_action],
[Event_Type_Desc],
[User_Id],
[Timestamp]
FROM
[refauditdatabase].[dbo].[AS_Event_Tracker_T] a,
[refauditdatabase].[dbo].[AS_Event_Type_M] b
WHERE
a.[Event_Type_Id] = b.[Event_Type_Id]) aa
where
User_Id = #User_Id
and Timestamp between #start_time and #end_time
and view_name = #view_name')
exec('select * from view_name where Activity = #Activity and view_name = #view_name')
end

Stored Procedure Can't drop temp table it don't exist

SQL Server 2008
This is a continuation of my last question. Now I'm trying to create a stored procedure, however I can't execute it. When I execute it, an error message displays
"Cannot drop the table #MyReport", because it does not exist or you do not have permissions.
Please guide me in the right direction.
Below is my stored Procedure
Create PROCEDURE [dbo].[SEL_MyReport]
(
#employeeid int,
#date1 datetime,
#date2 datetime
)
AS
BEGIN
drop table #MyReport
Create Table #MyReport
(
employeeid int,
name varchar(30),
department varchar(30),
checkTime datetime
)
if (#employeeid > 0)
Begin
INSERT INTO #MyReport (employeeid,name, department, checkTime)
select emp.EmpolyeeID, emp.Name,dep.DeptName,tm.checkTime
from TimeInOut tm
left join Employee emp on emp.EmpolyeeId = tm.EmployeeId
left join Department dep on dep.DeptID = emp.defaultDeptID
where (DATEDIFF(s,#date1,tm.checktime) >=0
and DATEDIFF(s,#date2,tm.checktime)<=0) and emp.employeeID = #employeeid
SELECT
employeeid
,name
,department
,[Time In] = MIN(checkTime)
,[Time Out] = MAX(checkTime)
FROM #MyReport
GROUP BY employeeid,name, department, CAST(checktime AS DATE)
End
Else
Begin
INSERT INTO #MyReport (employeeid,name, department, checkTime)
select emp.EmpolyeeID, emp.Name,dep.DeptName,tm.checkTime
from TimeInOut tm
left join Employee emp on emp.EmpolyeeId = tm.EmployeeId
left join Department dep on dep.DeptID = emp.defaultDeptID
where (DATEDIFF(s,#date1,tm.checktime) >=0
and DATEDIFF(s,#date2,tm.checktime)<=0)
SELECT
employeeid
,name
,department
,[Time In] = MIN(checkTime)
,[Time Out] = MAX(checkTime)
FROM #MyReport
GROUP BY employeeid,name, department, CAST(checktime AS DATE)
End
END
Go
exec SEL_MyReport('639','05/01/2014','05/08/2014')
There is quite a bit I would change - here is the code.
You will notice
branching logic (if #employeeid > 0) has been replaced by a slightly more verbose WHERE clause
no need for #tables as far as I can tell, the SELECT should suffice
Unfortunately, I do not have anything to test against, but you should understand the general impression of it.
Further, your date filtering seemed quite strange, so I assumed you may have meant something else - I could be mistaken. Either way, the way the date filtering is now done is SARGable
CREATE PROCEDURE [dbo].[SEL_MyReport]
(
#employeeid INT,
#date1 DATETIME,
#date2 DATETIME
)
AS
BEGIN
SET NOCOUNT ON;
SELECT emp.EmpolyeeID
,emp.Name
,dep.DeptName
,[Time In] = MIN(tm.checkTime)
,[Time Out] = MAX(tm.checkTime)
FROM TimeInOut tm
LEFT
JOIN Employee emp on emp.EmpolyeeId = tm.EmployeeId
LEFT
JOIN Department dep on dep.DeptID = emp.defaultDeptID
WHERE tm.checktime >= #date1
AND tm.checktime <= #date2
/***********************************************************************************************************
* I've assumed what you may be trying to express, above
* You might also want to look at the BETWEEN() operator, remembering that it is inclusive in its behaviour
* (DATEDIFF(s,#date1,tm.checktime) >=0
* AND DATEDIFF(s,#date2,tm.checktime)<=0)
***********************************************************************************************************/
AND (emp.employeeID = #employeeid OR #employeeid <= 0)
GROUP BY emp.EmpolyeeID, emp.name, dep.department, CAST(tm.checktime AS DATE)
END
GO
Well, since the very first step of your Stored Procedure attempts to drop a table, this will obviously result in an error if that table does not exist.
To work around this, make sure you check whether the table exists, before you drop it:
IF OBJECT_ID('tempdb..#MyReport') IS NOT NULL DROP
TABLE #MyReport