This is my first procedure in MySQL and I am trying to take the ID column from my table, store it into a variable and then add 1 to it and then update the table with the new value. When I call myFirstProcedure() it sets all of the id values to 6 rather than increasing each by 1. How do I code this correctly?
DELIMITER //
CREATE PROCEDURE myFirstProcedure()
BEGIN
DECLARE IdValue INT DEFAULT 0;
SELECT COUNT(*) INTO IdValue
FROM new_table;
UPDATE new_table
SET ID = IdValue +1;
END//
DELIMITER ;
That is because you are setting all the values to the same value. You can do this by incrementing the variable in the stored procedure:
DELIMITER //
CREATE PROCEDURE myFirstProcedure()
BEGIN
DECLARE v_maxid;
SELECT COUNT(*) INTO v_maxid
FROM new_table;
UPDATE new_table
SET ID = (v_maxid := v_maxid + 1);
END//
DELIMITER ;
Note that COUNT(*) will return 0 if the table is empty, so there is no problem with NULL values.
Related
I have a MariaDB database and I have table userInfo which has a column of ipAddress and country. I want to have another column named country and automatically get the country from the ipAddress and insert it in the country column. I already imported GeoIPLite2 and already have a SQL Query but I dont know how to use make mariadb do it instead of doing it on my code.
SELECT a.country_name
FROM geoipcountries a, geoipblocks b
WHERE INET_ATON('1.2.3.4') BETWEEN network_start_integer AND network_last_integer
AND b.geoname_id = a.geoname_id
This query give me the country name.
I want the MySQL to set the value of country column in userInfo table from the output of the query above.
I already wrote this function as well:
DELIMITER $$
CREATE FUNCTION getIpCountry(ip varchar(15)) RETURNS varchar(64)
BEGIN
declare result varchar(64);
select SQL_CACHE a.country_name into result FROM geoipcountries a, geoipblocks b WHERE INET_ATON(ip) BETWEEN network_start_integer AND network_last_integer AND b.geoname_id = a.geoname_id;
if (result is null) or (result = '') then
set result := 'unknown';
end if;
return result;
END$$
DELIMITER ;
IF you want to change all county names in one goal
Do a
UPDATE userInfo SET `country`= getIpCountry(`ipAddress `);
But today we use join and not comma separated tables
DELIMITER $$
CREATE FUNCTION getIpCountry(ip varchar(15)) RETURNS varchar(64)
BEGIN
declare result varchar(64);
SELECT
a.country_name
INTO result
FROM
geoipcountries a
INNER JOIN
geoipblocks b ON b.geoname_id = a.geoname_id
WHERE
INET_ATON(ip) BETWEEN network_start_integer AND network_last_integer;
if (result is null) or (result = '') then
set result := 'unknown';
end if;
return result;
END$$
DELIMITER ;
To d that automatically you need a BEFORE INSERT TRIGGER
DELIMITER $$
CREATE TRIGGER before_userInfo_insert
BEFORE INSERT
ON userInfo FOR EACH ROW
BEGIN
SET NEW.`country`= getIpCountry(NEW.`ipAddress `);
END $$
DELIMITER ;
and a BEFORE UPDATE TRIGGER
CREATE TRIGGER before_userInfo_update
BEFORE UPDATE
ON userInfo FOR EACH ROW
BEGIN
SET NEW.`country`= getIpCountry(NEW.`ipAddress `);
END $$
DELIMITER ;
Considering you table is userInfo and you want your country column to auto populate based on ipAddress. Use CREATE TRIGGER
DELIMITER $$
CREATE TRIGGER `userinfo_before_insert` BEFORE INSERT ON `userInfo` FOR EACH ROW BEGIN
SET NEW.country = getIpCountry(NEW.ipAddress);
END $$
Note: If ipAddress can be null, so make sure you handle that in your function getIpCountry function.
Same you can on on update event too.
DELIMITER $$
CREATE TRIGGER `userinfo_before_update` BEFORE UPDATE ON `userInfo` FOR EACH ROW BEGIN
SET NEW.country = getIpCountry(NEW.ipAddress);
END $$
Now just skip country column from both INSERT and UPDATE query and make sure to include ipAddress. It would be like as follow
INSERT INTO userInfo(user_id, ipAddress) VALUES (1, '172.16.6.20');
UPDATE userInfo SET ipAddress = '172.16.6.20' WHERE user_id = 1;
I want to grab a variable (between 1-365) and use this value to create the number of empty rows in a table:
insert into tblCustomer (ID) values (), (), ();
is there an easier way to do this or is using a loop the best way?
Any help would be appreciated.
A procedure with an IN parameter is quite easy
DELIMITER $$
DROP PROCEDURE IF EXISTS test_loop$$
CREATE PROCEDURE test_loop(IN number INT)
BEGIN
DECLARE x INT(11);
SET x = 1;
WHILE x <= number DO
INSERT INTO tblCustomer(id) VALUES('');
SET x = x + 1;
END WHILE;
END$$
DELIMITER ;
How to use it
CALL test_loop(20);
I Have a Database in mysql, i have a principal table that use a column name cedula VARCHAR (50), the column have characters, but i want to change it with a consecutive number. I tried with this:
SET #a:=1;
UPDATE bdpiiad2.tpersona
SET cedula=(CONVERT(#a:=#a+1, CHAR(50)))
But i have 2 problems, first doesn't change, and second I'm not sure if change the other ids in the others tables that have a reference.
try using this
SET #a:=1;
UPDATE bdpiiad2.tpersona
SET cedula=(CAST(#a:=#a+1 as CHAR));
to update all you need to create a procedure like this
DELIMITER $$
USE `bdpiiad2`$$
DROP PROCEDURE IF EXISTS bdpiiad2.`up`$$
CREATE PROCEDURE `up`()
BEGIN
DECLARE max_cnt INT;
DECLARE cnt INT;
SET cnt=1;
UPDATE bdpiiad2.tpersona SET cedula='0';
SELECT COUNT(*) INTO max_cnt FROM bdpiiad2.tpersona;
WHILE cnt<=max_cnt DO
UPDATE bdpiiad2.tpersona
SET cedula=(CAST(cnt AS CHAR))
WHERE cedula='0' LIMIT 1;
SET cnt=cnt+1;
END WHILE;
END$$
DELIMITER ;
and then call it like this
CALL bdpiiad2.up();
I am running a stored procedure. The issue seems to be that it will go into the if statement. Also for some reason or another regardless of how many selects I use it will only return the first. I've copied this from another stored procedure that works like a charm, but this one just won't go. Any ideas?
DROP PROCEDURE IF EXISTS genSelPriceTier;
DELIMITER $$
CREATE PROCEDURE genSelPriceTier(tier_id INT, default_id INT)
BEGIN
DECLARE rowCount INT DEFAULT 0;
SELECT * FROM price_tier WHERE price_tier_id = tier_id;
SET rowCount = FOUND_ROWS();
IF rowCount < 1 THEN
SELECT * FROM price_tier WHERE price_tier_id = default_id;
END IF;
END$$
DELIMITER ;
There is a bug reported related to the usage of FOUND_ROWS(). So, I recommend using Count(*) for the number of rows returned. Something like the following should work.
DROP PROCEDURE IF EXISTS genSelPriceTier;
DELIMITER $$
CREATE PROCEDURE genSelPriceTier(tier_id INT, default_id INT)
BEGIN
DECLARE rowCount INT DEFAULT 0;
SELECT COUNT(*) INTO rowCount FROM price_tier WHERE price_tier_id = tier_id
IF rowCount < 1 THEN
SELECT * FROM price_tier WHERE price_tier_id = default_id;
END IF;
END$$
DELIMITER ;
How do you declare variable and set a value which is a return from a query on them later.
Sample Stored Procedure:
DELIMITER $$
CREATE PROCEDURE `sampledb`.`SetVariableEx`()
BEGIN
-- declare variable
DECLARE xVarA INT;
DECLARE xVarB INT;
-- in this line, i would like to set a value on xVarA which is a COUNT
-- of record from table SINGLETABLE
-- i am getting error on this line.
SELECT xVarA := COUNT(*) FROM SingleTable;
-- the value of xVarA is added by 1 and set it to xVarB
SET xVarB = xVarA + 1;
-- insert the value of xVarB to the table SINGLETABLE
INSERT INTO SingleTable(SingleColumn) VALUES (xVarB);
-- lastly, display all records.
SELECT * FROM SingleTable;
END$$
DELIMITER ;
how would i do that?
Try the following:
SET xVarA := (SELECT COUNT(*) FROM SingleTable);
However, for this example, have you considered using an auto auto-incrementing value, rather than managing the value yourself?