MySQL WorkBench Stored Procedure Question - mysql

Can't figure out how to make mysql display the stored procedure result. Can't use table_name.column_name when calling the procedure. So the procedure doesn't know what table in the schema it should call? Trying to take an average of a numeric column called cateringID in a table called package. This table has NULL values several rows. Need to do this as a procedure. First converted all the NULLs values in cateringID field to numeric value of 0.0 in the procedure. Then took the resulting average of this field in the procedure. Then tried to call the procedure. But when trying to extract the average value of the cateringID field that is in the stored procedure, get NULL value?
DELIMITER //
CREATE PROCEDURE average_numeric_nulls(IN pPackageID INT, IN pCateringID DEC)
BEGIN
DECLARE pCateringID DECIMAL(5,4);
DECLARE catID DECIMAL(5,4);
SELECT IF(pCateringID IS NULL, 0.0000, FORMAT(pCateringID, 4))
INTO catID
FROM package
WHERE packageID = pPackageID;
SELECT(AVG(catID)) AS 'Replaced NULLS' FROM package;
END//
DELIMITER ;
CALL average_numeric_nulls(#packageID, #cateringID);
The pPackageID and pCateringID parameters represent the first two fields from an existing package table. ie.
pPackageID = packageID the PK in the package table. packageID is a numeric integer
pCateringID = cateringID the FK in the package table. cateringID is a mix of numeric integers and NULLs. Need to take the average of this column but must replace NULLs with 0.0 first.
So the procedure is supposed to read the value of the packageID from package table, pass this packageID value to the pPackageID variable in the procedure, then replace all pCateringID values if they are NULLs with the value 0.0000. So the average of the resulting cateringID column in the package table can be taken.
example package table
packageID cateringID packageName
001 NULL A
002 NULL B
003 001 C
004 002 D
005 003 E
Result ouput:
Replaced NULLS
NULL

So the procedure is supposed to read the value of the packageID from package table, pass this packageID value to the pPackageID variable in the procedure, then replace all pCateringID values if they are NULLs with the value 0.0000. So the average of the resulting cateringID column in the package table can be taken.
This can be performed by one single query:
SELECT FORMAT(AVG(COALESCE(cateringID, 0)), 4) AS avg_cateringID
FROM package
-- WHERE ...;
If you need to get average for some definite rows set then add according WHERE.
If you need to do it in SP form then
CREATE PROCEDURE average_numeric_nulls(IN pPackageID INT, IN pCateringID DEC)
SELECT FORMAT(AVG(COALESCE(cateringID, 0)), 4) AS avg_cateringID
FROM package
-- WHERE ...;
Use SP parameters in WHERE clause (or remove them if they not needed).

Related

Comma separated string parameter filter in Where clause My SQL

I'm trying to filter the records with where clause in procedure based on IN input parameter values I had written the stored procedure in My SQL as like below :
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_get_logs_Test`(IN `p_Bot_Ids` VARCHAR(500))
NO SQL
select id, bot_id, log_level,log_type,time_stamp,finger_print,windows_identity,machine_name,process_name,process_version
,job_Id,robot_name,machine_Id,file_name,message,created_date from log
where id < 200 and
bot_id IN (p_Bot_Ids)$$
DELIMITER ;
My "p_Bot_Ids" is a comma separated string. If I pass "1,2" its filtering only with "1". if I pass "2,1" its filtering with only "2".
Also my "p_Bot_Ids" can also be null.In that case I needs to pull out all the records.
Let us consider there are 50 records in my table. If i pass "p_Bot_Ids" = "1,2,3" I needs to get only 1,2,3 Ids records(total 3 rows) only.
If I pass "p_Bot_Ids" = NULL then I should get all my 50 records.
What you are passing to the procedure is not a list: it is a comma-separated list, in other words a scalar value. So IN does not do what you expect: it actually checks if bot_id is equal to the parameter (this includes implicit conversion to the correct datatype).
If you are to keep the parameter as such, then one option is to use string function find_in_set() instead: its purpose is to search for a value in a comma-separated list.
where id < 200 and find_in_set(bot_id, p_Bot_Ids)
If you want to match on null values too, then:
where id < 200
and (
(bot_id is null and p_Bot_Ids is null)
or find_in_set(bot_id, p_Bot_Ids)
)

Pass multiple parameters to sql function

I have sql table with data as below
SnackID Name
1 Chicken
2 Soda
3 Chocolate
4 IceCream
I have the below user-defined function which accepts arguments as a string with multiple values like 'Chicken', 'Soda'.
CREATE FUNCTION GetSnackCodes
(
#myValues varchar(max)
)
RETURNS #SnacksCodes TABLE
(
mySnackCoded int NULL
)
AS
BEGIN
insert into #SnacksCodes
select SnackID from Snack where Name In (#myValues)
return ;
END;
GO
When I tried to invoke this function by passing multiple values to this variable I am not getting expected result.
I guess it's trying to search multiple (comma separated )values as a single value.
Any other possible workaround for how to pass this values?
Your guess is correct - when you pass a single string with comma-separated values, SQL server treats it as a single string value.
Use table valued parameter instead:
CREATE TYPE SnackCode As Table (
Name NVARCHAR(50)
);
GO;
CREATE FUNCTION GetSnackCodes (
#myValues SnackCode
)
RETURNS #SnacksCodes TABLE (
mySnackCoded int NULL
)
AS
BEGIN
insert into #SnacksCodes
select SnackID
from Snack
where Name In (select Name from #myValues)
return ;
END;
GO
you can split comma separated value and store that in temporary table then pass that table value result to query

IFNULL is not working

Hi I am working with mysqli to replace a default value on the table if the data from the database is NULL. I already tried it on PHPmyAdmin and it's working but not on my code :(
Here's my SELECT query:
$query="SELECT pro_id, pro_name, unit_name, cat_name, IFNULL(quantity,'empty') AS quantity FROM products, unit, categories WHERE products.unit=unit.unit_id AND products.pro_cat=categories.cat_id";
If, as one of your comments seems to indicate, the error you're getting is:
Incorrect parameter count in the call to native function 'ISNULL'
then it's a simple typo. ISNULL is not the same as IFNULL.
The former returns a truth value if its one argument is null.
The latter returns the second argument if the first is null, otherwise it returns the first argument.
You can see this if you put the following code into SqlFiddle:
-- DDL
create table xyzzy (plugh int);
insert into xyzzy (plugh) values (null);
insert into xyzzy (plugh) values (42);
select plugh, isnull(plugh) from xyzzy;
select plugh, ifnull(plugh,-1) from xyzzy;
select plugh, isnull(plugh,-1) from xyzzy;
The output is as expected for the first two select statements while the third generates the error you describe:
plugh isnull(plugh)
------ -------------
(null) 1
42 0
plugh ifnull(plugh,-1)
------ ----------------
(null) -1
42 42
Incorrect parameter count in the call to native function 'isnull'

Merge stored procedure with datatype conversions

I am able to execute my stored procedure. When I execute it a second time instead of updating the existing values same values from source are inserted as new values.
i.e my target has
1
2
3
When I run the stored procedure a second time, instead of updating 1,2,3, it is inserting the same
1
2
3
1
2
3
My condition for when matched then select S.REPORT_TEST1 except T.REPORT_TEST1 is not working.
When I use the same code on a different table which doesn't have data conversions I am able to update.
Can anyone tell where am I going wrong?
CREATE PROCEDURE [dbo].[Merge]
INSERT INTO .[dbo].[TARGET](REPORT_TEST1, REPORT_TEST2, REPOST_TEST3)
FROM (MERGE [dbo].[TARGET] T
USING (SELECT
Cast([REPORT TEST1] as int) [REPORT_TEST1],
Cast([REPORT TEST2] as int) [REPORT_TEST2],
Cast([REPORT TEST3] as int) [REPORT_TEST3]
FROM
[dbo].[SOURCE]) S ON (T.[REPORT_TEST1] = S.[REPORT_TEST1])
WHEN NOT MATCHED BY TARGET
THEN INSERT
VALUES (S.REPORT_TEST1, S.REPORT_TEST2, S.REPOST_TEST3)
WHEN MATCHED
AND EXISTS (SELECT S.REPORT_TEST1, S.REPORT_TEST2, S.REPOST_TEST3
EXCEPT
SELECT T.REPORT_TEST1, T.REPORT_TEST2, T.REPOST_TEST3)
OUTPUT $ACTION ACTION_OUT,
S.REPORT_TEST1, S.REPORT_TEST2, S.REPOST_TEST3) ;
Thanks
would it not suffice to rewrite your WHEN MATCHED statement thusly:
WHEN MATCHED
AND S.REPORT_TEST2 <> T.REPORT_TEST2
AND S.REPORT_TEST3 <> T.REPORT_TEST3
(
SELECT
S.REPORT_TEST1
,S.REPORT_TEST2
,S.REPOST_TEST3
)
I think I understand what you're trying to do, but inside the MERGE context, you're only comparing this row with that row, not the source row against the whole target table. you could modify the subselect thusly if you're trying to query "this source is not at all in the target"
WHEN MATCHED AND EXISTS
(
SELECT
S.REPORT_TEST1
,S.REPORT_TEST2
,S.REPOST_TEST3
EXCEPT SELECT
T2.REPORT_TEST1
,T2.REPORT_TEST2
,T2.REPOST_TEST3
FROM
[dbo].[TARGET] T2
)

SSRS Creating an Expression with unkown column names

I have a stored procedure that returns three columns worth of data to our SSRS report. The stored procedure does not alias two of those columns, so they are returned unnamed. Here is an example of what the return dataset might look like:
[FundName] [blank] [blank]
Abc col2val1 col3val1
Def col2val2 col3val2
Ghi col2val3 col3val3
I'd like to be able to use an expression in SSRS to retrieve the values from column 2 and 3. Here's an example of what retrieving data from FundName would look like:
=Fields!FundName.Value
Is there any way to replace the column name (in this example, FundName) with say, the index or position of the column, like so:
=Fields![0].Value //returns FundName values
=Fields![1].Value //returns column 2 values
=Fields![2].Value //returns column 3 values
Thank you in advance.
If your stored procedure is not returning the columns names then you can't create a dataset in SSRS as it will throw an error
An item with the same key is already been added
and there is now way you can reference the column name using index in SSRS
Fortunately, a way to accomplish this has been found. Since our stored procedure could not be changed and it did not return enough information for SSRS to generate a report (missing column names in the resulting DataSet), we changed the way our DataSet gets populated.
In the DataSet query builder, we created a temporary table and had the stored procedure insert into that temporary table. Once inserted, we selected all the values in our temporary table which populated the DataSet. Now the DataSet has 3 columns with 3 column names to be used by our report.
CREATE TABLE #tempTable (
FundName varchar(50),
col2 dec(15,4),
col3 char(8)
)
insert into #tempTable
exec storedProcedureName
select * from #tempTable
drop table #tempTable
Then you can access those column values in an expression just like before:
=Fields!FundName.Value //returns FundName values
=Fields!col2.Value //returns column 2 values
=Fields!col3.Value //returns column 3 values
I hope this helps anyone else with this particular issue.