#1320 - No RETURN found in FUNCTION MYSQL - mysql

I'm try create a function in mysql but
the error is: #1320 - No RETURN found in FUNCTION
Thanks for the help
DELIMITER $$
CREATE FUNCTION `bascar20_GPCSAS`.`getPrice`(codRef integer(11), ultimoInventario varchar(50), fechaInicial varchar(50), fechaFinal varchar(50))
RETURNS INT(11)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
-- SET #codRef := 105;
-- SET #ultimoInventario := "2016-10-31";
-- SET #fechaInicial := '2016-11-01';
-- SET #fechaFinal := '2016-11-30';
SET #S := (SELECT IF(COUNT(*)=0,0,Saldo) FROM inventarios_finales WHERE FK_codigo_referencia = #codRef and fecha_inventario = #ultimoInventario AND FK_bodega = 1001);
SET #VU := (SELECT IF(COUNT(*)=0,0,valorUnitario) FROM inventarios_finales WHERE FK_codigo_referencia = #codRef and fecha_inventario = #ultimoInventario AND FK_bodega = 1001);
SET #VT := #S * #VU;
BEGIN
DECLARE returnVal INT(11);
SELECT ROUND(T.precio,0) INTO returnVal
FROM (
SELECT Fecha, referecia, Tipo, Cantidad, PrecioUnitario, IF(Tipo='EA'||Tipo='EM',(#S:=#S+Cantidad),(#S:=#S-Cantidad)) as SALDO ,IF(Tipo='EA'||Tipo='EM',(#VT:=#VT+(Cantidad*PrecioUnitario)),#VT:=#VT-(Cantidad*#VU)) as valortotal,IF(Tipo='EA'||Tipo='EM',#VU:=#VT/#S,#VU) as precio
FROM documentos
WHERE PrecioUnitario != 0 and Cantidad != 0 and Fecha BETWEEN #fechaInicial and #fechaFinal and NombreArticulo = #codRef and (Tipo = 'RM' or Tipo = 'EA' or Tipo = 'EM')
ORDER BY Fecha
) T
ORDER BY T.Fecha DESC
LIMIT 1
RETURN returnVal;
END$$
the error is:
1320 - No RETURN found in FUNCTION
Thanks for the help

That's cause you are missing a ; before the RETURN statement as pointed below from your posted code.
.....<rest of code>.....
ORDER BY Fecha
) T
ORDER BY T.Fecha DESC
LIMIT 1 <----------- Here
RETURN returnVal;

Related

Visual Studio 2010 Reporting Services - how to populate something when nothing is returned

I'm using a query with two parameters (#campaign,#resultcode) to populate a table with 3 columns ("Campaignname","Disposition","Count"), but when either one of those parameters don't exist in the database, nothing populates in the table. Is there a way to make it populate the two parameters with a count of 0? Also I have it set so that multiple parameters can be selected. I've tried IIF(IsNothing()..., IIF(***.value = null or ""). Still doesn't do what I want it to do. Some help?
Included code from comment response:
SELECT databasename, callresultdescription, count(*) as Count
FROM bpsql00.[histCallCenterStats].[dbo].[CallResults]
WHERE databasename IN(#campaign) AND callresultcode IN(#resultcode)
GROUP BY databasename, callresultdescription
The callresultdescription is AKA disposition
You could union them together:
--create table [CallResults] (databasename varchar(10),callresultdescription
varchar(10),myvalue int)
--insert into [CallResults]
--values ('a','AA',1),
--('b','BB',2),
--('c','CC',3)
--select * from [CallResults]
declare #campaign varchar(10)='d',#resultcode varchar(10)='dd' ;
SELECT databasename, callresultdescription,
count(1) as [Count]
FROM [CallResults]
WHERE databasename IN (#campaign)
AND callresultdescription IN (#resultcode)
GROUP BY databasename, callresultdescription
UNION
SELECT databasename=#campaign,
callresultdescription=#resultcode,
0 as [Count]
from [CallResults]
where databasename not IN (#campaign)
AND callresultdescription not IN (#resultcode)
You can accomplish this with an IF statement in the SQL query:
IF EXISTS (SELECT 1 FROM bpsql00.[histCallCenterStats].[dbo].[CallResults] WHERE databasename IN ( #campaign ) AND callresultcode IN ( #resultcode ))
SELECT databasename
, callresultdescription
, [Count] = COUNT(*)
FROM bpsql00.[histCallCenterStats].[dbo].[CallResults]
WHERE databasename IN ( #campaign )
AND callresultcode IN ( #resultcode )
GROUP BY databasename ,
callresultdescription;
ELSE
SELECT databasename = #campaign
, callresultdescription = #resultcode
, [Count] = 0
Edit per question in the comment:
It gets tricky when you need to return a multi-valued parameter. If you're on SQL 2016, you can use the new TSQL STRING_SPLIT function to split out their comma-separated selections. There are also splitter functions you can find on the interwebs for prior versions of SQL. The simplest solution, though, is to let the query return nothing and set the NoRowsMessage of the tablix to inform the client. You can use an expression like
="No records found in the selected campaigns (" & _
Parameters!campaign.Value & ") and result codes (" & _
Parameters!resultcode.Value & ")."
That gives the user a record of what was searched and that nothing was found to match their criteria.
So finally figured it out. I have concluded that the program is limited what I wanted to do. So... why not let SQL do it for me and I can just call a stored procedure. BINGO. I had to create a function as well. So for anyone who needs something like this.
Stored procedure I created:
alter procedure [dbo].[rs_Query]
#campaign varchar (100),
#resultcode varchar (100)
as
Begin
declare #var_campaign varchar(100)
declare #var_resultcode varchar(100)
declare #c table(ID int identity, databasename varchar(100))
declare #r table(ID int identity, callresultcode varchar(100))
insert into #c select element from dbo.func_split(#campaign, ',')
insert into #r select element from dbo.func_split(#resultcode,',')
declare #dbcnt int --count of campaigns selected
declare #crcnt int --count of dispositions selected
declare #crrow int --row id for campaigns selected
declare #dbrow int --row id for dispositions selected
declare #tempdbname varchar(50) --temp campaign name
declare #tempcr varchar(50) --temp call result name
declare #t table (databasename varchar(100), callresultdescription varchar (100), Count int)
declare #count int
select #dbcnt = count(*) from #c
select #crcnt = count(*) from #r
select #dbrow = 1
select #crrow = 1
while #dbcnt >= #dbrow
begin
set #tempdbname = (select databasename
from bpsql00.callcenteraux.dbo.DailyReportsCampaign
where databasename = (select databasename from #c where id = #dbrow))
set #crrow = 1
while #crcnt >= #crrow
begin
set #tempcr = (select CallResultDescription
from CallResultCode
where CallResultCode = (select CallResultCode from #r where id = #crrow));
if exists(select 1 from bpsql00.[histCallCenterStats].[dbo].[CallResults]
where CallResultCode = (select CallResultCode from #r where id = #crrow) and databasename = #tempdbname)
begin
select #count = count(*) from bpsql00.[histCallCenterStats].[dbo].[CallResults]
where CallResultCode = (select CallResultCode from #r where id = #crrow) and databasename = #tempdbname
insert into #t values(#tempdbname,#tempcr,#count)
end
else
begin
insert into #t values(#tempdbname,#tempcr,0)
end
set #crrow = #crrow + 1
end
set #dbrow = #dbrow + 1
end
select * from #t
end
And function I created:
ALTER FUNCTION [dbo].[func_Split]
(
#DelimitedString varchar(8000),
#Delimiter varchar(100)
)
RETURNS #tblArray TABLE
(
ElementID int IDENTITY(1,1), -- Array index
Element varchar(1000) -- Array element contents
)
AS
BEGIN
-- Local Variable Declarations
-- ---------------------------
DECLARE #Index smallint,
#Start smallint,
#DelSize smallint
SET #DelSize = LEN(#Delimiter + 'x') - 1
-- Loop through source string and add elements to destination table array
-- ----------------------------------------------------------------------
WHILE LEN(#DelimitedString) > 0
BEGIN
SET #Index = CHARINDEX(#Delimiter, #DelimitedString)
IF #Index = 0
BEGIN
INSERT INTO
#tblArray
(Element)
VALUES
(LTRIM(RTRIM(#DelimitedString)))
BREAK
END
ELSE
BEGIN
INSERT INTO
#tblArray
(Element)
VALUES
(LTRIM(RTRIM(SUBSTRING(#DelimitedString, 1,#Index - 1))))
SET #Start = #Index + #DelSize
SET #DelimitedString = SUBSTRING(#DelimitedString, #Start , LEN(#DelimitedString) - #Start + 1)
END
END
RETURN
END

how to declare variables in trigger with mysql?

CREATE OR REPLACE TRIGGER ATTENDANCE_NOTIFY AFTER INSERT OR UPDATE ON ATTENDANCE
FOR EACH ROW
DECLARE
V_STUDENT_ID STUDENT.STUDENT_ID%TYPE := NULL;
V_HOD_ID HEAD_OF_DEPARTMENT.HOD_ID%TYPE := NULL;
V_SUBCODE STUDENT.SUBCODE%TYPE := NULL;
V_ATTENDANCE ATTENDENCE%TYPE := NULL;
BEGIN
SELECT SUB_CODE, SUB_NAME INTO V_SUB_CODE, FROM SUBJECT WHERE STUDENT_ID = :NEW.STUDENT_ID;
SELECT STUDENT_ID INTO V_STUDENT_ID FROM STUDENT WHERE SUBJECT_CODE = :NEW.SUBJECT_CODE;
SELECT HOD_ID INTO V_HOD_ID FROM STUDENT_HOD WHERE STUDENT_ID = :NEW.STUDENT_ID;
SELECT ATTENDENCE INTO V_ATTENDENCE FROM ATTENDENCE WHERE STUDENT_ID=:NEW_STUDENT_ID
IF (V_ATTENDENCE IS NOT NULL AND V_SUB_CODE IS NOT NULL AND V_STUDENT_ID IS NOT NULL AND V_HOD_ID IS NOT NULL) THEN
IF (:NEW.ATTENDENCE < (V_ATTENDENCE * 0.85)) THEN
INSERT INTO NOTIFY VALUES(V_HOD_ID, V_STUDENT_ID || ' (ID:- ' || :NEW.STUDENT_ID ||') HAS LESS THAN 85% ATTENDENCE IN SUBJECT ' || V_SUB_CODE);
END IF;
END IF;
EXCEPTION
WHEN OTHERS
THEN NULL;
END;
i am getting a syntax error in declare
There is no way to refer datatype of column in MySQL. DECLARE must statically declare a variable's type and size.
Something like
DECLARE myvar VARCHAR( 8 ) -- This is valid in Mysql
Not
DECLARE myvar mytable.myfield%TYPE --This is invalid in Mysql
Hope this helps.

Mysql : Not allowed to return a result set from a function

I have write one function but getting this error Not allowed to return a result set from a function
DELIMITER $$
CREATE FUNCTION getTestFunction
(
p_ParentID int,
p_ListName nvarchar(50),
p_Type nvarchar(50),
p_Count int
)
RETURNS nvarchar(2000)
BEGIN
DECLARE p_KeyValue nvarchar(2000);
DECLARE p_ListValue nvarchar(2000);
DECLARE p_TextValue nvarchar(2000);
DECLARE p_ReturnValue nvarchar(2000);
DECLARE p_Key nvarchar(2000);
IF p_ParentID = 0 THEN
IF p_Count = 0 THEN
SET p_ReturnValue = '';
ELSE
SET p_ReturnValue = p_ListName;
END IF;
ELSE
SELECT p_KeyValue = ListName + '.' + Value
FROM ListsTable
WHERE EntryID = p_ParentID LIMIT 1 ;
RETURN p_ReturnValue;
If p_Type = 'ParentKey' Or (p_Type = 'ParentList' AND p_Count > 0) THEN
SET p_ReturnValue = p_KeyValue;
ELSE
IF p_Type = 'ParentList' THEN
SET p_ReturnValue = p_ListValue;
ELSE
SET p_ReturnValue = p_TextValue;
END IF;
END IF;
IF p_Count > 0 THEN
If p_Count = 1 AND p_Type = 'ParentList' THEN
SET p_ReturnValue = p_ReturnValue + ':' + p_ListName;
ELSE
SET p_ReturnValue = p_ReturnValue + '.' + p_ListName;
END IF;
END IF;
END IF;
RETURN p_ReturnValue;
END$$
DELIMITER ;
You want to assign the result of a query to a variable, but in fact you're just selecting. That's why MySQL's complaining.
You have to change this
SELECT p_KeyValue = ListName + '.' + Value
FROM ListsTable
WHERE EntryID = p_ParentID LIMIT 1 ;
to
SELECT CONCAT(ListName, '.', `Value`)
INTO p_KeyValue
FROM ListsTable
WHERE EntryID = p_ParentID LIMIT 1 ;
And you should add an ORDER BY. A LIMIT without ORDER BY doesn't make sense, since there's no guaranteed order in a relational database.
Mysql complains about SELECT statement in your function,
probably it understands SELECT p_KeyValue = ListName + '.' + Value as comparison
change it to
SELECT CONCAT(ListName, '.', Value) INTO p_KeyValue

mysql stored procedure error (1172, 'Result consisted of more than one row')

When trying to run the following stored procedure from django, I get an OperationError (1172, 'Result consisted of more than one row') Any idea what I might be doing wrong?
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `UpdatePrices`(IN storeId int, IN bottleSize VARCHAR(50))
BEGIN
DECLARE amount DECIMAL(10,2); DECLARE isCustom INT DEFAULT 0;
DECLARE changeType VARCHAR(50) DEFAULT 'State'; DECLARE updateType INT DEFAULT 0;
IF bottleSize = '1000 Ml' THEN
SELECT S1000IncreaseChoices INTO changeType FROM store_store WHERE StoreID = storeId;
IF changeType = 'State' THEN
SELECT updateType = 0;
END IF;
IF changeType = 'Flat' THEN
SELECT S1000IncreaseAmount INTO amount FROM store_store WHERE StoreID = storeId;
SELECT updateType = 1;
END IF;
IF changeType = 'Percent' THEN
SELECT 1 - S1000IncreaseAmount/100 INTO amount FROM store_store WHERE StoreID = storeId;
SELECT updateType = 2;
END IF;
END IF;
IF updateType = 0 THEN
update store_storeliquor SL
inner join liquor_liquor LL
on liquorID_id = id
set StorePrice = ShelfPrice
where BottleSize = bottleSize
and storeID_id = storeId
and custom = 0;
END IF;
IF updateType = 1 THEN
update store_storeliquor SL
inner join liquor_liquor LL
on liquorID_id = id
set StorePrice = OffPremisePrice + amount
where BottleSize = bottleSize
and storeID_id = storeId
and custom = 0;
END IF;
IF updateType = 1 THEN
update store_storeliquor SL
inner join liquor_liquor LL
on liquorID_id = id
set StorePrice = OffPremisePrice / amount
where BottleSize = bottleSize
and storeID_id = storeId
and custom = 0;
END IF;
END
I'm not sure if it matters, but I initiate the stored procedure like so:
def priceupdate(request, store_id):
cursor = connection.cursor()
cursor.callproc("UpdatePrices", (store_id, '1000 ML'))
cursor.close()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
Your SELECT...INTO queries give result sets with more then one record. The WHERE filters are incorrect - they compare two the same values StoreID = storeId. Rename IN storeId int parementer to another name. For example - IN storeId_param int
The query will be like this -
SELECT S1000IncreaseChoices INTO changeType FROM store_store WHERE StoreID = storeId_param;
This is a Bug and you need to apply something like that:
SELECT id,data INTO x,y FROM test.t1 LIMIT 1;

MsSQL to MySQL function conversion

So I am trying to convert a function I created in MSSQL to MYSQL. The way I have it written in MSSQL is:
ALTER function FormatDate(#date datetime) returns varchar(10)
begin
declare #salida varchar(10)
if (#date != '') and (#date != '01/01/1900')
begin
declare #day varchar(2)
set #day = cast(day(#date) as varchar)
if len(#day) = 1
set #day = '0' + #day
declare #month varchar(2)
set #month = cast(month(#date) as varchar)
if len(#month) = 1
set #month = '0' + #month
select #salida = #month + '/' + #day + '/' + cast(year(#date) as varchar)
end
else
set #salida = null
return #salida
end
I am trying to convert that function into a MYSQL function. I tried this:
Delimiter $$
create function FormatDate(tiempo datetime)
RETURNS varchar(10)
READS SQL DATA
BEGIN
declare salida varchar(10);
if ((tiempo != '') and (tiempo != '01/01/1900')) then
BEGIN
declare dia varchar(2);
set dia = cast(day(tiempo) as varchar);
if len(dia) = 1 then
set dia = '0' + dia;
END IF;
declare mes varchar(2);
set mes = cast(month(tiempo) as varchar);
if len(mes) = 1 then
set mes = '0' + mes;
END IF;
select salida = mes + '/' + dia + '/' + cast(year(tiempo) as varchar);
else
set salida = null;
END; End if;
return (salida);
END $$
Delimiter ;
but I get an error when I try to execute that code.
This is the error I am getting:
Error Code: 1064. You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'varchar);
if len(dia) = 1 then
' at line 14
Can someone please help me convert this MSSQL function into a MYSQL function?
The function to determine a strings lenght in MySQL is called LENGTH(), not len()
http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_length
MORE:
I added a working version of your function below. But please note that the built-in function DATE_FORMAT() does exactly what you want:
mysql> SELECT FormatDate( NOW() ), DATE_FORMAT( NOW(), "%m/%d/%Y" );
+---------------------+----------------------------------+
| FormatDate( NOW() ) | DATE_FORMAT( NOW(), "%m/%d/%Y" ) |
+---------------------+----------------------------------+
| 07/15/2011 | 07/15/2011 |
+---------------------+----------------------------------+
You should either use it or replace your function body with a call of that function. Here is, however, a MySQL compatible version of your function:
DELIMITER $$
CREATE FUNCTION `FormatDate`(tiempo datetime) RETURNS varchar(10)
READS SQL DATA
BEGIN
DECLARE salida VARCHAR(10);
DECLARE dia VARCHAR(2);
DECLARE mes VARCHAR(2);
IF ( (tiempo <> '') AND ( tiempo <> '01/01/1900' ) ) THEN
SET dia := CAST( DAY( tiempo ) AS CHAR );
IF LENGTH( dia ) = 1 THEN
SET dia := CONCAT( '0', dia);
END IF;
SET mes := CAST( MONTH( tiempo ) AS CHAR );
IF LENGTH( mes ) = 1 THEN
SET mes := CONCAT( '0', mes );
END IF;
SET salida := CONCAT_WS( '/', mes, dia, CAST( YEAR( tiempo ) AS CHAR ) );
ELSE
SET salida := NULL;
END IF;
RETURN salida;
END $$
DELIMITER ;