I have this stored procedure
DELIMITER $$
USE `testdb`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `TestProcedure`(
IN year_number YEAR,
IN month_name VARCHAR(12),
IN input_region VARCHAR(20)
)
BEGIN
DECLARE total_regions_count INT DEFAULT 0;
## Get Distinct Regions.
SELECT
total_regions_count = COUNT(DISTINCT region)
FROM aws_cost AS AC
WHERE AC.year = year_number;
SELECT total_regions_count;
END$$
DELIMITER ;
When I call this stored procedure total_regions_count I get is 0 but when I execute the query directly, I get the correct count of distinct values (Which is 9 and not 0.).
Why is the variable returning me default value of the variable as the result? Why 9 is not getting returned?
I have tried INTO keyword also to set the value but still the same result.
SELECT COUNT(DISTINCT region) INTO total_regions_count ...
It doesn't work properly inside the stored procedure because you're attempting to make a comparison between the value stored in "total_regions_count" (defaulted to 0) and COUNT(DISTINCT region), which is a number bigger than 0. Since the comparison fails, you get the value 0.
Try instead using INTO as follows:
DELIMITER $$
USE `testdb`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `TestProcedure`(
IN year_number YEAR,
IN month_name VARCHAR(12),
IN input_region VARCHAR(20)
)
BEGIN
DECLARE total_regions_count INT DEFAULT 0;
## Get Distinct Regions.
SELECT COUNT(DISTINCT region) INTO total_regions_count
FROM aws_cost AS AC
WHERE AC.year = year_number;
SELECT total_regions_count;
END$$
DELIMITER ;
In MySQL expressions, = is an equality comparison operator, not an assignment operator.
You could use := if you want to make an assignment in an expression. But this syntax is now discouraged.
The preferred syntax is to use SELECT ... INTO to assign the results of queries to variables:
SELECT
COUNT(DISTINCT region)
FROM aws_cost AS AC
WHERE AC.year = year_number
INTO total_regions_count;
Is it possible that the count of matching rows is in fact zero? You could test this by making the default value of total_regions_count some other value like -1. Then you'll be sure that the value is overwritten by the count computed by your query.
The variable usage is obviously excess. W/o it this SP contains one stmt hence BEGIN-END and DELIMITER are excess too.
CREATE DEFINER=`root`#`localhost` PROCEDURE `TestProcedure`(
IN year_number YEAR,
IN month_name VARCHAR(12),
IN input_region VARCHAR(20)
)
SELECT COUNT(DISTINCT region) AS total_regions_count
FROM aws_cost AS AC
WHERE AC.year = year_number;
Also month_name and input_region parameters are used nowhere and hense they're excess too.
You use SELECT variable = expression. This is SQL Server (MS SQL) syntax. In MySQL this construction performs another task - not assignment but compare. With obvious FALSE result - the variable value is zero whereas the expression will return zero only when there exists at least one row in this table and all rows in the table contains NULL in region column.
Related
I am new to mySQL my background is SQL Server
I have this SP that has this statement
DELIMITER //
create PROCEDURE spTest ()
BEGIN
declare vCnt int;
declare vMax int;
select vCnt = count(*), vMax=Max(ShortID) from ShrtMain;
select vCnt * vMax as Total;
END
I am expecting to one result with one field called Total
but what I actually get 2 results
one with 2 columns as shown here
and the other is what I actually want
how can I get just one result ?
To set a variable from a SELECT inside a MySQL stored procedure you use the SELECT ... INTO form of the query:
SELECT COUNT(*) INTO LimitCount
FROM Locations
WHERE IPAddress = IPAddress;
Note that it's inadvisable to use variables with the same name as columns (e.g. IPAddress in your query) as there is the potential for MySQL not to be able to determine which you want to use.
When I call this stored procedure it shows error: unknown column...
BEGIN
if (
`LastRow.Transaction`=4 and `LastRow.Xre`>1)
then
SELECT
sleep(2);
END if;
end
Please note that sleep(2) is just to demonstrate to do something if condition is true. What would be the proper way to accomplish a test based on value of a specific record? In the above example the table (actually a View) has only one row.
Q: What would be the proper way to accomplish a test based on value of a specific record?
If you mean, based on values in columns stored in one row of a table... it seems like we would need a query that references the table that retrieve the values stored in the row. And then we can have those values available in the procedure.
As an example
BEGIN
-- local procedure variables, specify appropriate datatypes
DECLARE lr_transaction BIGINT DEFAULT NULL;
DECLARE lr_xre BIGINT DEFAULT NULL;
-- retrieve values from columns into local procedure variables
SELECT `LastRow`.`Transaction`
, `LastRow`.`Xre`
INTO lr_transaction
, lr_xre
FROM `LastRow`
WHERE someconditions
ORDER BY someexpressions
LIMIT 1
;
IF ( lr_transaction = 4 AND lr_xre > 1 ) THEN
-- do something
END IF;
END$$
That's an example of how we can retrieve a row from a table, and do some check. We could also do the check with SQL and just return a boolean
BEGIN
-- local procedure variables, specify appropriate datatypes
DECLARE lb_check TINYINT(1) UNSIGNED DEFAULT 0;
-- retrieve values from columns into local procedure variables
SELECT IF(`LastRow`.`Transaction` = 4 AND `LastRow`.`Xre` > 1,1,0)
INTO lb_check
FROM `LastRow`
WHERE someconditions
ORDER BY someexpressions
LIMIT 1
;
IF ( lb_check ) THEN
-- do something
END IF;
END$$
I have created one procedure which take 2 parameter and it check the count.
But when I pass "" blank value It still return 1 count.
Did not get it why it is working like this.
Thanks for the help below is my procedure
DELIMITER $$
CREATE DEFINER=`dadclient`#`123.63.249.169` PROCEDURE `checkInOut`(IN grid varchar(50),OUT count INT)
begin
select count(GRIDID) into count from GRIDID where GRIDID=grid;
select count;
END
when I call
checkInOut("",#aaa);
select #aaa;
When I call this,it return me 1 which is wrong.
But when I pass "" blank value It still return 1 count.
Because when you say it is blank by providing an empty string it is a value. Empty string is also treated as a value in database and hence you get count as 1
The MySQL docs says:
COUNT(expr)
Returns a count of the number of non-NULL values of expr in the rows
retrieved by a SELECT statement. The result is a BIGINT value.
So if you want the count to return 0 then instead of making the string as empty "" you need to make the value as NULL.
Yo mate, try this:
DELIMITER $$
CREATE
DEFINER=`dadclient`#`123.63.249.169`
PROCEDURE `checkInOut`(
IN `grid` VARCHAR(50),
OUT `count` INT
)
BEGIN
-- insert value into variable
SET `count` = (
select count(GRIDID)
from GRIDID
where GRIDID=grid;
);
END$$
DELIMITER ;
So in your application, e.g. php you can CALL checkInOut($input, $output);. No need for the final SELECT... part in your initial code, afaik, because you already declared count as an OUT in the procedure parameter
Note:
Is the name GRIDID the name of your table? because as I see, you also used it in your WHERE statement as a key filter
Regarding your query, supposedly it is expected to contain one row of result. Kindly check that also mate
I'm not very familiar with MySQL stored procedures, but am attempting to write one for the first time. In my procedure, I have 2 in parameters and one or both of them could be null. I need to create a cursor to loop over, but my cursor needs to be based on the in parameters. Where if 1 is null and the other isn't, my cursor query is different.
For example:
CREATE PROCEDURE test (IN date timestamp, IN id int(11))
BEGIN
DECLARE cur CURSOR FOR
IF timestamp IS NOT NULL THEN
IF id IS NULL THEN
SELECT columns FROM Table WHERE modified_on <= timestamp
ELSE
SELECT columns FROM Table WHERE userid = id AND modified_on <= timestamp
ELSE
/* Logic here to pull query without the timestamp and where userid matches if the id passed in is not null */
END IF
END
Could someone show me a simple example of how to achieve this?
issue
syntax error, the declare cursor statement requires to be associated with exactly one select query :
DECLARE cursor_name CURSOR FOR select_statement
also Table is a reserved keyword and needs to be escaped ( or use a different name ) in :
SELECT columns FROM Table
to fix, either create two cursors one for each scenario or embed both query paths in one select query
setup
create table `Table`
(
id integer primary key auto_increment not null,
userid integer not null,
modified_on datetime not null
);
fix
-- option one : combine queries into one
drop procedure if exists test;
delimiter $$
CREATE PROCEDURE test (IN date timestamp, IN id int(11))
BEGIN
DECLARE cur CURSOR FOR SELECT columns FROM `Table` WHERE ( id is null or userid = id ) and modified_on <= timestamp;
-- open and read from cursor..
END$$
delimiter ;
-- option two define two cursors and use conditional logic below to decide which to read from
drop procedure if exists test;
delimiter $$
CREATE PROCEDURE test (IN date timestamp, IN id int(11))
BEGIN
DECLARE cur1 CURSOR FOR SELECT columns FROM `Table` WHERE modified_on <= timestamp;
DECLARE cur2 CURSOR FOR SELECT columns FROM `Table` WHERE userid = id AND modified_on <= timestamp;
-- evaluate if/else logic here to decide which cursor to open and use..
END$$
delimiter ;
note: not sure what you're planning todo for each cursor fetch. depending on your use case, its possible you can do this without a cursor. if this is the case, dont use a cursor and keep the processing closer to the natural sql set-based processing
reference
mysql declare cursor syntax
ansi sql reserved keywords
mysql cursors
It appears that performing a where clause on a table with Mysql works as expected (first code example).
However, when a where clause is performed on a view, the where clause appears to be ignored.
To keep things simple, I've tested a simple where clause on a standard table- this performs as expected, additionally a 'proof test' was ran to see if a mysql procedure can do a simple select * on a view (it did). Thus, it's only when the where clause is added to quiers on views.
How can I perform a WHERE query within a stored procedure on a View?
Example code 1 (working with normal table):
DELIMITER //
CREATE PROCEDURE p1 (id INT, fname VARCHAR(250))
BEGIN
DECLARE staffId INT;
DECLARE name VARCHAR(250);
SET name = fname;
SET staffId = id;
SELECT * FROM Staff WHERE ID_Staff = staffId AND Fname = name;
END; //
DELIMITER
Result set returned from the above performs as expected, acting upon the where clause.
However, with when using a where clause on a view the where clause is ignored:
Example code (not working as expected)
DELIMITER //
CREATE PROCEDURE p2 (year INT)
BEGIN
DECLARE a CHAR(4);
SET a = year;
SELECT * FROM TotalHoursView WHERE Year = "2014";
END; //
DELIMITER ;
Note: 'TotalHoursView' is a view, not a table.
The result of the second procedure ignores the where clause, always returning the full contents of the view (SELECT * FROM TotalHoursView).
Does Mysql not support where clauses on views when called in a stored procedure?
http://dev.mysql.com/tech-resources/articles/mysql-storedprocedures.pdf
Try to use another names for your variables, it's not CASE sensitive