MySQL Procedure within a Select? - mysql

I have a procedure that works like this:
mysql> call Ticket_FiscalTotals(100307);
+---------+--------+----------+------------+------------+
| Service | Items | SalesTax | eTaxAmount | GrandTotal |
+---------+--------+----------+------------+------------+
| 75.00 | 325.00 | 25.19 | 8.00 | 433.19 |
+---------+--------+----------+------------+------------+
1 row in set (0.08 sec)
I would like to call this procedure from within a select, like so:
SELECT Ticket.TicketID as `Ticket`,
Ticket.DtCheckOut as `Checkout Date / Time`,
CONCAT(Customer.FirstName, ' ', Customer.LastName) as `Full Name`,
Customer.PrimaryPhone as `Phone`,
(CALL Ticket_FiscalTotals(Ticket.TicketID)).Service as `Service`
FROM Ticket
INNER JOIN Customer ON Ticket.CustomerID = Customer.CustomerID
ORDER BY Ticket.SiteHomeLocation, Ticket.TicketID
However I know that this is painfully wrong. Can someone please point me in the proper direction? I will need access to all of the columns from the procedure to be (joined?) in the final Select. The SQL code within that procedure is rather painful, hence the reason for it in the first place!

The Ticket_FiscalTotals procedure returns a data set with some fields, but you need just one of them - Service. Rewrite your procedure to stored function - Get_Ticket_FiscalTotals_Service.
Another way is to create and fill temporary table in the procedure, and add this temporary to a query, e.g.:
DELIMITER $$
CREATE PROCEDURE Ticket_FiscalTotals()
BEGIN
DROP TEMPORARY TABLE IF EXISTS temp1;
CREATE TEMPORARY TABLE temp1(
Service FLOAT(10.2),
Items FLOAT(10.2),
SalesTax FLOAT(10.2),
eTaxAmount FLOAT(10.2),
GrandTotal FLOAT(10.2)
);
INSERT INTO temp1 VALUES (75.0, 325.0, 25.19, 8.0, 433.19);
END
$$
DELIMITER ;
-- Usage
CALL Ticket_FiscalTotals();
SELECT t.*, tmp.service FROM Ticket t, temp1 tmp;

You can't join directly to stored procedure. You can join to temporary table that this stored procedure fills:
create temporary table,
execute SP that fills data in your temp table,
join to temp table in your query,
drop temp table.
Of course it is not one line solution.
The other way (worse in my opinion) I think of is to have as many UDF as columns in SP result set, this might look like fallowing code:
SELECT
Ticket.TicketID as `Ticket`,
Ticket.DtCheckOut as `Checkout Date / Time`,
CONCAT(Customer.FirstName, ' ', Customer.LastName) as `Full Name`,
Customer.PrimaryPhone as `Phone`,
Ticket_FiscalTotals_Service(Ticket.TicketID) as `Service`,
Ticket_FiscalTotals_Items(Ticket.TicketID) as `Items`,
Ticket_FiscalTotals_SalesTax(Ticket.TicketID) as `SalesTax`,
Ticket_FiscalTotals_eTaxAmount(Ticket.TicketID) as `eTaxAmount`,
Ticket_FiscalTotals_GrandTotal(Ticket.TicketID) as `GrandTotal`
FROM Ticket
INNER JOIN Customer ON Ticket.CustomerID = Customer.CustomerID
ORDER BY Ticket.SiteHomeLocation, Ticket.TicketID

Related

I keep getting zeros when I call a procedure that should be calling data I know exists

I'm trying to write a stored procedure in MySQL and then call it back, and I have to submit a screenshot of the procedure returning a correct response. The code for storing the procedure seems to work fine (no errors, at least), but when I run the CALL function it returns 0.00 no matter which number I put in for #column3. My instructor thinks the issue is stating the OUT as AmountDue before I define the variable at the very top, but I couldn't figure out another way to have an input for #column3 in the CALL function without the IN/OUT constraints. I'm very new at this, obviously, so forgive me if I'm missing something obvious...Anyone got any ideas?
Also, I don't need any help with building the database, adding tables, anything like that. The database exists and functions appropriately. Only need help on storing the procedure and calling it back. Thanks.
delimiter //
DROP PROCEDURE IF EXISTS GetAmountDue;
CREATE PROCEDURE GetAmountDue(IN order_num INT, OUT AmountDue DECIMAL(10,2))
BEGIN
DECLARE AmountDue DECIMAL(10,2) DEFAULT 0;
SELECT COST
INTO #AmountDue
FROM cake_shape
INNER JOIN ll_cakery.order
ON cake_shape.shape_id=order.shape_id
WHERE order_num=#order_num;
SELECT AmountDue;
END//
delimiter ;
CALL GetAmountDue('113',#AmountDue);
order_num is a column with individual 3-character integer data values
cost is a column with individual decimal(10,2) data values
cake_shape is a table
ll_cakery.order is a table (that doesn't work quite right because
mysql has a command ORDER so I have to give the schema name)
shape_id is a column, only used in the procedure for the join
in the CALL function, #order_num=113
You are passinf a string not an int
You don't compare column 3 with column1
Last you have to set the output variable with the data ou get from the select
Last never name variables like columns name, that brings only problems
CREATE tABLE table1 ( COST DECIMAL(19,2),column2 int, column3 int)
INSERT INTO table1 VALUES (10.2,1,1),(10.2,1,1)
CREATE TABLE table2 (column2 int)
INSERT INTO table2 VALUES (1)
CREATE PROCEDURE GetAmountDue(IN _column1 INT, OUT _AmountDue DECIMAL(10,2))
BEGIN
SELECT SUM(COST)
INTO #AmountDue
FROM table1
INNER JOIN table2
ON table1.column2=table2.column2
WHERE column3=_column1;
SET _AmountDue := #AmountDue;
END
CALL GetAmountDue(1,#AmountDue);
SELECT #AmountDue
| #AmountDue |
| ---------: |
| 20.40 |
db<>fiddle here

Mysql procedure to insert data from file

I have an application that save data into a table , say my_table.
my_table
id | name | salary
this is a data entry application and not having a centralized database.Once all data entries complete, I have to merge the databases. My plan is to export insert statements from say DB2 and append it to DB1. So i wrote a procedure as follows:
CREATE PROCEDURE insertToTable
DECLARE max_id INT DEFAULT 1
BEGIN
SELECT MAX(id) INTO max_id FROM my_table
INSERT INTO table(id,name,salary) VALUES(max_id+1,'tom',1000);
INSERT INTO table(id,name,salary) VALUES(max_id+1,'john',1500);
....//a lot of statements
END
here i just increment id of DB2 by the max(id) of DB1 to avoid conflict.It works fine.
But some databases have large number of records.I could get these insert statements with 'max_id' variable in position.Then can I execute these 'insert' statements from file inside that procedure. Or is there any better solution..
Make "Id" column auto incremental by adding sequence.
Then create a trigger that increment upon insert.
I think i need this trigger:
CREATE TRIGGER insert_test BEFORE INSERT ON table my_table
FOR EACH ROW
BEGIN
SET #max_id = select max(id) from my_table;
IF NEW.id >= #max_id THEN
NEW.id = #max_id + 1;
END IF;
END;
Thanks for your suggestion.

Managing database view to get proper result

I have view which gives reasonably correct answer:
DELIMITER $$
DROP VIEW IF EXISTS `test`.`new_temp`$$
CREATE ALGORITHM=UNDEFINED DEFINER=`root`#`localhost` SQL SECURITY DEFINER VIEW `new_temp` AS
SELECT `temp`.`pcount` AS `ind_type`,SUM(`temp`.`pcount`) AS `Index_val` FROM `temp` UNION ALL
SELECT `temp`.`ncount` AS `sum`,SUM(`temp`.`ncount`) AS `ncount` FROM `temp` $$
DELIMITER ;
Ouput:
ind_type Index_val
----------------------
2 23
2 34
I want it to give this kinda output:
New_temp
ind_type Index_val
-------------------------------
pcount 23
ncount 34
Problem is with code I have written. I tried in different way but i did not get it. any idea?
What you are trying to get is actual name of the column rather than it's value. In such case instead of saying
SELECT `temp`.`pcount` AS `ind_type`
Do it like
SELECT 'pcount' AS `ind_type`
EDIT:
Not sure what do you mean by giving same result. I tried the same and it worked fine; as below
create table temp (pcount int,ncount int);
insert into temp values(22,33);
insert into temp values(23,43);
create VIEW new_temp as
select 'pcount' AS 'ind_type',sum(pcount) as 'ind_val'
from temp
union
select 'ncount' AS 'ind_type',sum(ncount) as 'ind_val'
from temp;
Check this SQL fiddle http://sqlfiddle.com/#!2/bbcf6/1
Normally, you would have the values in a normalized dictionary table or similar. But since you don't provide any of that in your query, the below should give the desired result.
SELECT 'pcount' AS `ind_type`,SUM(`temp`.`pcount`) AS `Index_val` FROM `temp` UNION ALL
SELECT 'ncount' AS `ind_type`,SUM(`temp`.`ncount`) AS `ncount` FROM `temp` $$

Trying to use stored procedure to access three tables but receiving only one row

So far I have tried many different ways of accessing the data on three tables using a stored procedure. First I tried a simple select statement :
create procedure reportCodes () begin
SELECT Numbers.serial_numb, numOwner.lName, numOwner.fName, numOwner.email,
location.long, location.lat, Numbers.dateValidated
FROM Numbers, Owner, location
WHERE Numbers.used = true AND Numbers.id=numOwner.Numbers_id AND
Numbers.id=location.Numbers_id;
end$$
(names changed to protect the guilty)
Running the stored procedure in phpmyadmin results in the first instance of the record (1 out of two ‘true’ in the test database). Running just:
SELECT Numbers.serial_numb, numOwner.lName, numOwner.fName, numOwner.email,
location.long, location.lat, Numbers.dateValidated
FROM Numbers, Owner, location
WHERE Numbers.used = true AND Numbers.id=numOwner.Numbers_id AND
Numbers.id=location.Numbers_id;
in the phpmyadmin SQL tab returns both records. Then I tried a temp table:
create procedure reportCodes () begin
CREATE TEMPORARY TABLE used_numbers AS (
SELECT Numbers.serial_numb, numOwner.lName, numOwner.fName, numOwner.email,
location.long, location.lat, Numbers.dateValidated
FROM Numbers, Owner, location
WHERE Numbers.used = true AND Numbers.id=numOwner.Numbers_id AND
Numbers.id=location.Numbers_id);
SELECT * FROM used_numbers; end$$
Returns 1 of 2 records as the procedure but both records in console. Finally I tried changing my table to a join:
CREATE PROCEDURE reportCodes()
begin
create temporary table used_numbers AS (
SELECT Numbers.serial_numb, numOwner.lName, numOwner.fName, numOwner.email,
location.long, location.lat, Numbers.dateValidated
FROM Numbers JOIN numOwner
ON Numbers.id=numOwner.Numbers_id
JOIN location ON
numOwner.Numbers_id=location.Numbers_id
WHERE Numbers.used = true
);
SELECT * FROM used_numbers; end$$
Same results as above. I’m at a loss as to why running just the SQL would show both test records but running the procedure with the exact same code only yields one.
Thanks
in your query, numOwners isn't a valid table being selected against, so something's wrong. Have you tried running your SQL in the Query window in phpMyAdmin to ensure that the EXACT same query is returning 2 rows?
I presume the "Owner" table is supposed to be "numOwner", so I've re-written the stored procedure call below. Also, I'm not sure what types of values you're storing in Numbers.used to evaluate to "TRUE". I will presume you're using a TINYINT(1), so I've altered that, as well. I hope this helps.
DELIMITER $$
USE `db`$$
DROP PROCEDURE IF EXISTS `reportCodes`$$
CREATE PROCEDURE `reportCodes`()
BEGIN
SELECT
n.serial_numb,
o.lName,
o.fName,
o.email,
l.long,
l.lat,
n.dateValidated
FROM Numbers n
INNER JOIN numOwner o ON n.id=o.Numbers_id
INNER JOIN location l ON n.id=l.Numbers_id;
WHERE n.used = 1
END$$
DELIMITER ;

How can I select out parameters in a MySQL procedure as table columns?

Environment: MySQL 5.1, Linux
I have a stored procedure that computes several values from a single input value. The values are returned as OUT parameters. I would like to call this procedure for every row set and have the values appear as columns in the result set. The values have a complex relationship such that distinct functions for each value is not easily constructed.
The question: How can I get OUT parameters to show up as columns in a table?
Here's what I have so far:
DELIMITER $_$
DROP PROCEDURE IF EXISTS in_out;
CREATE PROCEDURE in_out (
IN s TEXT,
OUT op TEXT,
OUT opn INT,
OUT opd TEXT,
OUT len INT
)
BEGIN
SET op = 'del';
SET opn = 1;
SET opd = substr(s,4);
SET len = LENGTH(SUBSTR(s,4));
END
$_$
DELIMITER ;
Then:
mysql> call in_out('delACT',#op,#opn,#opd,#len);
Query OK, 0 rows affected (0.00 sec)
mysql> select #op,#opn,#opd,#len;
+------+------+------+------+
| #op | #opn | #opd | #len |
+------+------+------+------+
| snv | 1 | ACT | 3 |
+------+------+------+------+
1 row in set (0.00 sec)
So far so good, but I can't figure out how to call this procedure for every row and return the results in the result set. I want is something like this:
dream> select mycol,in_out(mycol) from mytable
+---------+------+------+------+------+
| mycol | #op | #opn | #opd | #len |
+---------+------+------+------+------+
| delACT | del | 1 | ACT | 3 |
+---------+------+------+------+------+
Thanks!
You confuse the stored procedures and stored functions:
stored function will be return a value, the results can be used in
expressions (like COS() and other mysql built-in functions).
stored procedure need use CALL , is an independent operation, can not
be used in expressions.
If you want to "select mycol,in_out(mycol) from mytable",you must:
CREATE FUNCTION in_out( ...
This appears to be a trick question: one can't create table relations out of function/procedure results in MySQL. I ended up refactoring into separate functions (as suggested by Michał). I had been hoping for a MySQL equivalent to PostgreSQL's table functions (http://goo.gl/77QVE).
I'd recommend to prepare data in stored procedure for each possible value in:
select distinct mycol
from mytable
where <... condition that you would use anyway in final result ...>
where mycol is your parameter for stored procedure save it to temporary table and than join to this values.
-- way the temp table may look in your sp
create temporary table tmptable (
mycol text
op text,
opn int,
opd text,
len int
)
after that use join:
select m.mycol, t.op, t.opn, t.opd, t.len
from mytable m
join tmptable t on m.mycol = t.mycol
where <... condition that you would use anyway in final result ...>
Bit different question, are you absolutely sure that there is no different way to process your final result than using a stored procedure?