Stored procedure : Data truncation: Truncated incorrect DOUBLE value - mysql

I lack experience building stored procedures and have encountered this error that I cannot understand the reasoning behind :
[2015-09-29 01:01:55] [22001][1292] Data truncation: Truncated incorrect DOUBLE value: '5609d3e6c89be'
The value '5609d3e6c89be' is the "FlightID".
My stored procedure code :
DROP PROCEDURE IF EXISTS initFlight;
CREATE PROCEDURE initFlight (flightid VARCHAR(50))
BEGIN
-- rules, player should only fly if not in jail, not in missions
-- and is in the city the flight will take off from
DECLARE fname VARCHAR(50); -- flight name
DECLARE depart int; -- city number of departure
DECLARE dest int; -- city number of destination
-- assign values to our variables
select flightname, source_airport, destination_airport
into fname, depart, dest
from airport_flights where id = flightID;
-- show in console the variable values for debugging
-- select concat(" fname: ", fname, " depart: ", depart, " dest: ", dest);
-- set players flying means p.live = '-1'
update `[players]` as p set p.live = '-1' where p.id in (
select id from airport_tickets where flight = flightID
) and p.live = depart;
-- insert into alerts a message for players boarding the flight (are in the city of departure)
insert into player_alerts (alert_text, player_id)
select concat("Boarding flight ", fname) as alert_text, p.id as player_id from `[players]` as p
where p.id in (
select id from airport_tickets where flight = flightID
) and p.live = depart;
-- insert into alerts a message for players that missed the flight (are not in the city of departure)
insert into player_alerts (alert_text, player_id)
select concat("You missed flight ", fname) as alert_text, id as player_id from `[players]` as p
where p.id in (
select id from airport_tickets where flight = flightID
) and p.live != depart;
-- stop sales
update airport_flights set selling_tickets = 0 where id = flightID;
END;
call initFlight('5609d3da016bf');
What is happening here? Why is my "string" being coverted into a double and then truncated?
airport_flights.id is varchar(50)
airport_flights.source_airport is int(11)
airport_flights.destination_airport is int(11)
airport_tickets.id is varchar(50)
airport_tickets.flight is varchar(50)
airport_tickets.owner_id is int(11)
`[players]`.id is int(11)
`[players]`.live is int(11)
`[players]`.name is varchar(200)
player_alerts.id is int(11)
player_alerts.alert_text is varchar(250)
PS: if you need any more information let me know and criticism is as always welcome

After much head bumping around I found out that the problem was in the sub-queries where I was mixing the airport_tickets.id (varchar) with the player.id (int) when I wanted to match airport_tickets.owner_id with player.id.
I only found this out when removing everything and re-writing it all as a measure of removing any code blindness (when your brain reads what it thinks the code does instead of what is actually written).

Related

How to populate a table with 1000 rows of sample data?

For the table bellow:
CREATE TABLE Persons (
ID int NOT NULL,
ModifiedDate datetime,
FirstName varchar(50),
LastName varchar(50),
EMail varchar(30),
PhoneNumber varchar(15),
PRIMARY KEY (ID)
);
You can write a query such as this:
INSERT INTO Persons(ModifiedDate, FirstName, LastName, EMail, PhoneNumber)
SELECT
CURRENT_TIMESTAMP - INTERVAL FLOOR(RAND()* 31536000) SECOND, -- random datetime up to -1 year
CHAR(FLOOR(RAND() * 26)+ ASCII('A')), -- random character between A-Z
CHAR(FLOOR(RAND() * 26)+ ASCII('A')),
CHAR(FLOOR(RAND() * 26)+ ASCII('a')), -- random character between a-z
CHAR(FLOOR(RAND() * 10)+ ASCII('0')) -- random character between 0-9
FROM any_table_with_1000_rows
LIMIT 1000
Any table with 1000 rows could be used. If there isn't one, you can join a table having n rows with itself to get n2 rows.
An easy way is to use https://www.mockaroo.com/ which is designed for that purpose. Create the columns you want and choose SQL as the output. It will make you a nice script.
You could also create an Excel spreadsheet to generate your SQL queries but it is a bit time consuming
Execute the following query, it will insert 1000 dummy rows
BEGIN
DECLARE #RowCount int = 1000,
#Index int = 1
WHILE (#Index <= #RowCount)
BEGIN
INSERT INTO Persons (ID, ModifiedDate, FirstName, LastName, EMail, PhoneNumber)
VALUES (#Index, getdate(), 'FirstName' + CAST(#Index AS varchar(10)), 'LastName' + CAST(#Index AS varchar(10)), 'EMail' + CAST(#Index AS varchar(10)), CAST(#Index AS varchar(10)))
SET #Index += 1
END
END

Stored Procedure in mySQL workbench (INSERT INTO error)

I'm running into an error in my stored procedure, and after numerous YT videos and forums, I still have no clue where I'm going wrong. Given what I'm trying to do, it all seems to look correct.
Here's the deal. I take in some information to buy some stock, I use an IF to make sure that I have enough money to make the purchase, I then insert the purchase information into my TRADES table and update the cash balance in ACCOUNTS to reflect the spending of $$.
I can't even test to see if it works correctly because it won't run. The only error I'm getting is at INSERT INTO, in which it says error: INTO (into) is not valid input at this position
I have done ALL of my insert statements the exact same way, and have no idea why this particular syntax is incorrect? Any help would be greatly appreciated! Below are two approaches, both with errors.
CREATE PROCEDURE `BUY` (TID INT,ID INT, CASH INT, T_NAME VARCHAR(4) ,
TCOUNT INT, TBUYDATE DATE, TBUYPRICE INT )
BEGIN
IF (ACCOUNT.CASH_BALANCE >= (TCOUNT * TBUYPRICE),
INSERT INTO TRADES (TRADE_ID, ACCOUNT_ID, TRADE_NAME, TRADE_COUNT, TRADE_BUYDATE, TRADE_BUYPRICE)
VALUES (TID, ID, T_NAME, TCOUNT, TBUYDATE, TBUYPRICE)
AND UPDATE ACCOUNT.CASH_BALANCE
WHERE ACCOUNT.ACCOUNT_ID = ID
SET ACCOUNT.CASH_BALANCE = (ACCOUNT.CASH_BALANCE - (TCOUNT * TBUYPRICE)),
NULL
)
END
I have also tried the following, however I get an error on END missing subclause or other elements before end
CREATE PROCEDURE `BUY` (TID INT,ID INT, CASH INT, T_NAME VARCHAR(4) , TCOUNT
INT, TBUYDATE DATE, TBUYPRICE INT )
BEGIN
IF (ACCOUNT.CASH_BALANCE >= (TCOUNT * TBUYPRICE))
THEN
INSERT INTO TRADES (TRADE_ID, ACCOUNT_ID, TRADE_NAME, TRADE_COUNT,
TRADE_BUYDATE, TRADE_BUYPRICE)
VALUES (TID, ID, T_NAME, TCOUNT, TBUYDATE, TBUYPRICE);
UPDATE ACCOUNT.CASH_BALANCE
SET ACCOUNT.CASH_BALANCE = (ACCOUNT.CASH_BALANCE - (TCOUNT * TBUYPRICE))
WHERE ACCOUNT.ACCOUNT_ID = ID;
ELSE #noinsert
END
There are multiple errors/corrections:
The Delimiter command was not used, so he gets confused on the end of statement and the end of the procedure definition
The account table needs to be selected in an exists statement
I've used a local variable l_cash instead of repeating TCOUNT * TBUYPRICE (Not an error).
The ELSE statement was not necessary and an END IF; was missing.
Update statement corrected.
Here is the corrected code:
DELIMITER $$
CREATE PROCEDURE `BUY` (TID INT,ID INT, CASH INT, T_NAME VARCHAR(4) , TCOUNT
INT, TBUYDATE DATE, TBUYPRICE INT)
BEGIN
DECLARE l_cash INT DEFAULT 0;
SET l_cash = TCOUNT * TBUYPRICE;
IF EXISTS(SELECT 1 FROM Account WHERE ACCOUNT_ID = ID AND CASH_BALANCE >= l_cash) THEN
INSERT INTO TRADES (TRADE_ID, ACCOUNT_ID, TRADE_NAME, TRADE_COUNT,
TRADE_BUYDATE, TRADE_BUYPRICE)
VALUES (TID, ID, T_NAME, TCOUNT, TBUYDATE, TBUYPRICE);
UPDATE ACCOUNT
SET CASH_BALANCE = (CASH_BALANCE - l_cash)
WHERE ACCOUNT_ID = ID;
END IF;
END$$
DELIMITER ;

Can't get MySQL function to work

Ok so I'm making this little excercise in MySQL. I'm a pokemon trainer that needs to have a record of wins and loses, who I battled and the money earned. Everything goes all dandy until I get to this part:
*Create a function that calculates the earnings, if the battle was won then the earnings increase, if the battle was a loss then earnings decrease.
I assign the rival trainers with a "class" from 1 to 4, each trainer gives a certain amount of money
1.- 250
2.- 500
3.- 1000
4.- 2000
My tables structures go more or less like this:
battle(idBattle, idTrainer, outcome, date, place)
Trainer(idTrainer, nameTrainer, class)
protagonist(idProtagonist, loses, wons, earnings)
I need to check on the outcome of the battle to know if my earnings will increase or decrease, then go to my table Trainer and check the class to see how much is the class worth, then return how much will I increase or decrease my earnings.
Also I want to create a trigger that automatically updates my table(ie. the main trainers table) when a new win or loss has been entered as well as updating the earnings. I'll leave the code bellow, I'm all dried out and have no idea what to do now. I'm pretty much desperate. I may have been looking at this problem from the worng angle, just need some advise.
MANY, MANY THANKS IN ADVANCE IF YOU CAN HELP ME OUT!
CREATE DATABASE ricardoRifa;
USE ricardoRifa;
CREATE TABLE entrenador (//trainer table
idEntrenador INT NOT NULL DEFAULT 98000,
nombreEntrenador VARCHAR(20),
clasificacion INT NOT NULL DEFAULT 1, //this is the trainer class
PRIMARY KEY (idEntrenador)
) ENGINE=INNODB;
CREATE TABLE batalla (
idBatalla INT NOT NULL AUTO_INCREMENT,
idEntrenador INT,
resultado BOOLEAN, //false=lost battle, true=won
lugar VARCHAR(20),
fecha DATE,
PRIMARY KEY (idBatalla , idEntrenador),
CONSTRAINT fk_idEntrenador FOREIGN KEY (idEntrenador)
REFERENCES entrenador (idEntrenador)
ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=INNODB;
CREATE TABLE ricardo (//main trainer table, I wanted it to be like this for there may be more than one instance depending on the main trainer id
idRicardo INT NOT NULL DEFAULT 11490677,
perdidas INT NOT NULL DEFAULT 0,
victorias INT NOT NULL DEFAULT 0,
ganancias INT NOT NULL DEFAULT 10000,
PRIMARY KEY (idRicardo)
) ENGINE=INNODB;
delimiter |
CREATE PROCEDURE incersionEntrenador(idEntrenador INT, nombreEntrenador VARCHAR(20), clasificacion INT)
BEGIN
INSERT INTO entrenador VALUES(idEntrenador, nombreEntrenador, clasificacion);
END |
delimiter |
CREATE PROCEDURE incersionBatalla(idEntrenador INT, resultado BOOLEAN, lugar VARCHAR(20), fecha DATE)
BEGIN
INSERT INTO batalla (idEntrenador, resultado, lugar, fecha) VALUES(idEntrenador, resultado, lugar, fecha);
END |
delimiter |
CREATE FUNCTION calcularGanancia() RETURNS INT
BEGIN
DECLARE class, dinero INT;
SELECT
resultado, clasificacion
INTO class FROM
batalla
INNER JOIN
entrenador USING (idEntrenador)
WHERE
batalla.idEntrenador = entrenador.idEntrenador;
CASE class
WHEN 1 THEN SET dinero=250;
WHEN 2 THEN SET dinero=500;
WHEN 3 THEN SET dinero=1000;
WHEN 4 THEN SET dinero=2000;
ELSE SET dinero=0;
END CASE;
IF resultado = TRUE
THEN SET dinero = dinero * 1;
ELSE
SET dinero = dinero * -1;
END IF;
RETURN dinero;
END |
delimiter |
CREATE TRIGGER ricardoUpdate BEFORE
INSERT ON batalla
FOR EACH ROW BEGIN
UPDATE ricardo
SET perdidas=(SELECT COUNT(resultado) FROM batalla WHERE resultado=FALSE),
victorias=(SELECT COUNT(resultado) FROM batalla WHERE resultado=TRUE),
ganancias= ganancias + (SELECT CALCULARGANANCIA());
END |
I get this error with my function, Error Code 1222: The used SELECT statements have a different number of columns.
[edited]
That error usually means you have to explicitly pick the columns of your joined tables. Try changing your select in your calcularGanancia() function to something like the following (note I used aliases bat and ent):
declare class, resultado, dinero INT; /* note resultado here and into clause */
select bat.resultado, ent.clasificacion
into resultado, class
from batalla bat inner join
entrenador ent
ON bat.idEntrenador = ent.idEntrenador;

How to fix error in procedure SQL?

there is a hranimka, when it was created, an error occurs. Maybe she who struck by the ...
The stored procedure:
CREATE PROCEDURE insert_log(
IN LogType INT,
IN LogIdNote INT,
IN LogName VARCHAR,
IN LogTime TIMESTAMP,
IN logTypeCategory INT,
IN LogIdUser INT)
begin
INSERT INTO log (LogType,
LogIdNote,
LogName,
LogTime,
logTypeCategory,
LogIdUser,
LogTypeUser,
LogUrl)
SELECT LogType, LogIdNote, LogName, LogTime, logTypeCategory, LogIdUser, url.URLCategorysubscribetotype, u.UsersTypeAccount FROM users u LEFT JOIN categorysubscribetotype url ON url.CategoryTypeCategorysubscribetotype = LogType WHERE u.idUsers = LogIdUser;
end //
Error:
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 'INT LogType, INT LogIdNote, VARCHAR LogName, TIMESTAMP LogTime,
I' at line 3
I tried only change data types at params.
I think, the next code will give me a good result, but I need save result from SELECT query at variable and insert it at query Insert:
DELIMITER |
CREATE PROCEDURE insert_log(
IN pLogType INT,
IN pLogIdNote INT,
IN pLogName VARCHAR(150),
IN pLogTime TIMESTAMP,
IN plogTypeCategory INT,
IN pLogIdUser INT)
BEGIN
DECLARE user_type INT DEFAULT 0;
DECLARE url VARCHAR(250) DEFAULT;
SET user_type = (SELECT UsersTypeAccount FROM users WHERE idUsers = pLogIdUser);
SET url = (SELECT URLCategorysubscribetotype FROM categorysubscribetotype WHERE CategoryTypeCategorysubscribetotype = pLogType);
INSERT INTO log (pLogType,
pLogIdNote,
pLogName,
pLogTime,
plogTypeCategory,
pLogIdUser,
pLogTypeUser,
pLogUrl)
VALUES (
LogType,
LogIdNote,
LogName,
LogTime,
logTypeCategory,
LogIdUser,
user_type,
url
);
END |
delimiter ;
Your issue is here:
INSERT INTO log (pLogType, //wrong!
pLogIdNote,
pLogName,
pLogTime,
plogTypeCategory,
pLogIdUser,
pLogTypeUser,
pLogUrl)
You have used the parameter as column while they should be VALUES try this Query
DELIMITER //
CREATE PROCEDURE insert_log(
IN pLogType INT,
IN pLogIdNote INT,
IN pLogName VARCHAR(150),
IN pLogTime TIMESTAMP,
IN plogTypeCategory INT,
IN pLogIdUser INT)
BEGIN
DECLARE user_type INT DEFAULT 0;
DECLARE url VARCHAR(250) DEFAULT;
SET user_type = (
SELECT UsersTypeAccount
FROM users
WHERE idUsers = pLogIdUser
);
SET url = (
SELECT URLCategorysubscribetotype
FROM categorysubscribetotype
WHERE CategoryTypeCategorysubscribetotype = pLogType
);
INSERT INTO log (
`LogType`,
`LogIdNote`,
`LogName`,
`LogTime`,
`logTypeCategory`,
`LogIdUser`,
`LogIdUserType`, /*I added this*/
`LogIdUrl`, /*this one too */
)VALUES (
pLogType,
pLogIdNote,
pLogName,
pLogTime,
plogTypeCategory,
pLogIdUser,
user_type,
url
);
END //
DELIMITER ;
Please note You need to adjust this stored procedure, there was few mistakes. for example pLogTypeUser and pLogUrl are undefined and I added comments where you need to change the column name.
Your syntax is wrong. The data types come after the parameter names, the IN/OUT specifiers come before. Something like this:
CREATE PROCEDURE insert_log(
IN LogType INT,
IN LogIdNote INT,
IN LogName VARCHAR(10),
IN LogTime TIMESTAMP,
IN logTypeCategory INT,
IN LogIdUser INT)
begin
...
Edit: Also note that I added a size specifier to the VARCHAR data type, since it requires one. I guessed at 10, but you can replace that value with whatever yours is.

mysql stored procedure checking if record exists

I created the following stored procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `add_summit`(IN `assoc_code` CHAR(5), IN `assoc_name` CHAR(50), IN `reg_code` CHAR(2), IN `reg_name` CHAR(100), IN `code` CHAR(20), IN `name` CHAR(100), IN `sota_id` CHAR(5), IN `altitude_m` SMALLINT(5), IN `altitude_ft` SMALLINT(5), IN `longitude` DECIMAL(10,4), IN `latitude` DECIMAL(10,4), IN `points` TINYINT(3), IN `bonus_points` TINYINT(3), IN `valid_from` DATE, IN `valid_to` DATE)
BEGIN
declare assoc_id SMALLINT(5);
declare region_id SMALLINT(5);
declare summit_id MEDIUMINT(8);
-- ASSOCIATION check if an association with the given code and name already exists
SELECT id INTO assoc_id FROM association WHERE code = assoc_code LIMIT 1;
IF (assoc_id IS NULL) THEN
INSERT INTO association(code, name) VALUES (assoc_code, assoc_name);
set assoc_id = (select last_insert_id());
END IF;
-- REGION check if a region with the given code and name already exists
SET region_id = (SELECT id FROM region WHERE code = reg_code AND name = reg_name AND association_id = assoc_id);
IF (region_id IS NULL) THEN
INSERT INTO region(association_id, code, name) VALUES (assoc_id, reg_code, reg_name);
set region_id = (select last_insert_id());
END IF;
-- SUMMIT check if a summit with given parameters already exists
SET summit_id = (SELECT id FROM summit WHERE association_id = assoc_id AND region_id = region_id);
IF (summit_id IS NULL) THEN
INSERT INTO summit(code, name, sota_id, association_id, region_id, altitude_m, altitude_ft, longitude,
latitude, points, bonus_points, valid_from, valid_to)
VALUES (code, name, sota_id, assoc_id, region_id, altitude_m, altitude_ft, longitude, latitude,
points, bonus_points, valid_from, valid_to);
END IF;
END$$
basically, it should check if a record exists in some tables and, if it doesn't, it should insert it and use the inserted id (auto increment).
The problem is that even if the record exists (for instance in the association table), assoc_id keeps returning null and that leads to record duplication.
I'm new to stored procedures so I may be doing some stupid errors. I've been trying to debug this SP for hours but I cannot find the problem.
A newbie mistake.
I forgot to specify the table name in the field comparison and that leads to some conflicts with param names (for example the param name).
A good idea is to specify some kind of prefix for parameters (like p_) and always specify the name of the table in the SP.